Merge "Controller API support"
[multicloud/k8s.git] / src / orchestrator / pkg / module / add_intents.go
1 /*
2  * Copyright 2020 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 Addlicable 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 module
18
19 /*
20 This files deals with the backend implementation of adding
21 genericPlacementIntents to deployementIntentGroup
22 */
23
24 import (
25         "encoding/json"
26         "reflect"
27
28         "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
29
30         pkgerrors "github.com/pkg/errors"
31 )
32
33 // Intent shall have 2 fields - MetaData and Spec
34 type Intent struct {
35         MetaData IntentMetaData `json:"metadata"`
36         Spec     IntentSpecData `json:"spec"`
37 }
38
39 // IntentMetaData has Name, Description, userdata1, userdata2
40 type IntentMetaData struct {
41         Name        string `json:"name"`
42         Description string `json:"description"`
43         UserData1   string `json:"userData1"`
44         UserData2   string `json:"userData2"`
45 }
46
47 // IntentSpecData has Intent
48 type IntentSpecData struct {
49         Intent map[string]string `json:"intent"`
50 }
51
52
53 // ListOfIntents is a list of intents
54 type ListOfIntents struct {
55         ListOfIntents []map[string]string `json:"intent"`
56 }
57
58
59 // IntentManager is an interface which exposes the IntentManager functionality
60 type IntentManager interface {
61         AddIntent(a Intent, p string, ca string, v string, di string) (Intent, error)
62         GetIntent(i string, p string, ca string, v string, di string) (Intent, error)
63         GetAllIntents(p, ca, v, di string) (ListOfIntents, error)
64         GetIntentByName(i, p, ca, v, di string) (IntentSpecData, error)
65         DeleteIntent(i string, p string, ca string, v string, di string) error
66 }
67
68 // IntentKey consists of Name if the intent, Project name, CompositeApp name,
69 // CompositeApp version
70 type IntentKey struct {
71         Name                  string `json:"intentname"`
72         Project               string `json:"project"`
73         CompositeApp          string `json:"compositeapp"`
74         Version               string `json:"compositeappversion"`
75         DeploymentIntentGroup string `json:"deploymentintentgroup"`
76 }
77
78 // We will use json marshalling to convert to string to
79 // preserve the underlying structure.
80 func (ik IntentKey) String() string {
81         out, err := json.Marshal(ik)
82         if err != nil {
83                 return ""
84         }
85         return string(out)
86 }
87
88 // IntentClient implements the AddIntentManager interface
89 type IntentClient struct {
90         storeName   string
91         tagMetaData string
92 }
93
94 // NewIntentClient returns an instance of AddIntentClient
95 func NewIntentClient() *IntentClient {
96         return &IntentClient{
97                 storeName:   "orchestrator",
98                 tagMetaData: "addintent",
99         }
100 }
101
102 /*
103 AddIntent adds a given intent to the deployment-intent-group and stores in the db.
104 Other input parameters for it - projectName, compositeAppName, version, DeploymentIntentgroupName
105 */
106 func (c *IntentClient) AddIntent(a Intent, p string, ca string, v string, di string) (Intent, error) {
107
108         //Check for the AddIntent already exists here.
109         res, err := c.GetIntent(a.MetaData.Name, p, ca, v, di)
110         if !reflect.DeepEqual(res, Intent{}) {
111                 return Intent{}, pkgerrors.New("Intent already exists")
112         }
113
114         //Check if project exists
115         _, err = NewProjectClient().GetProject(p)
116         if err != nil {
117                 return Intent{}, pkgerrors.New("Unable to find the project")
118         }
119
120         //check if compositeApp exists
121         _, err = NewCompositeAppClient().GetCompositeApp(ca, v, p)
122         if err != nil {
123                 return Intent{}, pkgerrors.New("Unable to find the composite-app")
124         }
125
126         //check if DeploymentIntentGroup exists
127         _, err = NewDeploymentIntentGroupClient().GetDeploymentIntentGroup(di, p, ca, v)
128         if err != nil {
129                 return Intent{}, pkgerrors.New("Unable to find the intent")
130         }
131
132         akey := IntentKey{
133                 Name:                  a.MetaData.Name,
134                 Project:               p,
135                 CompositeApp:          ca,
136                 Version:               v,
137                 DeploymentIntentGroup: di,
138         }
139
140         err = db.DBconn.Insert(c.storeName, akey, nil, c.tagMetaData, a)
141         if err != nil {
142                 return Intent{}, pkgerrors.Wrap(err, "Create DB entry error")
143         }
144         return a, nil
145 }
146
147 /*
148 GetIntent takes in an IntentName, ProjectName, CompositeAppName, Version and DeploymentIntentGroup.
149 It returns the Intent.
150 */
151 func (c *IntentClient) GetIntent(i string, p string, ca string, v string, di string) (Intent, error) {
152
153         k := IntentKey{
154                 Name:                  i,
155                 Project:               p,
156                 CompositeApp:          ca,
157                 Version:               v,
158                 DeploymentIntentGroup: di,
159         }
160
161         result, err := db.DBconn.Find(c.storeName, k, c.tagMetaData)
162         if err != nil {
163                 return Intent{}, pkgerrors.Wrap(err, "Get Intent error")
164         }
165
166         if result != nil {
167                 a := Intent{}
168                 err = db.DBconn.Unmarshal(result[0], &a)
169                 if err != nil {
170                         return Intent{}, pkgerrors.Wrap(err, "Unmarshalling  AppIntent")
171                 }
172                 return a, nil
173
174         }
175         return Intent{}, pkgerrors.New("Error getting Intent")
176 }
177
178
179 /*
180 GetIntentByName takes in IntentName, projectName, CompositeAppName, CompositeAppVersion
181 and deploymentIntentGroupName returns the list of intents under the IntentName.
182 */
183 func (c IntentClient) GetIntentByName(i string, p string, ca string, v string, di string) (IntentSpecData, error) {
184         k := IntentKey{
185                 Name:                  i,
186                 Project:               p,
187                 CompositeApp:          ca,
188                 Version:               v,
189                 DeploymentIntentGroup: di,
190         }
191         result, err := db.DBconn.Find(c.storeName, k, c.tagMetaData)
192         if err != nil {
193                 return IntentSpecData{}, pkgerrors.Wrap(err, "Get AppIntent error")
194         }
195         var a Intent
196         err = db.DBconn.Unmarshal(result[0], &a)
197         if err != nil {
198                 return IntentSpecData{}, pkgerrors.Wrap(err, "Unmarshalling  Intent")
199         }
200         return a.Spec, nil
201 }
202
203
204 /*
205 GetAllIntents takes in projectName, CompositeAppName, CompositeAppVersion,
206 DeploymentIntentName . It returns ListOfIntents.
207 */
208 func (c IntentClient) GetAllIntents(p string, ca string, v string, di string) (ListOfIntents, error) {
209         k := IntentKey{
210                 Name:                  "",
211                 Project:               p,
212                 CompositeApp:          ca,
213                 Version:               v,
214                 DeploymentIntentGroup: di,
215         }
216
217         result, err := db.DBconn.Find(c.storeName, k, c.tagMetaData)
218         if err != nil {
219                 return ListOfIntents{}, pkgerrors.Wrap(err, "Get AppIntent error")
220         }
221         var a Intent
222         var listOfMapOfIntents []map[string]string
223
224         if len(result) != 0 {
225                 for i := range result {
226                         a = Intent{}
227                         err = db.DBconn.Unmarshal(result[i], &a)
228                         if err != nil {
229                                 return ListOfIntents{}, pkgerrors.Wrap(err, "Unmarshalling Intent")
230                         }
231                         //mapOfIntents := ListOfIntents{a.Spec.Intent.ListOfIntents}
232                         listOfMapOfIntents = append(listOfMapOfIntents, a.Spec.Intent)
233                 }
234                 return ListOfIntents{listOfMapOfIntents}, nil
235         }
236         return ListOfIntents{}, err
237 }
238
239
240 // DeleteIntent deletes a given intent tied to project, composite app and deployment intent group
241 func (c IntentClient) DeleteIntent(i string, p string, ca string, v string, di string) error {
242         k := IntentKey{
243                 Name:                  i,
244                 Project:               p,
245                 CompositeApp:          ca,
246                 Version:               v,
247                 DeploymentIntentGroup: di,
248         }
249
250         err := db.DBconn.Remove(c.storeName, k)
251         if err != nil {
252                 return pkgerrors.Wrap(err, "Delete Project entry;")
253         }
254         return nil
255 }