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 OSMakeDir(dirpath string, perm int) error
62 OSCreateFile(filePath string) error
63 GetPath(user *user.User, imageName string, storeName string) (string, string)
64 DBDelete(storeName string, key ImageKey, meta string) error
65 OSRemove(filePath string) error
66 DBUpdate(storeName string, key ImageKey, tagMeta string, c Image) error
69 // ImageClient implements the ImageManager
70 // It will also be used to maintain some localized state
71 type ImageClient struct {
77 type DBService struct {
80 // To Do - Fix repetition in
81 // NewImageClient returns an instance of the ImageClient
82 // which implements the ImageManager
83 func NewBinaryImageClient() *ImageClient {
84 service := DBService{}
87 storeName: "binary_images",
92 func NewContainerImageClient() *ImageClient {
93 service := DBService{}
96 storeName: "container_images",
101 func NewOSImageClient() *ImageClient {
102 service := DBService{}
105 storeName: "os_images",
110 // Create an entry for the Image resource in the database`
111 func (v *ImageClient) Create(c Image) (Image, error) {
112 //Construct composite key consisting of name
114 ImageName: c.ImageName,
117 //Check if this Image already exists
118 _, err := v.Get(c.ImageName)
120 return Image{}, pkgerrors.New("Image already exists")
123 err = v.util.DBCreate(v.storeName, key, v.tagMeta, c)
125 return Image{}, pkgerrors.Wrap(err, "Creating DB Entry")
128 err = v.CreateFile(c)
130 return Image{}, pkgerrors.Wrap(err, "Creating File in FS")
136 func (d DBService) DBCreate(storeName string, key ImageKey, meta string, c Image) error {
138 //Construct composite key consisting of name
139 err := db.DBconn.Create(storeName, key, meta, c)
141 return pkgerrors.Wrap(err, "Creating DB Entry")
149 func (v *ImageClient) CreateFile(c Image) error {
150 filePath, dirPath, err := v.GetDirPath(c.ImageName)
152 return pkgerrors.Wrap(err, "Get file path")
154 err = v.util.OSMakeDir(dirPath, 0744)
156 return pkgerrors.Wrap(err, "Make image directory")
158 err = v.util.OSCreateFile(filePath)
160 return pkgerrors.Wrap(err, "Create image file")
166 func (d DBService) OSMakeDir(dirPath string, perm int) error {
167 err := os.MkdirAll(dirPath, 0744)
169 return pkgerrors.Wrap(err, "Make image directory")
174 func (d DBService) OSCreateFile(filePath string) error {
175 file1, err := os.Create(filePath)
177 return pkgerrors.Wrap(err, "Create image file")
184 // Get returns Image for corresponding to name
185 func (v *ImageClient) Get(imageName string) (Image, error) {
187 //Construct the composite key to select the entry
190 // ClusterName: clusterName,
191 ImageName: imageName,
194 value, err := v.util.DBRead(v.storeName, key, v.tagMeta)
196 return Image{}, pkgerrors.Wrap(err, "Get Image")
199 //value is a byte array
201 c, err := v.util.DBUnmarshal(value)
203 return Image{}, pkgerrors.Wrap(err, "Unmarshaling Value")
208 return Image{}, pkgerrors.New("Error getting Connection")
211 func (d DBService) DBRead(storeName string, key ImageKey, meta string) ([]byte, error) {
212 value, err := db.DBconn.Read(storeName, key, meta)
214 return []byte{}, pkgerrors.Wrap(err, "Get Image")
220 func (d DBService) DBUnmarshal(value []byte) (Image, error) {
222 err := db.DBconn.Unmarshal(value, &c)
224 return Image{}, pkgerrors.Wrap(err, "Unmarshaling Value")
230 func (v *ImageClient) GetImageRecordByName(imgName string,
231 imageRecordName string) (map[string]string, error) {
233 img, err := v.Get(imgName)
235 return nil, pkgerrors.Wrap(err, "Error getting image")
238 for _, value := range img.Description.ImageRecords {
239 if imageRecordName == value["image_record_name"] {
244 return nil, pkgerrors.New("Image record " + imageRecordName + " not found")
247 func (v *ImageClient) GetDirPath(imageName string) (string, string, error) {
248 u, err := v.util.GetCurrentUser()
249 filePath, dirPath := v.util.GetPath(u, imageName, v.storeName)
251 return filePath, dirPath, err
254 // Delete the Image from database
255 func (v *ImageClient) Delete(imageName string) error {
257 //Construct the composite key to select the entry
260 // ClusterName: clusterName,
261 ImageName: imageName,
263 err := v.util.DBDelete(v.storeName, key, v.tagMeta)
265 //Delete image from FS
266 filePath, _, err := v.GetDirPath(imageName)
268 return pkgerrors.Wrap(err, "Get file path")
270 err = v.util.OSRemove(filePath)
275 func (d DBService) OSRemove(filePath string) error {
276 err := os.Remove(filePath)
278 return pkgerrors.Wrap(err, "Delete image file")
284 func (d DBService) DBDelete(storeName string, key ImageKey, tagMeta string) error {
285 err := db.DBconn.Delete(storeName, key, tagMeta)
287 return pkgerrors.Wrap(err, "Delete Image")
293 // Update an entry for the image in the database
294 func (v *ImageClient) Update(imageName string, c Image) (Image, error) {
297 ImageName: imageName,
300 //Check if this Image exists
301 _, err := v.Get(imageName)
303 return Image{}, pkgerrors.New("Update Error - Image doesn't exist")
306 err = v.util.DBUpdate(v.storeName, key, v.tagMeta, c)
311 func (d DBService) DBUpdate(storeName string, key ImageKey, tagMeta string, c Image) error {
312 err := db.DBconn.Update(storeName, key, tagMeta, c)
314 return pkgerrors.Wrap(err, "Updating DB Entry")
320 // Define GetCurrentUser
321 func (d DBService) GetCurrentUser() (*user.User, error) {
322 u, err := user.Current()
324 return nil, pkgerrors.Wrap(err, "Current user")
330 func (d DBService) GetPath(user *user.User, imageName string, storeName string) (string, string) {
332 dirPath := path.Join(home, "images", storeName)
333 filePath := path.Join(dirPath, imageName)
335 return filePath, dirPath