aboutsummaryrefslogtreecommitdiffstats
path: root/src/orchestrator/pkg/module/instantiation.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/orchestrator/pkg/module/instantiation.go')
-rw-r--r--src/orchestrator/pkg/module/instantiation.go248
1 files changed, 222 insertions, 26 deletions
diff --git a/src/orchestrator/pkg/module/instantiation.go b/src/orchestrator/pkg/module/instantiation.go
index 56021547..58706ef6 100644
--- a/src/orchestrator/pkg/module/instantiation.go
+++ b/src/orchestrator/pkg/module/instantiation.go
@@ -17,15 +17,17 @@
package module
import (
+ "encoding/base64"
"fmt"
-
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext"
gpic "github.com/onap/multicloud-k8s/src/orchestrator/pkg/gpic"
-
- "encoding/base64"
-
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+ "github.com/onap/multicloud-k8s/src/orchestrator/utils"
"github.com/onap/multicloud-k8s/src/orchestrator/utils/helm"
pkgerrors "github.com/pkg/errors"
- "log"
+ "io/ioutil"
+ //"log"
+ log "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/logutils"
)
// ManifestFileName is the name given to the manifest file in the profile package
@@ -34,10 +36,29 @@ const ManifestFileName = "manifest.yaml"
// GenericPlacementIntentName denotes the generic placement intent name
const GenericPlacementIntentName = "generic-placement-intent"
+// SEPARATOR used while creating clusternames to store in etcd
+const SEPARATOR = "+"
+
// InstantiationClient implements the InstantiationManager
type InstantiationClient struct {
- storeName string
- tagMetaData string
+ db InstantiationClientDbInfo
+}
+
+/*
+InstantiationKey used in storing the contextid in the momgodb
+It consists of
+GenericPlacementIntentName,
+ProjectName,
+CompositeAppName,
+CompositeAppVersion,
+DeploymentIntentGroup
+*/
+type InstantiationKey struct {
+ IntentName string
+ Project string
+ CompositeApp string
+ Version string
+ DeploymentIntentGroup string
}
// InstantiationManager is an interface which exposes the
@@ -47,11 +68,19 @@ type InstantiationManager interface {
Instantiate(p string, ca string, v string, di string) error
}
+// InstantiationClientDbInfo consists of storeName and tagContext
+type InstantiationClientDbInfo struct {
+ storeName string // name of the mongodb collection to use for Instantiationclient documents
+ tagContext string // attribute key name for context object in App Context
+}
+
// NewInstantiationClient returns an instance of InstantiationClient
func NewInstantiationClient() *InstantiationClient {
return &InstantiationClient{
- storeName: "orchestrator",
- tagMetaData: "instantiation",
+ db: InstantiationClientDbInfo{
+ storeName: "orchestrator",
+ tagContext: "contextid",
+ },
}
}
@@ -70,10 +99,10 @@ func getOverrideValuesByAppName(ov []OverrideValues, a string) map[string]string
}
/*
-FindGenericPlacementIntent takes in projectName, CompositeAppName, CompositeAppVersion, DeploymentIntentName
+findGenericPlacementIntent takes in projectName, CompositeAppName, CompositeAppVersion, DeploymentIntentName
and returns the name of the genericPlacementIntentName. Returns empty value if string not found.
*/
-func FindGenericPlacementIntent(p, ca, v, di string) (string, error) {
+func findGenericPlacementIntent(p, ca, v, di string) (string, error) {
var gi string
var found bool
iList, err := NewIntentClient().GetAllIntents(p, ca, v, di)
@@ -82,7 +111,7 @@ func FindGenericPlacementIntent(p, ca, v, di string) (string, error) {
}
for _, eachMap := range iList.ListOfIntents {
if gi, found := eachMap[GenericPlacementIntentName]; found {
- log.Printf("::Name of the generic-placement-intent:: %s", gi)
+ log.Info(":: Name of the generic-placement-intent ::", log.Fields{"GenPlmtIntent":gi})
return gi, err
}
}
@@ -97,7 +126,8 @@ func FindGenericPlacementIntent(p, ca, v, di string) (string, error) {
//It takes in arguments - appName, project, compositeAppName, releaseName, compositeProfileName, array of override values
func GetSortedTemplateForApp(appName, p, ca, v, rName, cp string, overrideValues []OverrideValues) ([]helm.KubernetesResourceTemplate, error) {
- log.Println("Processing App.. ", appName)
+
+ log.Info(":: Processing App ::", log.Fields{"appName":appName})
var sortedTemplates []helm.KubernetesResourceTemplate
@@ -109,7 +139,8 @@ func GetSortedTemplateForApp(appName, p, ca, v, rName, cp string, overrideValues
if err != nil {
return sortedTemplates, pkgerrors.Wrap(err, "Fail to convert to byte array")
}
- log.Println("Got the app content..")
+
+ log.Info(":: Got the app content.. ::", log.Fields{"appName":appName})
appPC, err := NewAppProfileClient().GetAppProfileContentByApp(p, ca, v, cp, appName)
if err != nil {
@@ -120,7 +151,7 @@ func GetSortedTemplateForApp(appName, p, ca, v, rName, cp string, overrideValues
return sortedTemplates, pkgerrors.Wrap(err, "Fail to convert to byte array")
}
- log.Println("Got the app Profile content ...")
+ log.Info(":: Got the app Profile content .. ::", log.Fields{"appName":appName})
overrideValuesOfApp := getOverrideValuesByAppName(overrideValues, appName)
//Convert override values from map to array of strings of the following format
@@ -137,12 +168,111 @@ func GetSortedTemplateForApp(appName, p, ca, v, rName, cp string, overrideValues
appProfileContent, overrideValuesOfAppStr,
appName)
- log.Printf("The len of the sortedTemplates :: %d", len(sortedTemplates))
+ log.Info(":: Total no. of sorted templates ::", log.Fields{"len(sortedTemplates):":len(sortedTemplates)})
return sortedTemplates, err
}
-// Instantiate methods takes in project
+// resource consists of name of reource
+type resource struct {
+ name string
+ filecontent []byte
+}
+
+// getResources shall take in the sorted templates and output the resources
+// which consists of name(name+kind) and filecontent
+func getResources(st []helm.KubernetesResourceTemplate) ([]resource, error) {
+ var resources []resource
+ for _, t := range st {
+ yamlStruct, err := utils.ExtractYamlParameters(t.FilePath)
+ yamlFile, err := ioutil.ReadFile(t.FilePath)
+ if err != nil {
+ return nil, pkgerrors.Wrap(err, "Failed to get the resources..")
+ }
+ n := yamlStruct.Metadata.Name + SEPARATOR + yamlStruct.Kind
+
+ resources = append(resources, resource{name: n, filecontent: yamlFile})
+
+ log.Info(":: Added resource into resource-order ::", log.Fields{"ResourceName":n})
+ }
+ return resources, nil
+}
+
+func addResourcesToCluster(ct appcontext.AppContext, ch interface{}, resources []resource, resourceOrder []string) error {
+ for _, resource := range resources {
+
+ resourceOrder = append(resourceOrder, resource.name)
+ _, err := ct.AddResource(ch, resource.name, resource.filecontent)
+ if err != nil {
+ cleanuperr := ct.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Info(":: Error Cleaning up AppContext after add resource failure ::", log.Fields{"Resource":resource.name, "Error":cleanuperr.Error})
+ }
+ return pkgerrors.Wrapf(err, "Error adding resource ::%s to AppContext", resource.name)
+ }
+ _, err = ct.AddInstruction(ch, "resource", "order", resourceOrder)
+ if err != nil {
+ cleanuperr := ct.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Info(":: Error Cleaning up AppContext after add instruction failure ::", log.Fields{"Resource":resource.name, "Error":cleanuperr.Error})
+ }
+ return pkgerrors.Wrapf(err, "Error adding instruction for resource ::%s to AppContext", resource.name)
+ }
+ }
+ return nil
+}
+
+func addClustersToAppContext(l gpic.Clusters, ct appcontext.AppContext, appHandle interface{}, resources []resource) error {
+ for _, c := range l.ClustersWithName {
+ p := c.ProviderName
+ n := c.ClusterName
+ var resourceOrder []string
+ clusterhandle, err := ct.AddCluster(appHandle, p+SEPARATOR+n)
+ if err != nil {
+ cleanuperr := ct.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Info(":: Error Cleaning up AppContext after add cluster failure ::", log.Fields{"cluster-provider":p, "cluster-name":n, "Error":cleanuperr.Error})
+ }
+ return pkgerrors.Wrapf(err, "Error adding Cluster(provider::%s and name::%s) to AppContext", p, n)
+ }
+
+ err = addResourcesToCluster(ct, clusterhandle, resources, resourceOrder)
+ if err != nil {
+ return pkgerrors.Wrapf(err, "Error adding Resources to Cluster(provider::%s and name::%s) to AppContext", p, n)
+ }
+ }
+ return nil
+}
+
+/*
+verifyResources method is just to check if the resource handles are correctly saved.
+*/
+
+func verifyResources(l gpic.Clusters, ct appcontext.AppContext, resources []resource, appName string) error {
+ for _, c := range l.ClustersWithName {
+ p := c.ProviderName
+ n := c.ClusterName
+ cn := p + SEPARATOR + n
+ for _, res := range resources {
+
+ rh, err := ct.GetResourceHandle(appName, cn, res.name)
+ if err != nil {
+ return pkgerrors.Wrapf(err, "Error getting resoure handle for resource :: %s, app:: %s, cluster :: %s", appName, res.name, cn)
+ }
+ log.Info(":: GetResourceHandle ::", log.Fields{"ResourceHandler":rh, "appName":appName, "Cluster": cn, "Resource":res.name})
+
+ }
+
+ }
+
+ return nil
+}
+
+/*
+Instantiate methods takes in projectName, compositeAppName, compositeAppVersion,
+DeploymentIntentName. This method is responsible for template resolution, intent
+resolution, creation and saving of context for saving into etcd.
+*/
func (c InstantiationClient) Instantiate(p string, ca string, v string, di string) error {
dIGrp, err := NewDeploymentIntentGroupClient().GetDeploymentIntentGroup(di, p, ca, v)
@@ -153,36 +283,102 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin
overrideValues := dIGrp.Spec.OverrideValuesObj
cp := dIGrp.Spec.Profile
- gIntent, err := FindGenericPlacementIntent(p, ca, v, di)
+ gIntent, err := findGenericPlacementIntent(p, ca, v, di)
if err != nil {
return err
}
- log.Printf("The name of the GenPlacIntent:: %s", gIntent)
- log.Printf("dIGrp :: %s, releaseName :: %s and cp :: %s \n", dIGrp.MetaData.Name, rName, cp)
+ log.Info(":: The name of the GenPlacIntent ::", log.Fields{"GenPlmtIntent":gIntent})
+ log.Info(":: DeploymentIntentGroup, ReleaseName, CompositeProfile ::", log.Fields{"dIGrp":dIGrp.MetaData.Name, "releaseName":rName, "cp":cp})
+
allApps, err := NewAppClient().GetApps(p, ca, v)
if err != nil {
return pkgerrors.Wrap(err, "Not finding the apps")
}
+
+ // Make an app context for the compositeApp
+ context := appcontext.AppContext{}
+ ctxval, err := context.InitAppContext()
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error creating AppContext CompositeApp")
+ }
+ compositeHandle, err := context.CreateCompositeApp()
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error creating AppContext")
+ }
+
+ var appOrder []string
+
+ // Add composite app using appContext
for _, eachApp := range allApps {
+ appOrder = append(appOrder, eachApp.Metadata.Name)
sortedTemplates, err := GetSortedTemplateForApp(eachApp.Metadata.Name, p, ca, v, rName, cp, overrideValues)
+
if err != nil {
return pkgerrors.Wrap(err, "Unable to get the sorted templates for app")
}
- log.Printf("Resolved all the templates for app :: %s under the compositeApp...", eachApp.Metadata.Name)
- log.Printf("sortedTemplates :: %v ", sortedTemplates)
+
+ log.Info(":: Resolved all the templates ::", log.Fields{"appName":eachApp.Metadata.Name, "SortedTemplate":sortedTemplates})
+
+ resources, err := getResources(sortedTemplates)
+ if err != nil {
+ return pkgerrors.Wrapf(err, "Unable to get the resources for app :: %s", eachApp.Metadata.Name)
+ }
specData, err := NewAppIntentClient().GetAllIntentsByApp(eachApp.Metadata.Name, p, ca, v, gIntent)
if err != nil {
return pkgerrors.Wrap(err, "Unable to get the intents for app")
}
- listOfClusters,err := gpic.IntentResolver(specData.Intent)
- if err!=nil {
+ listOfClusters, err := gpic.IntentResolver(specData.Intent)
+ if err != nil {
return pkgerrors.Wrap(err, "Unable to get the intents resolved for app")
}
- log.Printf("::listOfClusters:: %v", listOfClusters)
+ log.Info(":: listOfClusters ::", log.Fields{"listOfClusters":listOfClusters})
+
+ //BEGIN: storing into etcd
+ // Add an app to the app context
+ apphandle, err := context.AddApp(compositeHandle, eachApp.Metadata.Name)
+ if err != nil {
+ cleanuperr := context.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Info(":: Error Cleaning up AppContext compositeApp failure ::", log.Fields{"Error":cleanuperr.Error(), "AppName":eachApp.Metadata.Name})
+ }
+ return pkgerrors.Wrap(err, "Error adding App to AppContext")
+ }
+ err = addClustersToAppContext(listOfClusters, context, apphandle, resources)
+ if err != nil {
+ log.Info(":: Error while adding cluster and resources to app ::", log.Fields{"Error":err.Error(), "AppName":eachApp.Metadata.Name})
+ }
+ err = verifyResources(listOfClusters, context, resources, eachApp.Metadata.Name)
+ if err != nil {
+ log.Info(":: Error while verifying resources in app ::", log.Fields{"Error":err.Error(), "AppName":eachApp.Metadata.Name})
+ }
+
+ }
+ context.AddInstruction(compositeHandle, "app", "order", appOrder)
+ //END: storing into etcd
+
+ // BEGIN:: save the context in the orchestrator db record
+ key := InstantiationKey{
+ IntentName: gIntent,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ DeploymentIntentGroup: di,
+ }
+
+ err = db.DBconn.Insert(c.db.storeName, key, nil, c.db.tagContext, ctxval)
+ if err != nil {
+ cleanuperr := context.DeleteCompositeApp()
+ if cleanuperr != nil {
+
+ log.Info(":: Error Cleaning up AppContext while saving context in the db for GPIntent ::", log.Fields{"Error":cleanuperr.Error(), "GPIntent":gIntent, "DeploymentIntentGroup":di, "CompositeApp":ca, "CompositeAppVersion":v, "Project":p})
+ }
+ return pkgerrors.Wrap(err, "Error adding AppContext to DB")
}
- log.Printf("Done with instantiation...")
+ // END:: save the context in the orchestrator db record
+
+ log.Info(":: Done with instantiation... ::", log.Fields{"CompositeAppName":ca})
return err
}