X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=cmd%2Fbpa-restapi-agent%2Finternal%2Fapp%2Fimage.go;h=2c117a33138462401eeed15600a1e2abc737b9ed;hb=refs%2Fchanges%2F53%2F1753%2F21;hp=a1beed80267573c770cce037336cbb917db9dc29;hpb=aaaa10a54a1d7ec0a1c4e3a675113ec9656c0e1a;p=icn.git diff --git a/cmd/bpa-restapi-agent/internal/app/image.go b/cmd/bpa-restapi-agent/internal/app/image.go index a1beed8..2c117a3 100644 --- a/cmd/bpa-restapi-agent/internal/app/image.go +++ b/cmd/bpa-restapi-agent/internal/app/image.go @@ -1,26 +1,25 @@ package app import ( - //"encoding/base64" - "encoding/json" - //"io/ioutil" - "bpa-restapi-agent/internal/db" + "encoding/json" + "os" + "os/user" + "path" pkgerrors "github.com/pkg/errors" ) // Image contains the parameters needed for Image information type Image struct { - Owner string `json:"owner"` - ClusterName string `json:"cluster_name"` - Type string `json:"type"` - ImageName string `json:"image_name"` - Config string `json:"config"` - ImageOffset *int `json:"image_offset"` - ImageLength int `json:"image_length"` - UploadComplete *bool `json:"upload_complete"` - Description ImageRecordList `json:"description"` + Owner string `json:"owner"` + ClusterName string `json:"cluster_name"` + Type string `json:"type"` + ImageName string `json:"image_name"` + ImageOffset *int `json:"image_offset"` + ImageLength int `json:"image_length"` + UploadComplete *bool `json:"upload_complete"` + Description ImageRecordList `json:"description"` } type ImageRecordList struct { @@ -29,9 +28,7 @@ type ImageRecordList struct { // ImageKey is the key structure that is used in the database type ImageKey struct { - // Owner string `json:"owner"` - // ClusterName string `json:"cluster_name"` - ImageName string `json:"image_name"` + ImageName string `json:"image_name"` } // We will use json marshalling to convert to string to @@ -52,46 +49,68 @@ type ImageManager interface { Delete(imageName string) error Update(imageName string, c Image) (Image, error) GetImageRecordByName(imgname, imageName string) (map[string]string, error) + GetDirPath(imageName string) (string, string, error) +} + +// Interface to aid unit test by mocking third party packages +type Utility interface { + GetCurrentUser() (*user.User, error) + DBCreate(storeName string, key ImageKey, meta string, c Image) error + DBRead(storeName string, key ImageKey, meta string) ([]byte, error) + DBUnmarshal(value []byte) (Image, error) + OSMakeDir(dirpath string, perm int) error + OSCreateFile(filePath string) error + GetPath(user *user.User, imageName string, storeName string) (string, string) + DBDelete(storeName string, key ImageKey, meta string) error + OSRemove(filePath string) error + DBUpdate(storeName string, key ImageKey, tagMeta string, c Image) error } // ImageClient implements the ImageManager // It will also be used to maintain some localized state type ImageClient struct { + util Utility storeName string tagMeta string } +type DBService struct { +} + // To Do - Fix repetition in // NewImageClient returns an instance of the ImageClient // which implements the ImageManager func NewBinaryImageClient() *ImageClient { + service := DBService{} return &ImageClient{ - storeName: "binary_image", + util: service, + storeName: "binary_images", tagMeta: "metadata", } } func NewContainerImageClient() *ImageClient { + service := DBService{} return &ImageClient{ - storeName: "container_image", + util: service, + storeName: "container_images", tagMeta: "metadata", } } func NewOSImageClient() *ImageClient { + service := DBService{} return &ImageClient{ - storeName: "os_image", + util: service, + storeName: "os_images", tagMeta: "metadata", } } // Create an entry for the Image resource in the database` func (v *ImageClient) Create(c Image) (Image, error) { - //Construct composite key consisting of name key := ImageKey{ - // Owner: c.Owner, - // ClusterName: c.ClusterName, ImageName: c.ImageName, } @@ -101,14 +120,67 @@ func (v *ImageClient) Create(c Image) (Image, error) { return Image{}, pkgerrors.New("Image already exists") } - err = db.DBconn.Create(v.storeName, key, v.tagMeta, c) + err = v.util.DBCreate(v.storeName, key, v.tagMeta, c) if err != nil { return Image{}, pkgerrors.Wrap(err, "Creating DB Entry") } + err = v.CreateFile(c) + if err != nil { + return Image{}, pkgerrors.Wrap(err, "Creating File in FS") + } + return c, nil } +func (d DBService) DBCreate(storeName string, key ImageKey, meta string, c Image) error { + + //Construct composite key consisting of name + err := db.DBconn.Create(storeName, key, meta, c) + if err != nil { + return pkgerrors.Wrap(err, "Creating DB Entry") + } + + return nil +} + +// Create file + +func (v *ImageClient) CreateFile(c Image) error { + filePath, dirPath, err := v.GetDirPath(c.ImageName) + if err != nil { + return pkgerrors.Wrap(err, "Get file path") + } + err = v.util.OSMakeDir(dirPath, 0744) + if err != nil { + return pkgerrors.Wrap(err, "Make image directory") + } + err = v.util.OSCreateFile(filePath) + if err != nil { + return pkgerrors.Wrap(err, "Create image file") + } + + return nil +} + +func (d DBService) OSMakeDir(dirPath string, perm int) error { + err := os.MkdirAll(dirPath, 0744) + if err != nil { + return pkgerrors.Wrap(err, "Make image directory") + } + return nil +} + +func (d DBService) OSCreateFile(filePath string) error { + file1, err := os.Create(filePath) + if err != nil { + return pkgerrors.Wrap(err, "Create image file") + } + defer file1.Close() + + return nil +} + // Get returns Image for corresponding to name func (v *ImageClient) Get(imageName string) (Image, error) { @@ -119,15 +191,14 @@ func (v *ImageClient) Get(imageName string) (Image, error) { ImageName: imageName, } - value, err := db.DBconn.Read(v.storeName, key, v.tagMeta) + value, err := v.util.DBRead(v.storeName, key, v.tagMeta) if err != nil { return Image{}, pkgerrors.Wrap(err, "Get Image") } //value is a byte array if value != nil { - c := Image{} - err = db.DBconn.Unmarshal(value, &c) + c, err := v.util.DBUnmarshal(value) if err != nil { return Image{}, pkgerrors.Wrap(err, "Unmarshaling Value") } @@ -137,6 +208,25 @@ func (v *ImageClient) Get(imageName string) (Image, error) { return Image{}, pkgerrors.New("Error getting Connection") } +func (d DBService) DBRead(storeName string, key ImageKey, meta string) ([]byte, error) { + value, err := db.DBconn.Read(storeName, key, meta) + if err != nil { + return []byte{}, pkgerrors.Wrap(err, "Get Image") + } + + return value, nil +} + +func (d DBService) DBUnmarshal(value []byte) (Image, error) { + c := Image{} + err := db.DBconn.Unmarshal(value, &c) + if err != nil { + return Image{}, pkgerrors.Wrap(err, "Unmarshaling Value") + } + + return c, nil +} + func (v *ImageClient) GetImageRecordByName(imgName string, imageRecordName string) (map[string]string, error) { @@ -154,6 +244,13 @@ func (v *ImageClient) GetImageRecordByName(imgName string, return nil, pkgerrors.New("Image record " + imageRecordName + " not found") } +func (v *ImageClient) GetDirPath(imageName string) (string, string, error) { + u, err := v.util.GetCurrentUser() + filePath, dirPath := v.util.GetPath(u, imageName, v.storeName) + + return filePath, dirPath, err +} + // Delete the Image from database func (v *ImageClient) Delete(imageName string) error { @@ -163,10 +260,33 @@ func (v *ImageClient) Delete(imageName string) error { // ClusterName: clusterName, ImageName: imageName, } - err := db.DBconn.Delete(v.storeName, key, v.tagMeta) + err := v.util.DBDelete(v.storeName, key, v.tagMeta) + + //Delete image from FS + filePath, _, err := v.GetDirPath(imageName) + if err != nil { + return pkgerrors.Wrap(err, "Get file path") + } + err = v.util.OSRemove(filePath) + + return nil +} + +func (d DBService) OSRemove(filePath string) error { + err := os.Remove(filePath) + if err != nil { + return pkgerrors.Wrap(err, "Delete image file") + } + + return nil +} + +func (d DBService) DBDelete(storeName string, key ImageKey, tagMeta string) error { + err := db.DBconn.Delete(storeName, key, tagMeta) if err != nil { return pkgerrors.Wrap(err, "Delete Image") } + return nil } @@ -174,8 +294,6 @@ func (v *ImageClient) Delete(imageName string) error { func (v *ImageClient) Update(imageName string, c Image) (Image, error) { key := ImageKey{ - // Owner: c.Owner, - // ClusterName: c.ClusterName, ImageName: imageName, } @@ -185,10 +303,34 @@ func (v *ImageClient) Update(imageName string, c Image) (Image, error) { return Image{}, pkgerrors.New("Update Error - Image doesn't exist") } - err = db.DBconn.Update(v.storeName, key, v.tagMeta, c) + err = v.util.DBUpdate(v.storeName, key, v.tagMeta, c) + + return c, nil +} + +func (d DBService) DBUpdate(storeName string, key ImageKey, tagMeta string, c Image) error { + err := db.DBconn.Update(storeName, key, tagMeta, c) + if err != nil { + return pkgerrors.Wrap(err, "Updating DB Entry") + } + + return nil +} + +// Define GetCurrentUser +func (d DBService) GetCurrentUser() (*user.User, error) { + u, err := user.Current() if err != nil { - return Image{}, pkgerrors.Wrap(err, "Updating DB Entry") + return nil, pkgerrors.Wrap(err, "Current user") } - return c, nil + return u, nil +} + +func (d DBService) GetPath(user *user.User, imageName string, storeName string) (string, string) { + home := user.HomeDir + dirPath := path.Join(home, "images", storeName) + filePath := path.Join(dirPath, imageName) + + return filePath, dirPath }