Merge "Add another parameter to the definition"
[multicloud/k8s.git] / src / k8splugin / rb / definition.go
1 /*
2  * Copyright 2018 Intel Corporation, Inc
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package rb
18
19 import (
20         "bytes"
21         "encoding/base64"
22         "k8splugin/db"
23         "log"
24
25         uuid "github.com/hashicorp/go-uuid"
26         pkgerrors "github.com/pkg/errors"
27 )
28
29 // Definition contains the parameters needed for resource bundle (rb) definitions
30 // It implements the interface for managing the definitions
31 type Definition struct {
32         UUID        string `json:"uuid,omitempty"`
33         Name        string `json:"name"`
34         ChartName   string `json:"chart-name"`
35         Description string `json:"description"`
36         ServiceType string `json:"service-type"`
37 }
38
39 // DefinitionManager is an interface exposes the resource bundle definition functionality
40 type DefinitionManager interface {
41         Create(def Definition) (Definition, error)
42         List() ([]Definition, error)
43         Get(resID string) (Definition, error)
44         Delete(resID string) error
45         Upload(resID string, inp []byte) error
46 }
47
48 // DefinitionClient implements the DefinitionManager
49 // It will also be used to maintain some localized state
50 type DefinitionClient struct {
51         storeName           string
52         tagMeta, tagContent string
53 }
54
55 // NewDefinitionClient returns an instance of the DefinitionClient
56 // which implements the DefinitionManager
57 // Uses rbdef collection in underlying db
58 func NewDefinitionClient() *DefinitionClient {
59         return &DefinitionClient{
60                 storeName:  "rbdef",
61                 tagMeta:    "metadata",
62                 tagContent: "content",
63         }
64 }
65
66 // Create an entry for the resource in the database
67 func (v *DefinitionClient) Create(def Definition) (Definition, error) {
68         // If UUID is empty, we will generate one
69         if def.UUID == "" {
70                 def.UUID, _ = uuid.GenerateUUID()
71         }
72         key := def.UUID
73
74         err := db.DBconn.Create(v.storeName, key, v.tagMeta, def)
75         if err != nil {
76                 return Definition{}, pkgerrors.Wrap(err, "Creating DB Entry")
77         }
78
79         return def, nil
80 }
81
82 // List all resource entries in the database
83 func (v *DefinitionClient) List() ([]Definition, error) {
84         res, err := db.DBconn.ReadAll(v.storeName, v.tagMeta)
85         if err != nil || len(res) == 0 {
86                 return []Definition{}, pkgerrors.Wrap(err, "Listing Resource Bundle Definitions")
87         }
88
89         var results []Definition
90         for key, value := range res {
91                 //value is a byte array
92                 if len(value) > 0 {
93                         def := Definition{}
94                         err = db.DBconn.Unmarshal(value, &def)
95                         if err != nil {
96                                 log.Printf("[Definition] Error Unmarshaling value for: %s", key)
97                                 continue
98                         }
99                         results = append(results, def)
100                 }
101         }
102
103         return results, nil
104 }
105
106 // Get returns the Resource Bundle Definition for corresponding ID
107 func (v *DefinitionClient) Get(id string) (Definition, error) {
108         value, err := db.DBconn.Read(v.storeName, id, v.tagMeta)
109         if err != nil {
110                 return Definition{}, pkgerrors.Wrap(err, "Get Resource Bundle definition")
111         }
112
113         //value is a byte array
114         if value != nil {
115                 def := Definition{}
116                 err = db.DBconn.Unmarshal(value, &def)
117                 if err != nil {
118                         return Definition{}, pkgerrors.Wrap(err, "Unmarshaling Value")
119                 }
120                 return def, nil
121         }
122
123         return Definition{}, pkgerrors.New("Error getting Resource Bundle Definition")
124 }
125
126 // Delete the Resource Bundle definition from database
127 func (v *DefinitionClient) Delete(id string) error {
128         err := db.DBconn.Delete(v.storeName, id, v.tagMeta)
129         if err != nil {
130                 return pkgerrors.Wrap(err, "Delete Resource Bundle Definition")
131         }
132
133         //Delete the content when the delete operation happens
134         err = db.DBconn.Delete(v.storeName, id, v.tagContent)
135         if err != nil {
136                 return pkgerrors.Wrap(err, "Delete Resource Bundle Definition Content")
137         }
138
139         return nil
140 }
141
142 // Upload the contents of resource bundle into database
143 func (v *DefinitionClient) Upload(id string, inp []byte) error {
144
145         //ignore the returned data here
146         _, err := v.Get(id)
147         if err != nil {
148                 return pkgerrors.Errorf("Invalid Definition ID provided: %s", err.Error())
149         }
150
151         err = isTarGz(bytes.NewBuffer(inp))
152         if err != nil {
153                 return pkgerrors.Errorf("Error in file format: %s", err.Error())
154         }
155
156         //Encode given byte stream to text for storage
157         encodedStr := base64.StdEncoding.EncodeToString(inp)
158         err = db.DBconn.Create(v.storeName, id, v.tagContent, encodedStr)
159         if err != nil {
160                 return pkgerrors.Errorf("Error uploading data to db: %s", err.Error())
161         }
162
163         return nil
164 }