Remove BPA operator
[icn.git] / cmd / bpa-restapi-agent / internal / storage / minio.go
1 package storage
2
3 import (
4     "github.com/minio/minio-go/v6"
5     "bpa-restapi-agent/internal/config"
6
7     "log"
8     "os"
9 )
10
11 type MinIOInfo struct {
12         minioC         *minio.Client            `json:"minio client"`
13 }
14
15 // Initialize the MinIO server, create buckets
16 func Initialize() (MinIOInfo, error) {
17         endpoint := config.GetConfiguration().MinIOAddress + ":" + config.GetConfiguration().MinIOPort
18     accessKeyID := config.GetConfiguration().AccessKeyID
19     secretAccessKey := config.GetConfiguration().SecretAccessKey
20     useSSL := false
21
22     minioInfo := MinIOInfo{}
23     // Initialize minio client object.
24     minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, useSSL)
25     if err != nil {
26         log.Fatalln(err)
27         return minioInfo, err
28     }
29
30     // Make a new bucket.
31     bucketNames := []string{"binary", "container", "operatingsystem"}
32     location := "us-west-1"
33
34     for _, bucketName := range bucketNames {
35         err := minioClient.MakeBucket(bucketName, location)
36         if err != nil {
37             // Check to see if we already own this bucket (which happens if you run this twice)
38             exists, errBucketExists := minioClient.BucketExists(bucketName)
39             if errBucketExists == nil && exists {
40                 log.Printf("We already own %s\n", bucketName)
41             } else {
42                 log.Fatalln(err)
43                 return minioInfo, err
44             }
45         } else {
46             log.Printf("Successfully created %s\n", bucketName)
47         }
48     }
49
50     minioInfo.minioC = minioClient
51     return minioInfo, nil
52 }
53
54 func (m MinIOInfo) PutImage(bucketName string, objName string, localPath string) (int64, error) {
55
56     //contentType := "multipart/form-data"
57     contentType := "application/octet-stream"
58
59     // Upload the zip file with FPutObject
60     n, err := m.minioC.FPutObject(bucketName, objName, localPath, minio.PutObjectOptions{ContentType:contentType})
61     if err != nil {
62                 log.Fatalln(err)
63                 return n, err
64     }
65
66     fileInfo, _ := os.Stat(localPath)
67     fileSize := fileInfo.Size()
68
69     if n != int64(fileSize) {
70         log.Printf("FPutObject failed %s of size %d\n", objName, n)
71         return n, err
72     }
73
74         log.Printf("Successfully uploaded %s of size %d\n", objName, n)
75         return n, nil
76 }
77
78 func (m MinIOInfo) PatchImage(bucketName string, objName string, localPath string, offset int64, objSize int64) (int64, error) {
79
80     var n = int64(0)
81
82     tempFile, err := os.Open(localPath)
83     if err != nil {
84         log.Fatalln(err)
85         return n, err
86     }
87
88     defer tempFile.Close()
89
90     if _, err := tempFile.Seek(offset, 0); err != nil {
91         log.Printf("PatchImage seek %s failed: %s", tempFile.Name(), err)
92         return n, err
93     }
94
95     objInfo, err := m.minioC.StatObject(bucketName, objName, minio.StatObjectOptions{})
96     var objHealthy = true
97     if err != nil {
98         objHealthy = false
99     } else if objInfo.Size != offset || objInfo.Size == 0 {
100         objHealthy = false
101     }
102
103     var objNameTemp = objName
104     if objHealthy {
105         objNameTemp = objName + ".tmp"
106     }
107
108     contentType := "application/octet-stream"
109     n, err = m.minioC.PutObject(bucketName, objNameTemp, tempFile, objSize, minio.PutObjectOptions{ContentType:contentType})
110     if err != nil {
111         log.Fatalln(err)
112         return n, err
113     }
114
115     if n != objSize {
116         log.Printf("PatchImage PutObject %s failed with bytes: %d", tempFile.Name(), n)
117         return n, err
118     }
119
120     if objHealthy {
121         src1 := minio.NewSourceInfo(bucketName, objName, nil)
122         src2 := minio.NewSourceInfo(bucketName, objNameTemp, nil)
123         srcs := []minio.SourceInfo{src1, src2}
124
125         dst, err := minio.NewDestinationInfo(bucketName, objName, nil, nil)
126         if err != nil {
127             log.Printf("NewDestinationInfo failed", err)
128             return n, err
129         }
130
131         // There is issue, the last src should be the smallest obj size
132         err = m.minioC.ComposeObject(dst, srcs)
133         if err != nil {
134             log.Printf("ComposeObject failed", err)
135             return n, err
136         }
137     }
138
139     log.Printf("Successfully PatchImage %s of size %d\n", objName, n)
140     return n, nil
141 }
142
143 func (m MinIOInfo) DeleteImage(bucketName string, objName string) (error) {
144
145     err := m.minioC.RemoveObject(bucketName, objName)
146     if err != nil {
147         log.Printf("MinIO Remove object %s failed\n", bucketName)
148         return err
149     }
150
151     return nil
152 }
153
154 func (m MinIOInfo) CleanupImages(bucketName string) (error) {
155     // create a done channel to control 'ListObjectsV2' go routine.
156     doneCh := make(chan struct{})
157     defer close(doneCh)
158
159     for objCh := range m.minioC.ListObjectsV2(bucketName, "", true, doneCh) {
160         if objCh.Err != nil {
161             return objCh.Err
162         }
163         if objCh.Key != "" {
164             err := m.minioC.RemoveObject(bucketName, objCh.Key)
165             if err != nil {
166                 return err
167             }
168         }
169     }
170     for objPartInfo := range m.minioC.ListIncompleteUploads(bucketName, "", true, doneCh) {
171         if objPartInfo.Err != nil {
172             return objPartInfo.Err
173         }
174         if objPartInfo.Key != "" {
175             err := m.minioC.RemoveIncompleteUpload(bucketName, objPartInfo.Key)
176             if err != nil {
177                 return err
178             }
179         }
180     }
181
182     return nil
183 }