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