4 "bpa-restapi-agent/internal/db"
10 pkgerrors "github.com/pkg/errors"
13 // Image contains the parameters needed for Image information
15 Owner string `json:"owner"`
16 ClusterName string `json:"cluster_name"`
17 Type string `json:"type"`
18 ImageName string `json:"image_name"`
19 ImageOffset *int `json:"image_offset"`
20 ImageLength int `json:"image_length"`
21 UploadComplete *bool `json:"upload_complete"`
22 Description ImageRecordList `json:"description"`
25 type ImageRecordList struct {
26 ImageRecords []map[string]string `json:"image_records"`
29 // ImageKey is the key structure that is used in the database
30 type ImageKey struct {
31 ImageName string `json:"image_name"`
34 // We will use json marshalling to convert to string to
35 // preserve the underlying structure.
36 func (dk ImageKey) String() string {
37 out, err := json.Marshal(dk)
45 // ImageManager is an interface that exposes the Image functionality
46 type ImageManager interface {
47 Create(c Image) (Image, error)
48 Get(imageName string) (Image, error)
49 Delete(imageName string) error
50 Update(imageName string, c Image) (Image, error)
51 GetImageRecordByName(imgname, imageName string) (map[string]string, error)
52 GetDirPath(imageName string) (string, string, error)
55 // Interface to aid unit test by mocking third party packages
56 type Utility interface {
57 GetCurrentUser() (*user.User, error)
58 DBCreate(storeName string, key ImageKey, meta string, c Image) error
59 DBRead(storeName string, key ImageKey, meta string) ([]byte, error)
60 DBUnmarshal(value []byte) (Image, error)
61 GetPath(user *user.User, imageName string, storeName string) (string, string)
62 DBDelete(storeName string, key ImageKey, meta string) error
63 DBUpdate(storeName string, key ImageKey, tagMeta string, c Image) error
66 // ImageClient implements the ImageManager
67 // It will also be used to maintain some localized state
68 type ImageClient struct {
74 type DBService struct {
77 // To Do - Fix repetition in
78 // NewImageClient returns an instance of the ImageClient
79 // which implements the ImageManager
80 func NewBinaryImageClient() *ImageClient {
81 service := DBService{}
84 storeName: "binary_images",
89 func NewContainerImageClient() *ImageClient {
90 service := DBService{}
93 storeName: "container_images",
98 func NewOSImageClient() *ImageClient {
99 service := DBService{}
102 storeName: "os_images",
107 // Create an entry for the Image resource in the database`
108 func (v *ImageClient) Create(c Image) (Image, error) {
109 //Construct composite key consisting of name
111 ImageName: c.ImageName,
114 //Check if this Image already exists
115 _, err := v.Get(c.ImageName)
117 return Image{}, pkgerrors.New("Image already exists")
120 err = v.util.DBCreate(v.storeName, key, v.tagMeta, c)
122 return Image{}, pkgerrors.Wrap(err, "Creating DB Entry")
125 err = v.CreateFile(c)
127 return Image{}, pkgerrors.Wrap(err, "Creating File in FS")
133 func (d DBService) DBCreate(storeName string, key ImageKey, meta string, c Image) error {
135 //Construct composite key consisting of name
136 err := db.DBconn.Create(storeName, key, meta, c)
138 return pkgerrors.Wrap(err, "Creating DB Entry")
146 func (v *ImageClient) CreateFile(c Image) error {
147 filePath, dirPath, err := v.GetDirPath(c.ImageName)
149 return pkgerrors.Wrap(err, "Get file path")
151 err = os.MkdirAll(dirPath, 0744)
153 return pkgerrors.Wrap(err, "Make image directory")
155 file, err := os.Create(filePath)
157 return pkgerrors.Wrap(err, "Create image file")
164 // Get returns Image for corresponding to name
165 func (v *ImageClient) Get(imageName string) (Image, error) {
167 //Construct the composite key to select the entry
170 // ClusterName: clusterName,
171 ImageName: imageName,
174 value, err := v.util.DBRead(v.storeName, key, v.tagMeta)
176 return Image{}, pkgerrors.Wrap(err, "Get Image")
179 //value is a byte array
181 c, err := v.util.DBUnmarshal(value)
183 return Image{}, pkgerrors.Wrap(err, "Unmarshaling Value")
188 return Image{}, pkgerrors.New("Error getting Connection")
191 func (d DBService) DBRead(storeName string, key ImageKey, meta string) ([]byte, error) {
192 value, err := db.DBconn.Read(storeName, key, meta)
194 return []byte{}, pkgerrors.Wrap(err, "Get Image")
200 func (d DBService) DBUnmarshal(value []byte) (Image, error) {
202 err := db.DBconn.Unmarshal(value, &c)
204 return Image{}, pkgerrors.Wrap(err, "Unmarshaling Value")
210 func (v *ImageClient) GetImageRecordByName(imgName string,
211 imageRecordName string) (map[string]string, error) {
213 img, err := v.Get(imgName)
215 return nil, pkgerrors.Wrap(err, "Error getting image")
218 for _, value := range img.Description.ImageRecords {
219 if imageRecordName == value["image_record_name"] {
224 return nil, pkgerrors.New("Image record " + imageRecordName + " not found")
227 func (v *ImageClient) GetDirPath(imageName string) (string, string, error) {
228 u, err := v.util.GetCurrentUser()
229 filePath, dirPath := v.util.GetPath(u, imageName, v.storeName)
231 return filePath, dirPath, err
234 // Delete the Image from database
235 func (v *ImageClient) Delete(imageName string) error {
237 //Construct the composite key to select the entry
240 // ClusterName: clusterName,
241 ImageName: imageName,
243 err := v.util.DBDelete(v.storeName, key, v.tagMeta)
245 //Delete image from FS
246 filePath, _, err := v.GetDirPath(imageName)
248 return pkgerrors.Wrap(err, "Get file path")
250 err = os.Remove(filePath)
252 return pkgerrors.Wrap(err, "Delete image file")
258 func (d DBService) DBDelete(storeName string, key ImageKey, tagMeta string) error {
259 err := db.DBconn.Delete(storeName, key, tagMeta)
261 return pkgerrors.Wrap(err, "Delete Image")
267 // Update an entry for the image in the database
268 func (v *ImageClient) Update(imageName string, c Image) (Image, error) {
271 ImageName: imageName,
274 //Check if this Image exists
275 _, err := v.Get(imageName)
277 return Image{}, pkgerrors.New("Update Error - Image doesn't exist")
280 err = v.util.DBUpdate(v.storeName, key, v.tagMeta, c)
285 func (d DBService) DBUpdate(storeName string, key ImageKey, tagMeta string, c Image) error {
286 err := db.DBconn.Update(storeName, key, tagMeta, c)
288 return pkgerrors.Wrap(err, "Updating DB Entry")
294 // Define GetCurrentUser
295 func (d DBService) GetCurrentUser() (*user.User, error) {
296 u, err := user.Current()
298 return nil, pkgerrors.Wrap(err, "Current user")
304 func (d DBService) GetPath(user *user.User, imageName string, storeName string) (string, string) {
306 dirPath := path.Join(home, "images", storeName)
307 filePath := path.Join(dirPath, imageName)
309 return filePath, dirPath