Adding Initial ICN API Service
[icn.git] / cmd / bpa-restapi-agent / internal / app / image.go
diff --git a/cmd/bpa-restapi-agent/internal/app/image.go b/cmd/bpa-restapi-agent/internal/app/image.go
new file mode 100644 (file)
index 0000000..a1beed8
--- /dev/null
@@ -0,0 +1,194 @@
+package app
+
+import (
+  //"encoding/base64"
+       "encoding/json"
+       //"io/ioutil"
+
+       "bpa-restapi-agent/internal/db"
+
+       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"`
+}
+
+type ImageRecordList struct {
+       ImageRecords []map[string]string `json:"image_records"`
+}
+
+// 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"`
+}
+
+// We will use json marshalling to convert to string to
+// preserve the underlying structure.
+func (dk ImageKey) String() string {
+       out, err := json.Marshal(dk)
+       if err != nil {
+               return ""
+       }
+
+       return string(out)
+}
+
+// ImageManager is an interface that exposes the Image functionality
+type ImageManager interface {
+       Create(c Image) (Image, error)
+       Get(imageName string) (Image, error)
+       Delete(imageName string) error
+       Update(imageName string, c Image) (Image, error)
+       GetImageRecordByName(imgname, imageName string) (map[string]string, error)
+}
+
+// ImageClient implements the ImageManager
+// It will also be used to maintain some localized state
+type ImageClient struct {
+       storeName string
+       tagMeta   string
+}
+
+// To Do - Fix repetition in
+// NewImageClient returns an instance of the ImageClient
+// which implements the ImageManager
+func NewBinaryImageClient() *ImageClient {
+       return &ImageClient{
+               storeName: "binary_image",
+               tagMeta:   "metadata",
+       }
+}
+
+func NewContainerImageClient() *ImageClient {
+       return &ImageClient{
+               storeName: "container_image",
+               tagMeta:   "metadata",
+       }
+}
+
+func NewOSImageClient() *ImageClient {
+       return &ImageClient{
+               storeName: "os_image",
+               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,
+       }
+
+       //Check if this Image already exists
+       _, err := v.Get(c.ImageName)
+       if err == nil {
+               return Image{}, pkgerrors.New("Image already exists")
+       }
+
+       err = db.DBconn.Create(v.storeName, key, v.tagMeta, c)
+       if err != nil {
+               return Image{}, pkgerrors.Wrap(err, "Creating DB Entry")
+       }
+
+       return c, nil
+}
+
+// Get returns Image for corresponding to name
+func (v *ImageClient) Get(imageName string) (Image, error) {
+
+       //Construct the composite key to select the entry
+       key := ImageKey{
+               // Owner:       ownerName,
+               // ClusterName: clusterName,
+               ImageName: imageName,
+       }
+
+       value, err := db.DBconn.Read(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)
+               if err != nil {
+                       return Image{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+               }
+               return c, nil
+       }
+
+       return Image{}, pkgerrors.New("Error getting Connection")
+}
+
+func (v *ImageClient) GetImageRecordByName(imgName string,
+       imageRecordName string) (map[string]string, error) {
+
+       img, err := v.Get(imgName)
+       if err != nil {
+               return nil, pkgerrors.Wrap(err, "Error getting image")
+       }
+
+       for _, value := range img.Description.ImageRecords {
+               if imageRecordName == value["image_record_name"] {
+                       return value, nil
+               }
+       }
+
+       return nil, pkgerrors.New("Image record " + imageRecordName + " not found")
+}
+
+// Delete the Image from database
+func (v *ImageClient) Delete(imageName string) error {
+
+       //Construct the composite key to select the entry
+       key := ImageKey{
+               // Owner:       ownerName,
+               // ClusterName: clusterName,
+               ImageName: imageName,
+       }
+       err := db.DBconn.Delete(v.storeName, key, v.tagMeta)
+       if err != nil {
+               return pkgerrors.Wrap(err, "Delete Image")
+       }
+       return nil
+}
+
+// Update an entry for the image in the database
+func (v *ImageClient) Update(imageName string, c Image) (Image, error) {
+
+       key := ImageKey{
+               // Owner:       c.Owner,
+               // ClusterName: c.ClusterName,
+               ImageName: imageName,
+       }
+
+       //Check if this Image exists
+       _, err := v.Get(imageName)
+       if err != nil {
+               return Image{}, pkgerrors.New("Update Error - Image doesn't exist")
+       }
+
+       err = db.DBconn.Update(v.storeName, key, v.tagMeta, c)
+       if err != nil {
+               return Image{}, pkgerrors.Wrap(err, "Updating DB Entry")
+       }
+
+       return c, nil
+}