userData1="user1"
userData2="user2"
-composite_app_name="test_composite_app"
+composite_app_name="test_composite_app_collection"
composite_app_description="test_project_description"
composite_app_version="test_composite_app_version"
app1_helm_path="$CSAR_DIR/$csar_id/collectd.tar.gz"
main_composite_profile_name="main_composite_profile"
sub_composite_profile_name1="test_composite_profile1"
sub_composite_profile_name2="test_composite_profile2"
-composite_profile_description="test_composite_profile_description"
+main_composite_profile_description="main_composite_profile_description"
+sub_composite_profile_description="sub_composite_profile_description"
genericPlacementIntentName="test_gen_placement_intent1"
genericPlacementIntentDesc="test_gen_placement_intent_desc"
{
"metadata":{
"name":"${main_composite_profile_name}",
- "description":"${composite_profile_description}",
+ "description":"${main_composite_profile_description}",
"userData1":"${userData1}",
"userData2":"${userData2}"
}
{
"metadata":{
"name":"${sub_composite_profile_name1}",
- "description":"${composite_profile_description}",
+ "description":"${sub_composite_profile_description}",
"userData1":"${userData1}",
"userData2":"${userData2}"
},
{
"metadata":{
"name":"${sub_composite_profile_name2}",
- "description":"${composite_profile_description}",
+ "description":"${sub_composite_profile_description}",
"userData1":"${userData1}",
"userData2":"${userData2}"
},
return
}
-
mapOfIntents, err := h.client.GetIntentByName(iN, p, ca, v, di)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
cProfClient: &mockCompositeProfileManager{
//Items that will be returned by the mocked Client
Items: []moduleLib.CompositeProfile{
- moduleLib.CompositeProfile{
+ {
Metadata: moduleLib.CompositeProfileMetadata{
Name: "testCompositeProfile",
Description: "Test CompositeProfile used for unit testing",
projectClient: &mockProjectManager{
//Items that will be returned by the mocked Client
Items: []moduleLib.Project{
- moduleLib.Project{
+ {
MetaData: moduleLib.ProjectMetaData{
Name: "testProject",
Description: "Test Project used for unit testing",
name: "testProject",
projectClient: &mockProjectManager{
Items: []moduleLib.Project{
- moduleLib.Project{
+ {
MetaData: moduleLib.ProjectMetaData{
Name: "testProject",
Description: "Test Project used for unit testing",
--- /dev/null
+/*
+ * Copyright 2020 Intel Corporation, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package gpic
+
+/*
+ gpic stands for GenericPlacementIntent Controller.
+ This file pertains to the implementation and handling of generic placement intents
+*/
+
+import (
+ "log"
+ ncmmodule "github.com/onap/multicloud-k8s/src/ncm/pkg/module"
+ pkgerrors "github.com/pkg/errors"
+)
+
+// Clusters has 1 field - a list of ClusterNames
+type Clusters struct {
+ ClustersWithName []ClusterWithName
+}
+
+// ClusterWithName has two fields - ProviderName and ClusterName
+type ClusterWithName struct {
+ ProviderName string
+ ClusterName string
+}
+
+// ClusterWithLabel has two fields - ProviderName and ClusterLabel
+type ClusterWithLabel struct {
+ ProviderName string
+ ClusterLabel string
+}
+
+// IntentStruc consists of AllOfArray and AnyOfArray
+type IntentStruc struct {
+ AllOfArray []AllOf `json:"allOf,omitempty"`
+ AnyOfArray []AnyOf `json:"anyOf,omitempty"`
+}
+
+// AllOf consists if ProviderName, ClusterName, ClusterLabelName and AnyOfArray. Any of them can be empty
+type AllOf struct {
+ ProviderName string `json:"provider-name,omitempty"`
+ ClusterName string `json:"cluster-name,omitempty"`
+ ClusterLabelName string `json:"cluster-label-name,omitempty"`
+ AnyOfArray []AnyOf `json:"anyOf,omitempty"`
+}
+
+// AnyOf consists of Array of ProviderName & ClusterLabelNames
+type AnyOf struct {
+ ProviderName string `json:"provider-name,omitempty"`
+ ClusterName string `json:"cluster-name,omitempty"`
+ ClusterLabelName string `json:"cluster-label-name,omitempty"`
+}
+
+// intentResolverHelper helps to populate the cluster lists
+func intentResolverHelper(pn, cn, cln string, clustersWithName []ClusterWithName) ([]ClusterWithName, error) {
+ if cln == "" && cn != "" {
+ eachClusterWithName := ClusterWithName{pn, cn}
+ clustersWithName = append(clustersWithName, eachClusterWithName)
+ log.Printf("Added Cluster: %s ", cn)
+ }
+ if cn == "" && cln != "" {
+ //Finding cluster names for the clusterlabel
+ clusterNamesList, err := ncmmodule.NewClusterClient().GetClustersWithLabel(pn, cln)
+ if err != nil {
+ return []ClusterWithName{}, pkgerrors.Wrap(err, "Error getting clusterLabels")
+ }
+ // Populate the clustersWithName array with the clusternames found above
+ for _, eachClusterName := range clusterNamesList {
+ eachClusterWithPN := ClusterWithName{pn, eachClusterName}
+ clustersWithName = append(clustersWithName, eachClusterWithPN)
+ log.Printf("Added Cluster: %s ", cln)
+ }
+ }
+ return clustersWithName, nil
+}
+
+// IntentResolver shall help to resolve the given intent into 2 lists of clusters where the app need to be deployed.
+func IntentResolver(intent IntentStruc) (Clusters, error) {
+ var clustersWithName []ClusterWithName
+ var err error
+
+ for _, eachAllOf := range intent.AllOfArray {
+ clustersWithName, err = intentResolverHelper(eachAllOf.ProviderName, eachAllOf.ClusterName, eachAllOf.ClusterLabelName, clustersWithName)
+ if err!=nil {
+ return Clusters{}, pkgerrors.Wrap(err, "intentResolverHelper error")
+ }
+ if len(eachAllOf.AnyOfArray) > 0 {
+ for _, eachAnyOf := range eachAllOf.AnyOfArray {
+ clustersWithName, err = intentResolverHelper(eachAnyOf.ProviderName, eachAnyOf.ClusterName, eachAnyOf.ClusterLabelName, clustersWithName)
+ if err!=nil {
+ return Clusters{}, pkgerrors.Wrap(err, "intentResolverHelper error")
+ }
+ }
+ }
+ }
+ if len(intent.AnyOfArray) > 0 {
+ for _, eachAnyOf := range intent.AnyOfArray {
+ clustersWithName, err = intentResolverHelper(eachAnyOf.ProviderName, eachAnyOf.ClusterName, eachAnyOf.ClusterLabelName, clustersWithName)
+ if err!=nil {
+ return Clusters{}, pkgerrors.Wrap(err, "intentResolverHelper error")
+ }
+ }
+ }
+ clusters := Clusters{clustersWithName}
+ return clusters, nil
+}
func (c *MockEtcd) GetAllKeys(path string) ([]string, error) {
var keys []string
- for k, _ := range c.Items {
+ for k := range c.Items {
keys = append(keys, string(k))
}
return keys, nil
Intent map[string]string `json:"intent"`
}
-
// ListOfIntents is a list of intents
type ListOfIntents struct {
ListOfIntents []map[string]string `json:"intent"`
}
-
// IntentManager is an interface which exposes the IntentManager functionality
type IntentManager interface {
AddIntent(a Intent, p string, ca string, v string, di string) (Intent, error)
return Intent{}, pkgerrors.New("Error getting Intent")
}
-
/*
GetIntentByName takes in IntentName, projectName, CompositeAppName, CompositeAppVersion
and deploymentIntentGroupName returns the list of intents under the IntentName.
return a.Spec, nil
}
-
/*
GetAllIntents takes in projectName, CompositeAppName, CompositeAppVersion,
DeploymentIntentName . It returns ListOfIntents.
return ListOfIntents{}, err
}
-
// DeleteIntent deletes a given intent tied to project, composite app and deployment intent group
func (c IntentClient) DeleteIntent(i string, p string, ca string, v string, di string) error {
k := IntentKey{
}
//AppContent contains fileContent
-// TODO : This should have been []byte
type AppContent struct {
FileContent string
}
"encoding/json"
"reflect"
+ gpic "github.com/onap/multicloud-k8s/src/orchestrator/pkg/gpic"
"github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
-
pkgerrors "github.com/pkg/errors"
)
UserData2 string `json:"userData2"`
}
-// AllOf consists of AnyOfArray and ClusterNames array
-type AllOf struct {
- ProviderName string `json:"provider-name,omitempty"`
- ClusterName string `json:"cluster-name,omitempty"`
- ClusterLabelName string `json:"cluster-label-name,omitempty"`
- AnyOfArray []AnyOf `json:"anyOf,omitempty"`
-}
-
-// AnyOf consists of Array of ProviderName & ClusterLabelNames
-type AnyOf struct {
- ProviderName string `json:"provider-name,omitempty"`
- ClusterName string `json:"cluster-name,omitempty"`
- ClusterLabelName string `json:"cluster-label-name,omitempty"`
-}
-
-// IntentStruc consists of AllOfArray and AnyOfArray
-type IntentStruc struct {
- AllOfArray []AllOf `json:"allOf,omitempty"`
- AnyOfArray []AnyOf `json:"anyOf,omitempty"`
-}
-
// SpecData consists of appName and intent
type SpecData struct {
- AppName string `json:"app-name"`
- Intent IntentStruc `json:"intent"`
+ AppName string `json:"app-name"`
+ Intent gpic.IntentStruc `json:"intent"`
}
// AppIntentManager is an interface which exposes the
// AppClusterInfo is a type linking the app and the clusters
// on which they need to be installed.
type AppClusterInfo struct {
- Name string `json:"name"`
- AllOfArray []AllOf `json:"allOf,omitempty"`
- AnyOfArray []AnyOf `json:"anyOf,omitempty"`
+ Name string `json:"name"`
+ AllOfArray []gpic.AllOf `json:"allOf,omitempty"`
+ AnyOfArray []gpic.AnyOf `json:"anyOf,omitempty"`
}
// We will use json marshalling to convert to string to
"strings"
"testing"
+ gpic "github.com/onap/multicloud-k8s/src/orchestrator/pkg/gpic"
"github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
)
},
Spec: SpecData{
AppName: "SampleApp",
- Intent: IntentStruc{
- AllOfArray: []AllOf{
+ Intent: gpic.IntentStruc{
+ AllOfArray: []gpic.AllOf{
{
ProviderName: "aws",
ClusterName: "edge1",
//ClusterLabelName: "edge2",
},
{
- AnyOfArray: []AnyOf{
+ AnyOfArray: []gpic.AnyOf{
{ProviderName: "aws",
ClusterLabelName: "east-us1"},
{ProviderName: "aws",
},
},
- AnyOfArray: []AnyOf{},
+ AnyOfArray: []gpic.AnyOf{},
},
},
},
},
Spec: SpecData{
AppName: "SampleApp",
- Intent: IntentStruc{
- AllOfArray: []AllOf{
+ Intent: gpic.IntentStruc{
+ AllOfArray: []gpic.AllOf{
{
ProviderName: "aws",
ClusterName: "edge1",
//ClusterLabelName: "edge2",
},
{
- AnyOfArray: []AnyOf{
+ AnyOfArray: []gpic.AnyOf{
{ProviderName: "aws",
ClusterLabelName: "east-us1"},
{ProviderName: "aws",
},
},
},
- AnyOfArray: []AnyOf{},
+ AnyOfArray: []gpic.AnyOf{},
},
},
},
},
Spec: SpecData{
AppName: "SampleApp",
- Intent: IntentStruc{
- AllOfArray: []AllOf{
+ Intent: gpic.IntentStruc{
+ AllOfArray: []gpic.AllOf{
{
ProviderName: "aws",
ClusterName: "edge1",
ClusterName: "edge2",
},
{
- AnyOfArray: []AnyOf{
+ AnyOfArray: []gpic.AnyOf{
{ProviderName: "aws",
ClusterLabelName: "east-us1"},
{ProviderName: "aws",
import (
"fmt"
- "github.com/onap/multicloud-k8s/src/orchestrator/utils/helm"
- pkgerrors "github.com/pkg/errors"
+ gpic "github.com/onap/multicloud-k8s/src/orchestrator/pkg/gpic"
"encoding/base64"
+
+ "github.com/onap/multicloud-k8s/src/orchestrator/utils/helm"
+ pkgerrors "github.com/pkg/errors"
"log"
)
// ManifestFileName is the name given to the manifest file in the profile package
const ManifestFileName = "manifest.yaml"
+// GenericPlacementIntentName denotes the generic placement intent name
+const GenericPlacementIntentName = "generic-placement-intent"
+
// InstantiationClient implements the InstantiationManager
type InstantiationClient struct {
storeName string
return map[string]string{}
}
+/*
+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) {
+ var gi string
+ var found bool
+ iList, err := NewIntentClient().GetAllIntents(p, ca, v, di)
+ if err != nil {
+ return gi, err
+ }
+ for _, eachMap := range iList.ListOfIntents {
+ if gi, found := eachMap[GenericPlacementIntentName]; found {
+ log.Printf("::Name of the generic-placement-intent:: %s", gi)
+ return gi, err
+ }
+ }
+ if found == false {
+ fmt.Println("generic-placement-intent not found !")
+ }
+ return gi, pkgerrors.New("Generic-placement-intent not found")
+
+}
+
// GetSortedTemplateForApp returns the sorted templates.
//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) {
overrideValues := dIGrp.Spec.OverrideValuesObj
cp := dIGrp.Spec.Profile
+ 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)
allApps, err := NewAppClient().GetApps(p, ca, v)
if err != nil {
}
log.Printf("Resolved all the templates for app :: %s under the compositeApp...", eachApp.Metadata.Name)
log.Printf("sortedTemplates :: %v ", sortedTemplates)
+
+ 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 {
+ return pkgerrors.Wrap(err, "Unable to get the intents resolved for app")
+ }
+ log.Printf("::listOfClusters:: %v", listOfClusters)
+
}
log.Printf("Done with instantiation...")
return err