Adding Initial ICN API Service
[icn.git] / cmd / bpa-restapi-agent / internal / app / image.go
1 package app
2
3 import (
4   //"encoding/base64"
5         "encoding/json"
6         //"io/ioutil"
7
8         "bpa-restapi-agent/internal/db"
9
10         pkgerrors "github.com/pkg/errors"
11 )
12
13 // Image contains the parameters needed for Image information
14 type Image struct {
15         Owner                           string               `json:"owner"`
16         ClusterName         string               `json:"cluster_name"`
17         Type                string               `json:"type"`
18         ImageName           string               `json:"image_name"`
19         Config                                                  string                                                   `json:"config"`
20         ImageOffset                                     *int                                                       `json:"image_offset"`
21         ImageLength                                     int                                                                      `json:"image_length"`
22         UploadComplete                  *bool                                                            `json:"upload_complete"`
23         Description         ImageRecordList      `json:"description"`
24 }
25
26 type ImageRecordList struct {
27         ImageRecords []map[string]string `json:"image_records"`
28 }
29
30 // ImageKey is the key structure that is used in the database
31 type ImageKey struct {
32         // Owner            string     `json:"owner"`
33         // ClusterName      string     `json:"cluster_name"`
34         ImageName        string     `json:"image_name"`
35 }
36
37 // We will use json marshalling to convert to string to
38 // preserve the underlying structure.
39 func (dk ImageKey) String() string {
40         out, err := json.Marshal(dk)
41         if err != nil {
42                 return ""
43         }
44
45         return string(out)
46 }
47
48 // ImageManager is an interface that exposes the Image functionality
49 type ImageManager interface {
50         Create(c Image) (Image, error)
51         Get(imageName string) (Image, error)
52         Delete(imageName string) error
53         Update(imageName string, c Image) (Image, error)
54         GetImageRecordByName(imgname, imageName string) (map[string]string, error)
55 }
56
57 // ImageClient implements the ImageManager
58 // It will also be used to maintain some localized state
59 type ImageClient struct {
60         storeName string
61         tagMeta   string
62 }
63
64 // To Do - Fix repetition in
65 // NewImageClient returns an instance of the ImageClient
66 // which implements the ImageManager
67 func NewBinaryImageClient() *ImageClient {
68         return &ImageClient{
69                 storeName: "binary_image",
70                 tagMeta:   "metadata",
71         }
72 }
73
74 func NewContainerImageClient() *ImageClient {
75         return &ImageClient{
76                 storeName: "container_image",
77                 tagMeta:   "metadata",
78         }
79 }
80
81 func NewOSImageClient() *ImageClient {
82         return &ImageClient{
83                 storeName: "os_image",
84                 tagMeta:   "metadata",
85         }
86 }
87
88 // Create an entry for the Image resource in the database`
89 func (v *ImageClient) Create(c Image) (Image, error) {
90
91         //Construct composite key consisting of name
92         key := ImageKey{
93                 // Owner:       c.Owner,
94                 // ClusterName: c.ClusterName,
95                 ImageName: c.ImageName,
96         }
97
98         //Check if this Image already exists
99         _, err := v.Get(c.ImageName)
100         if err == nil {
101                 return Image{}, pkgerrors.New("Image already exists")
102         }
103
104         err = db.DBconn.Create(v.storeName, key, v.tagMeta, c)
105         if err != nil {
106                 return Image{}, pkgerrors.Wrap(err, "Creating DB Entry")
107         }
108
109         return c, nil
110 }
111
112 // Get returns Image for corresponding to name
113 func (v *ImageClient) Get(imageName string) (Image, error) {
114
115         //Construct the composite key to select the entry
116         key := ImageKey{
117                 // Owner:       ownerName,
118                 // ClusterName: clusterName,
119                 ImageName: imageName,
120         }
121
122         value, err := db.DBconn.Read(v.storeName, key, v.tagMeta)
123         if err != nil {
124                 return Image{}, pkgerrors.Wrap(err, "Get Image")
125         }
126
127         //value is a byte array
128         if value != nil {
129                 c := Image{}
130                 err = db.DBconn.Unmarshal(value, &c)
131                 if err != nil {
132                         return Image{}, pkgerrors.Wrap(err, "Unmarshaling Value")
133                 }
134                 return c, nil
135         }
136
137         return Image{}, pkgerrors.New("Error getting Connection")
138 }
139
140 func (v *ImageClient) GetImageRecordByName(imgName string,
141         imageRecordName string) (map[string]string, error) {
142
143         img, err := v.Get(imgName)
144         if err != nil {
145                 return nil, pkgerrors.Wrap(err, "Error getting image")
146         }
147
148         for _, value := range img.Description.ImageRecords {
149                 if imageRecordName == value["image_record_name"] {
150                         return value, nil
151                 }
152         }
153
154         return nil, pkgerrors.New("Image record " + imageRecordName + " not found")
155 }
156
157 // Delete the Image from database
158 func (v *ImageClient) Delete(imageName string) error {
159
160         //Construct the composite key to select the entry
161         key := ImageKey{
162                 // Owner:       ownerName,
163                 // ClusterName: clusterName,
164                 ImageName: imageName,
165         }
166         err := db.DBconn.Delete(v.storeName, key, v.tagMeta)
167         if err != nil {
168                 return pkgerrors.Wrap(err, "Delete Image")
169         }
170         return nil
171 }
172
173 // Update an entry for the image in the database
174 func (v *ImageClient) Update(imageName string, c Image) (Image, error) {
175
176         key := ImageKey{
177                 // Owner:       c.Owner,
178                 // ClusterName: c.ClusterName,
179                 ImageName: imageName,
180         }
181
182         //Check if this Image exists
183         _, err := v.Get(imageName)
184         if err != nil {
185                 return Image{}, pkgerrors.New("Update Error - Image doesn't exist")
186         }
187
188         err = db.DBconn.Update(v.storeName, key, v.tagMeta, c)
189         if err != nil {
190                 return Image{}, pkgerrors.Wrap(err, "Updating DB Entry")
191         }
192
193         return c, nil
194 }