1 // SPDX-License-Identifier: Apache-2.0
\r
2 // Copyright (c) 2020 Intel Corporation
\r
10 log "github.com/open-ness/EMCO/src/orchestrator/pkg/infra/logutils"
\r
11 "github.com/open-ness/EMCO/src/orchestrator/pkg/rtcontext"
\r
12 pkgerrors "github.com/pkg/errors"
\r
15 // metaPrefix used for denoting clusterMeta level
\r
16 const metaGrpPREFIX = "!@#metaGrp"
\r
18 type AppContext struct {
\r
20 rtcObj rtcontext.RunTimeContext
\r
21 rtc rtcontext.Rtcontext
\r
24 // AppContextStatus represents the current status of the appcontext
\r
25 // Instantiating - instantiate has been invoked and is still in progress
\r
26 // Instantiated - instantiate has completed
\r
27 // Terminating - terminate has been invoked and is still in progress
\r
28 // Terminated - terminate has completed
\r
29 // InstantiateFailed - the instantiate action has failed
\r
30 // TerminateFailed - the terminate action has failed
\r
31 type AppContextStatus struct {
\r
34 type StatusValue string
\r
35 type statuses struct {
\r
36 Instantiating StatusValue
\r
37 Instantiated StatusValue
\r
38 Terminating StatusValue
\r
39 Terminated StatusValue
\r
40 InstantiateFailed StatusValue
\r
41 TerminateFailed StatusValue
\r
44 var AppContextStatusEnum = &statuses{
\r
45 Instantiating: "Instantiating",
\r
46 Instantiated: "Instantiated",
\r
47 Terminating: "Terminating",
\r
48 Terminated: "Terminated",
\r
49 InstantiateFailed: "InstantiateFailed",
\r
50 TerminateFailed: "TerminateFailed",
\r
53 // CompositeAppMeta consists of projectName, CompositeAppName,
\r
54 // CompositeAppVersion, ReleaseName. This shall be used for
\r
55 // instantiation of a compositeApp
\r
56 type CompositeAppMeta struct {
\r
57 Project string `json:"Project"`
\r
58 CompositeApp string `json:"CompositeApp"`
\r
59 Version string `json:"Version"`
\r
60 Release string `json:"Release"`
\r
61 DeploymentIntentGroup string `json:"DeploymentIntentGroup"`
\r
62 Namespace string `json:"Namespace"`
\r
63 Level string `json:"Level"`
\r
67 func (ac *AppContext) InitAppContext() (interface{}, error) {
\r
68 ac.rtcObj = rtcontext.RunTimeContext{}
\r
70 return ac.rtc.RtcInit()
\r
73 // Load app context that was previously created
\r
74 func (ac *AppContext) LoadAppContext(cid interface{}) (interface{}, error) {
\r
75 ac.rtcObj = rtcontext.RunTimeContext{}
\r
77 return ac.rtc.RtcLoad(cid)
\r
80 // CreateCompositeApp method returns composite app handle as interface.
\r
81 func (ac *AppContext) CreateCompositeApp() (interface{}, error) {
\r
82 h, err := ac.rtc.RtcCreate()
\r
86 log.Info(":: CreateCompositeApp ::", log.Fields{"CompositeAppHandle": h})
\r
90 // AddCompositeAppMeta adds the meta data associated with a composite app
\r
91 func (ac *AppContext) AddCompositeAppMeta(meta interface{}) error {
\r
92 err := ac.rtc.RtcAddMeta(meta)
\r
99 // Deletes the entire context
\r
100 func (ac *AppContext) DeleteCompositeApp() error {
\r
101 h, err := ac.rtc.RtcGet()
\r
105 err = ac.rtc.RtcDeletePrefix(h)
\r
112 //Returns the handles for a given composite app context
\r
113 func (ac *AppContext) GetCompositeAppHandle() (interface{}, error) {
\r
114 h, err := ac.rtc.RtcGet()
\r
121 // GetLevelHandle returns the handle for the supplied level at the given handle.
\r
122 // For example, to get the handle of the 'status' level at a given handle.
\r
123 func (ac *AppContext) GetLevelHandle(handle interface{}, level string) (interface{}, error) {
\r
124 ach := fmt.Sprintf("%v%v/", handle, level)
\r
125 hs, err := ac.rtc.RtcGetHandles(ach)
\r
129 for _, v := range hs {
\r
134 return nil, pkgerrors.Errorf("No handle was found for level %v", level)
\r
137 //Add app to the context under composite app
\r
138 func (ac *AppContext) AddApp(handle interface{}, appname string) (interface{}, error) {
\r
139 h, err := ac.rtc.RtcAddLevel(handle, "app", appname)
\r
143 log.Info(":: Added app handle ::", log.Fields{"AppHandle": h})
\r
147 //Delete app from the context and everything underneth
\r
148 func (ac *AppContext) DeleteApp(handle interface{}) error {
\r
149 err := ac.rtc.RtcDeletePrefix(handle)
\r
156 //Returns the handle for a given app
\r
157 func (ac *AppContext) GetAppHandle(appname string) (interface{}, error) {
\r
159 return nil, pkgerrors.Errorf("Not a valid run time context app name")
\r
162 rh, err := ac.rtc.RtcGet()
\r
167 apph := fmt.Sprintf("%v", rh) + "app/" + appname + "/"
\r
168 hs, err := ac.rtc.RtcGetHandles(apph)
\r
172 for _, v := range hs {
\r
177 return nil, pkgerrors.Errorf("No handle was found for the given app")
\r
180 // AddCluster helps to add cluster to the context under app. It takes in the app handle and clusterName as value.
\r
181 func (ac *AppContext) AddCluster(handle interface{}, clustername string) (interface{}, error) {
\r
182 h, err := ac.rtc.RtcAddLevel(handle, "cluster", clustername)
\r
186 log.Info(":: Added cluster handle ::", log.Fields{"ClusterHandler": h})
\r
190 // AddClusterMetaGrp adds the meta info of groupNumber to which a cluster belongs.
\r
191 // It takes in cluster handle and groupNumber as arguments
\r
192 func (ac *AppContext) AddClusterMetaGrp(ch interface{}, gn string) error {
\r
193 mh, err := ac.rtc.RtcAddOneLevel(ch, metaGrpPREFIX, gn)
\r
197 log.Info(":: Added cluster meta handle ::", log.Fields{"ClusterMetaHandler": mh})
\r
201 // DeleteClusterMetaGrpHandle deletes the group number to which the cluster belongs, it takes in the cluster handle.
\r
202 func (ac *AppContext) DeleteClusterMetaGrpHandle(ch interface{}) error {
\r
203 err := ac.rtc.RtcDeletePrefix(ch)
\r
207 log.Info(":: Deleted cluster meta handle ::", log.Fields{"ClusterMetaHandler": ch})
\r
212 GetClusterMetaHandle takes in appName and ClusterName as string arguments and return the ClusterMetaHandle as string
\r
214 func (ac *AppContext) GetClusterMetaHandle(app string, cluster string) (string, error) {
\r
216 return "", pkgerrors.Errorf("Not a valid run time context app name")
\r
219 return "", pkgerrors.Errorf("Not a valid run time context cluster name")
\r
222 ch, err := ac.GetClusterHandle(app, cluster)
\r
226 cmh := fmt.Sprintf("%v", ch) + metaGrpPREFIX + "/"
\r
232 GetClusterGroupMap shall take in appName and return a map showing the grouping among the clusters.
\r
233 sample output of "GroupMap" :{"1":["cluster_provider1+clusterName3","cluster_provider1+clusterName5"],"2":["cluster_provider2+clusterName4","cluster_provider2+clusterName6"]}
\r
235 func (ac *AppContext) GetClusterGroupMap(an string) (map[string][]string, error) {
\r
236 cl, err := ac.GetClusterNames(an)
\r
238 log.Info(":: Unable to fetch clusterList for app ::", log.Fields{"AppName ": an})
\r
241 rh, err := ac.rtc.RtcGet()
\r
246 var gmap = make(map[string][]string)
\r
247 for _, cn := range cl {
\r
248 s := fmt.Sprintf("%v", rh) + "app/" + an + "/cluster/" + cn + "/" + metaGrpPREFIX + "/"
\r
250 err = ac.rtc.RtcGetValue(s, &v)
\r
252 log.Info(":: No group number for cluster ::", log.Fields{"cluster": cn, "Reason": err})
\r
255 gn := fmt.Sprintf("%v", v)
\r
256 log.Info(":: GroupNumber retrieved ::", log.Fields{"GroupNumber": gn})
\r
258 cl, found := gmap[gn]
\r
259 if found == false {
\r
260 cl = make([]string, 0)
\r
262 cl = append(cl, cn)
\r
268 //Delete cluster from the context and everything underneth
\r
269 func (ac *AppContext) DeleteCluster(handle interface{}) error {
\r
270 err := ac.rtc.RtcDeletePrefix(handle)
\r
277 //Returns the handle for a given app and cluster
\r
278 func (ac *AppContext) GetClusterHandle(appname string, clustername string) (interface{}, error) {
\r
280 return nil, pkgerrors.Errorf("Not a valid run time context app name")
\r
282 if clustername == "" {
\r
283 return nil, pkgerrors.Errorf("Not a valid run time context cluster name")
\r
286 rh, err := ac.rtc.RtcGet()
\r
291 ach := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/" + clustername + "/"
\r
292 hs, err := ac.rtc.RtcGetHandles(ach)
\r
296 for _, v := range hs {
\r
301 return nil, pkgerrors.Errorf("No handle was found for the given cluster")
\r
304 //Returns a list of all clusters for a given app
\r
305 func (ac *AppContext) GetClusterNames(appname string) ([]string, error) {
\r
307 return nil, pkgerrors.Errorf("Not a valid run time context app name")
\r
310 rh, err := ac.rtc.RtcGet()
\r
315 prefix := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/"
\r
316 hs, err := ac.rtc.RtcGetHandles(prefix)
\r
318 return nil, pkgerrors.Errorf("Error getting handles for %v", prefix)
\r
321 for _, h := range hs {
\r
322 hstr := fmt.Sprintf("%v", h)
\r
323 ks := strings.Split(hstr, prefix)
\r
324 for _, k := range ks {
\r
325 ck := strings.Split(k, "/")
\r
326 if len(ck) == 2 && ck[1] == "" {
\r
327 cs = append(cs, ck[0])
\r
334 //Add resource under app and cluster
\r
335 func (ac *AppContext) AddResource(handle interface{}, resname string, value interface{}) (interface{}, error) {
\r
336 h, err := ac.rtc.RtcAddResource(handle, resname, value)
\r
340 log.Info(":: Added resource handle ::", log.Fields{"ResourceHandler": h})
\r
345 //Return the handle for given app, cluster and resource name
\r
346 func (ac *AppContext) GetResourceHandle(appname string, clustername string, resname string) (interface{}, error) {
\r
348 return nil, pkgerrors.Errorf("Not a valid run time context app name")
\r
350 if clustername == "" {
\r
351 return nil, pkgerrors.Errorf("Not a valid run time context cluster name")
\r
354 rh, err := ac.rtc.RtcGet()
\r
359 acrh := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/" + clustername + "/resource/" + resname + "/"
\r
360 hs, err := ac.rtc.RtcGetHandles(acrh)
\r
364 for _, v := range hs {
\r
369 return nil, pkgerrors.Errorf("No handle was found for the given resource")
\r
372 //Update the resource value using the given handle
\r
373 func (ac *AppContext) UpdateResourceValue(handle interface{}, value interface{}) error {
\r
374 return ac.rtc.RtcUpdateValue(handle, value)
\r
377 //Return the handle for given app, cluster and resource name
\r
378 func (ac *AppContext) GetResourceStatusHandle(appname string, clustername string, resname string) (interface{}, error) {
\r
380 return nil, pkgerrors.Errorf("Not a valid run time context app name")
\r
382 if clustername == "" {
\r
383 return nil, pkgerrors.Errorf("Not a valid run time context cluster name")
\r
386 return nil, pkgerrors.Errorf("Not a valid run time context resource name")
\r
389 rh, err := ac.rtc.RtcGet()
\r
394 acrh := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/" + clustername + "/resource/" + resname + "/status/"
\r
395 hs, err := ac.rtc.RtcGetHandles(acrh)
\r
399 for _, v := range hs {
\r
404 return nil, pkgerrors.Errorf("No handle was found for the given resource")
\r
407 //Add instruction under given handle and type
\r
408 func (ac *AppContext) AddInstruction(handle interface{}, level string, insttype string, value interface{}) (interface{}, error) {
\r
409 if !(insttype == "order" || insttype == "dependency") {
\r
410 log.Error("Not a valid app context instruction type", log.Fields{})
\r
411 return nil, pkgerrors.Errorf("Not a valid app context instruction type")
\r
413 if !(level == "app" || level == "resource" || level == "subresource") {
\r
414 log.Error("Not a valid app context instruction level", log.Fields{})
\r
415 return nil, pkgerrors.Errorf("Not a valid app context instruction level")
\r
417 h, err := ac.rtc.RtcAddInstruction(handle, level, insttype, value)
\r
419 log.Error("ac.rtc.RtcAddInstruction(handle, level, insttype, value)", log.Fields{"err": err})
\r
422 log.Info(":: Added instruction handle ::", log.Fields{"InstructionHandler": h})
\r
426 //Delete instruction under given handle
\r
427 func (ac *AppContext) DeleteInstruction(handle interface{}) error {
\r
428 err := ac.rtc.RtcDeletePair(handle)
\r
435 //Returns the app instruction for a given instruction type
\r
436 func (ac *AppContext) GetAppInstruction(insttype string) (interface{}, error) {
\r
437 if !(insttype == "order" || insttype == "dependency") {
\r
438 log.Error("Not a valid app context instruction type", log.Fields{})
\r
439 return nil, pkgerrors.Errorf("Not a valid app context instruction type")
\r
441 rh, err := ac.rtc.RtcGet()
\r
443 log.Error("ac.rtc.RtcGet()", log.Fields{"err": err})
\r
446 s := fmt.Sprintf("%v", rh) + "app/" + "instruction/" + insttype + "/"
\r
447 log.Info("Getting app instruction", log.Fields{"s": s})
\r
449 err = ac.rtc.RtcGetValue(s, &v)
\r
451 log.Error("ac.rtc.RtcGetValue(s, &v)", log.Fields{"err": err})
\r
457 //Update the instruction usign the given handle
\r
458 func (ac *AppContext) UpdateInstructionValue(handle interface{}, value interface{}) error {
\r
459 return ac.rtc.RtcUpdateValue(handle, value)
\r
462 //Returns the resource instruction for a given instruction type
\r
463 func (ac *AppContext) GetResourceInstruction(appname string, clustername string, insttype string) (interface{}, error) {
\r
464 if !(insttype == "order" || insttype == "dependency") {
\r
465 log.Error("Not a valid app context instruction type", log.Fields{})
\r
466 return nil, pkgerrors.Errorf("Not a valid app context instruction type")
\r
468 rh, err := ac.rtc.RtcGet()
\r
470 log.Error("ac.rtc.RtcGet()", log.Fields{"err": err})
\r
473 s := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/" + clustername + "/resource/instruction/" + insttype + "/"
\r
475 err = ac.rtc.RtcGetValue(s, &v)
\r
477 log.Error("ac.rtc.RtcGetValue(s, &v)", log.Fields{"err": err})
\r
483 // AddLevelValue for holding a state object at a given level
\r
484 // will make a handle with an appended "<level>/" to the key
\r
485 func (ac *AppContext) AddLevelValue(handle interface{}, level string, value interface{}) (interface{}, error) {
\r
486 h, err := ac.rtc.RtcAddOneLevel(handle, level, value)
\r
490 log.Info(":: Added handle ::", log.Fields{"Handle": h})
\r
495 // GetClusterStatusHandle returns the handle for cluster status for a given app and cluster
\r
496 func (ac *AppContext) GetClusterStatusHandle(appname string, clustername string) (interface{}, error) {
\r
498 return nil, pkgerrors.Errorf("Not a valid run time context app name")
\r
500 if clustername == "" {
\r
501 return nil, pkgerrors.Errorf("Not a valid run time context cluster name")
\r
504 rh, err := ac.rtc.RtcGet()
\r
509 acrh := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/" + clustername + "/status/"
\r
510 hs, err := ac.rtc.RtcGetHandles(acrh)
\r
514 for _, v := range hs {
\r
519 return nil, pkgerrors.Errorf("No handle was found for the given resource")
\r
522 //UpdateStatusValue updates the status value with the given handle
\r
523 func (ac *AppContext) UpdateStatusValue(handle interface{}, value interface{}) error {
\r
524 return ac.rtc.RtcUpdateValue(handle, value)
\r
527 //UpdateValue updates the state value with the given handle
\r
528 func (ac *AppContext) UpdateValue(handle interface{}, value interface{}) error {
\r
529 return ac.rtc.RtcUpdateValue(handle, value)
\r
532 //Return all the handles under the composite app
\r
533 func (ac *AppContext) GetAllHandles(handle interface{}) ([]interface{}, error) {
\r
534 hs, err := ac.rtc.RtcGetHandles(handle)
\r
541 //Returns the value for a given handle
\r
542 func (ac *AppContext) GetValue(handle interface{}) (interface{}, error) {
\r
544 err := ac.rtc.RtcGetValue(handle, &v)
\r
551 // GetCompositeAppMeta returns the meta data associated with the compositeApp
\r
552 // Its return type is CompositeAppMeta
\r
553 func (ac *AppContext) GetCompositeAppMeta() (CompositeAppMeta, error) {
\r
554 mi, err := ac.rtcObj.RtcGetMeta()
\r
557 return CompositeAppMeta{}, pkgerrors.Errorf("Failed to get compositeApp meta")
\r
559 datamap, ok := mi.(map[string]interface{})
\r
561 return CompositeAppMeta{}, pkgerrors.Errorf("Failed to cast meta interface to compositeApp meta")
\r
564 p := fmt.Sprintf("%v", datamap["Project"])
\r
565 ca := fmt.Sprintf("%v", datamap["CompositeApp"])
\r
566 v := fmt.Sprintf("%v", datamap["Version"])
\r
567 rn := fmt.Sprintf("%v", datamap["Release"])
\r
568 dig := fmt.Sprintf("%v", datamap["DeploymentIntentGroup"])
\r
569 namespace := fmt.Sprintf("%v", datamap["Namespace"])
\r
570 level := fmt.Sprintf("%v", datamap["Level"])
\r
572 return CompositeAppMeta{Project: p, CompositeApp: ca, Version: v, Release: rn, DeploymentIntentGroup: dig, Namespace: namespace, Level: level}, nil
\r