aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajamohan Raj <rajamohan.raj@intel.com>2020-04-30 23:07:15 +0000
committerRajamohan Raj <rajamohan.raj@intel.com>2020-05-12 19:47:41 +0000
commit8fd7fd2ba9db1fb2dbe22c0cf89edb80454cff6d (patch)
tree867d42e86073a5b3ca3917096e8f99f8f791d448
parent8e0c00c4c59add2fa03a67081d74cd46934d034e (diff)
Create appContext and save to etcd
In this patch, following tasks are accomplished 1. Creation of appContext and storing the appcontexts for each app in the compositeApp into etcd as part of the instantiation process 2. Added a util method to extract parameters from k8s manifest files. 3. Added a new testing script to auto create NCM artifacts through the NCM APIs 4. Modified the existing plugin_collection_v2.sh to better test the orchestrator APIs. 5. Added logging to appcontext lib 6. Bug fix in the helm charts. Issue-ID: MULTICLOUD-1064 Signed-off-by: Rajamohan Raj <rajamohan.raj@intel.com> Change-Id: I1b0e4d1351ad3a083be529239748015ea5db2a41
-rwxr-xr-xkud/tests/plugin_collection_v2.sh67
-rwxr-xr-xkud/tests/plugin_ncm_v2.sh196
-rw-r--r--kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/role.yaml2
-rw-r--r--kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/rolebinding.yaml2
-rw-r--r--src/orchestrator/pkg/appcontext/appcontext.go13
-rw-r--r--src/orchestrator/pkg/gpic/gpic.go12
-rw-r--r--src/orchestrator/pkg/module/instantiation.go248
-rw-r--r--src/orchestrator/utils/utils.go100
8 files changed, 591 insertions, 49 deletions
diff --git a/kud/tests/plugin_collection_v2.sh b/kud/tests/plugin_collection_v2.sh
index 09dec5c4..5ebed6ad 100755
--- a/kud/tests/plugin_collection_v2.sh
+++ b/kud/tests/plugin_collection_v2.sh
@@ -33,6 +33,7 @@ if [ ${1:+1} ]; then
fi
base_url=${base_url:-"http://localhost:9015/v2"}
+
kubeconfig_path="$HOME/.kube/config"
csar_id=cb009bfe-bbee-11e8-9766-525400435678
@@ -69,12 +70,12 @@ appIntentNameForApp1="appIntentForApp1"
appIntentForApp1Desc="AppIntentForApp1Desc"
appIntentNameForApp2="appIntentForApp2"
appIntentForApp2Desc="AppIntentForApp2Desc"
-providerName1="aws"
-providerName2="azure"
-clusterName1="edge1"
-clusterName2="edge2"
-clusterLabelName1="east-us1"
-clusterLabelName2="east-us2"
+providerName1="cluster_provider1"
+providerName2="cluster_provider2"
+clusterName1="clusterName1"
+clusterName2="clusterName2"
+clusterLabelName1="clusterLabel1"
+clusterLabelName2="clusterLabel2"
deploymentIntentGroupName="test_deployment_intent_group"
deploymentIntentGroupNameDesc="test_deployment_intent_group_desc"
@@ -93,7 +94,53 @@ cloud_region_owner="localhost"
install_deps
populate_CSAR_composite_app_helm "$csar_id"
-# BEGIN: Register project API
+# BEGIN :: Delete statements are issued so that we clean up the 'orchestrator' collection
+# and freshly populate the documents, also it serves as a direct test
+# for all our DELETE APIs and an indirect test for all GET APIs
+
+
+print_msg "Deleting intentToBeAddedinDeploymentIntentGroup"
+delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/deployment-intent-groups/${deploymentIntentGroupName}/intents/${intentToBeAddedinDeploymentIntentGroup}"
+
+print_msg "Deleting ${deploymentIntentGroupName}"
+delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/deployment-intent-groups/${deploymentIntentGroupName}"
+
+print_msg "Deleting ${appIntentNameForApp2}"
+delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/generic-placement-intents/${genericPlacementIntentName}/app-intents/${appIntentNameForApp2}"
+
+print_msg "Deleting ${appIntentNameForApp1}"
+delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/generic-placement-intents/${genericPlacementIntentName}/app-intents/${appIntentNameForApp1}"
+
+print_msg "Deleting ${genericPlacementIntentName}"
+delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/generic-placement-intents/${genericPlacementIntentName}"
+
+print_msg "Deleting ${sub_composite_profile_name2}"
+delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/composite-profiles/${main_composite_profile_name}/profiles/${sub_composite_profile_name2}"
+
+print_msg "Deleting ${sub_composite_profile_name1}"
+delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/composite-profiles/${main_composite_profile_name}/profiles/${sub_composite_profile_name1}"
+
+print_msg "Deleting ${main_composite_profile_name}"
+delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/composite-profiles/${main_composite_profile_name}"
+
+print_msg "Deleting ${app2_name}"
+delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/apps/${app2_name}"
+
+print_msg "Deleting ${app1_name}"
+delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/apps/${app1_name}"
+
+print_msg "Deleting ${composite_app_name}/${composite_app_version}"
+delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}"
+
+print_msg "Deleting ${project_name}"
+delete_resource "${base_url}/projects/${project_name}"
+
+# END :: Delete statements were issued so that we clean up the db
+# and freshly populate the documents, also it serves as a direct test
+# for all our DELETE APIs and an indirect test for all GET APIs
+
+
+# BEGIN: Register project
print_msg "Registering project"
payload="$(cat <<EOF
{
@@ -107,9 +154,9 @@ payload="$(cat <<EOF
EOF
)"
call_api -d "${payload}" "${base_url}/projects"
-# END: Register project API
+# END: Register project
-# BEGIN: Register composite-app API
+# BEGIN: Register composite-app
print_msg "Registering composite-app"
payload="$(cat <<EOF
{
@@ -126,7 +173,7 @@ payload="$(cat <<EOF
EOF
)"
call_api -d "${payload}" "${base_url}/projects/${project_name}/composite-apps"
-# END: Register composite-app API
+# END: Register composite-app
diff --git a/kud/tests/plugin_ncm_v2.sh b/kud/tests/plugin_ncm_v2.sh
new file mode 100755
index 00000000..b7d791f3
--- /dev/null
+++ b/kud/tests/plugin_ncm_v2.sh
@@ -0,0 +1,196 @@
+# /*
+# * 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.
+# */
+
+set -o errexit
+set -o nounset
+set -o pipefail
+#set -o xtrace
+
+source _common_test.sh
+source _functions.sh
+source _common.sh
+
+base_url=${base_url:-"http://localhost:9016/v2"}
+
+kubeconfig_path="$HOME/.kube/config"
+
+cluster_provider_name1="cluster_provider1"
+cluster_provider_name2="cluster_provider2"
+cluster_provider_desc1="cluster_provider1_Desc"
+cluster_provider_desc2="cluster_provider2_Desc"
+userData1="user1"
+userData2="user2"
+
+clusterName1="clusterName1"
+cluster_desc1="cluster_desc1"
+clusterName2="clusterName2"
+cluster_desc2="cluster_desc2"
+#clusterName3 and clusterName4 shall be added with clusterLabel1 and clusterLabel2
+# under cluster_provider1 and cluster_provider2 respectively
+clusterName3="clusterName3"
+cluster_desc3="cluster_desc3"
+clusterName4="clusterName4"
+cluster_desc4="cluster_desc4"
+
+clusterLabel1="clusterLabel1"
+clusterLabel2="clusterLabel2"
+
+# BEGIN :: Delete statements are issued so that we clean up the 'cluster' collection
+# and freshly populate the documents, also it serves as a direct test
+# for all our DELETE APIs and an indirect test for all GET APIs
+print_msg "Deleting the clusterLabel1 and clusterLabel2, if they were existing"
+delete_resource "${base_url}/cluster-providers/${cluster_provider_name1}/clusters/${clusterName3}/labels/${clusterLabel1}"
+delete_resource "${base_url}/cluster-providers/${cluster_provider_name2}/clusters/${clusterName4}/labels/${clusterLabel2}"
+# Above statements delete the clusterLabel1 and clusterLabel2 which are linked to cluster3 and cluster4
+
+print_msg "Deleting the cluster1, cluster2, cluster3, cluster4 if they were existing"
+delete_resource "${base_url}/cluster-providers/${cluster_provider_name1}/clusters/${clusterName1}"
+delete_resource "${base_url}/cluster-providers/${cluster_provider_name2}/clusters/${clusterName2}"
+delete_resource "${base_url}/cluster-providers/${cluster_provider_name1}/clusters/${clusterName3}"
+delete_resource "${base_url}/cluster-providers/${cluster_provider_name2}/clusters/${clusterName4}"
+
+print_msg "Deleting the cluster-providers, if they were existing"
+delete_resource "${base_url}/cluster-providers/${cluster_provider_name1}"
+delete_resource "${base_url}/cluster-providers/${cluster_provider_name2}"
+
+# END :: Delete statements are issued so that we clean up the 'cluster' collection
+# and freshly populate the documents, also it serves as a direct test
+# for all our DELETE APIs and an indirect test for all GET APIs
+
+# BEGIN: Register cluster_provider_name1 and cluster_provider_name2
+print_msg "Deleting the cluster-providers, if they were existing"
+delete_resource "${base_url}/cluster-providers/${cluster_provider_name1}"
+delete_resource "${base_url}/cluster-providers/${cluster_provider_name2}"
+
+print_msg "Registering cluster_provider_name1"
+payload="$(cat <<EOF
+{
+ "metadata": {
+ "name": "${cluster_provider_name1}",
+ "description": "${cluster_provider_desc1}",
+ "userData1": "${userData1}",
+ "userData2": "${userData2}"
+ }
+}
+EOF
+)"
+call_api -d "${payload}" "${base_url}/cluster-providers"
+
+print_msg "Registering cluster_provider_name2"
+payload="$(cat <<EOF
+{
+ "metadata": {
+ "name": "${cluster_provider_name2}",
+ "description": "${cluster_provider_desc2}",
+ "userData1": "${userData1}",
+ "userData2": "${userData2}"
+ }
+}
+EOF
+)"
+call_api -d "${payload}" "${base_url}/cluster-providers"
+# END: Register cluster_provider_name1 and cluster_provider_name2
+
+# BEGIN : Register cluster1, cluster2, cluster3 and cluster4
+print_msg "Registering cluster1"
+payload="$(cat <<EOF
+{
+ "metadata": {
+ "name": "${clusterName1}",
+ "description": "${cluster_desc1}",
+ "userData1": "${userData1}",
+ "userData2": "${userData2}"
+ }
+}
+EOF
+)"
+call_api -F "metadata=$payload" \
+ -F "file=@$kubeconfig_path" \
+ "${base_url}/cluster-providers/${cluster_provider_name1}/clusters" >/dev/null #massive output
+
+
+print_msg "Registering cluster2"
+payload="$(cat <<EOF
+{
+ "metadata": {
+ "name": "${clusterName2}",
+ "description": "${cluster_desc2}",
+ "userData1": "${userData1}",
+ "userData2": "${userData2}"
+ }
+}
+EOF
+)"
+call_api -F "metadata=$payload" \
+ -F "file=@$kubeconfig_path" \
+ "${base_url}/cluster-providers/${cluster_provider_name2}/clusters" >/dev/null #massive output
+
+
+print_msg "Registering cluster3"
+payload="$(cat <<EOF
+{
+ "metadata": {
+ "name": "${clusterName3}",
+ "description": "${cluster_desc3}",
+ "userData1": "${userData1}",
+ "userData2": "${userData2}"
+ }
+}
+EOF
+)"
+call_api -F "metadata=$payload" \
+ -F "file=@$kubeconfig_path" \
+ "${base_url}/cluster-providers/${cluster_provider_name1}/clusters" >/dev/null #massive output
+
+
+print_msg "Registering cluster4"
+payload="$(cat <<EOF
+{
+ "metadata": {
+ "name": "${clusterName4}",
+ "description": "${cluster_desc4}",
+ "userData1": "${userData1}",
+ "userData2": "${userData2}"
+ }
+}
+EOF
+)"
+call_api -F "metadata=$payload" \
+ -F "file=@$kubeconfig_path" \
+ "${base_url}/cluster-providers/${cluster_provider_name2}/clusters" >/dev/null #massive output
+
+# END : Register cluster1, cluster2, cluster3 and cluster4
+
+
+# BEGIN: adding labels to cluster3 and cluster4
+print_msg "Adding label to cluster3"
+payload="$(cat <<EOF
+{
+ "label-name" : "${clusterLabel1}"
+}
+EOF
+)"
+call_api -d "${payload}" "${base_url}/cluster-providers/${cluster_provider_name1}/clusters/${clusterName3}/labels"
+
+print_msg "Adding label to cluster2"
+payload="$(cat <<EOF
+{
+ "label-name" : "${clusterLabel2}"
+}
+EOF
+)"
+call_api -d "${payload}" "${base_url}/cluster-providers/${cluster_provider_name2}/clusters/${clusterName4}/labels"
+
diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/role.yaml b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/role.yaml
index dfb932d8..a3c69c31 100644
--- a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/role.yaml
+++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/role.yaml
@@ -1,7 +1,5 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
-apiVersion: rbac.authorization.k8s.io/v1
-kind: Role
metadata:
name: {{ template "prometheus.fullname" . }}-prometheus
labels:
diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/rolebinding.yaml b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/rolebinding.yaml
index 04932ee1..a721cd42 100644
--- a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/rolebinding.yaml
+++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/rolebinding.yaml
@@ -1,7 +1,5 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
-apiVersion: rbac.authorization.k8s.io/v1
-kind: RoleBinding
metadata:
name: {{ template "prometheus.fullname" . }}-prometheus
labels:
diff --git a/src/orchestrator/pkg/appcontext/appcontext.go b/src/orchestrator/pkg/appcontext/appcontext.go
index d92b1d11..8f7841ac 100644
--- a/src/orchestrator/pkg/appcontext/appcontext.go
+++ b/src/orchestrator/pkg/appcontext/appcontext.go
@@ -22,6 +22,8 @@ import (
"github.com/onap/multicloud-k8s/src/orchestrator/pkg/rtcontext"
pkgerrors "github.com/pkg/errors"
+ //"log"
+ log "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/logutils"
)
type AppContext struct {
@@ -81,6 +83,7 @@ func (ac *AppContext) AddApp(handle interface{}, appname string) (interface{}, e
if err != nil {
return nil, err
}
+ log.Info(":: Added app handle ::", log.Fields{"AppHandle":h})
return h, nil
}
@@ -93,7 +96,7 @@ func (ac *AppContext) DeleteApp(handle interface{}) error {
return nil
}
-//Returns the hanlde for a given app
+//Returns the handle for a given app
func (ac *AppContext) GetAppHandle(appname string) (interface{}, error) {
if appname == "" {
return nil, pkgerrors.Errorf("Not a valid run time context app name")
@@ -123,6 +126,7 @@ func (ac *AppContext) AddCluster(handle interface{}, clustername string) (interf
if err != nil {
return nil, err
}
+ log.Info(":: Added cluster handle ::", log.Fields{"ClusterHandler":h})
return h, nil
}
@@ -193,11 +197,13 @@ func (ac *AppContext) GetClusterNames(appname string) ([]string, error) {
}
//Add resource under app and cluster
-func (ac *AppContext) AddResource(handle interface{}, resname string, value interface{}) (interface{}, error) {
+func (ac *AppContext) AddResource(handle interface{}, resname string, value []byte) (interface{}, error) {
h, err := ac.rtc.RtcAddResource(handle, resname, value)
if err != nil {
return nil, err
}
+ log.Info(":: Added resource handle ::", log.Fields{"ResourceHandler":h})
+
return h, nil
}
@@ -238,7 +244,7 @@ func (ac *AppContext) GetResourceHandle(appname string, clustername string, resn
}
//Update the resource value usign the given handle
-func (ac *AppContext) UpdateResourceValue(handle interface{}, value interface{}) error {
+func (ac *AppContext) UpdateResourceValue(handle interface{}, value []byte) error {
return ac.rtc.RtcUpdateValue(handle, value)
}
@@ -254,6 +260,7 @@ func (ac *AppContext) AddInstruction(handle interface{}, level string, insttype
if err != nil {
return nil, err
}
+ log.Info(":: Added instruction handle ::", log.Fields{"InstructionHandler":h})
return h, nil
}
diff --git a/src/orchestrator/pkg/gpic/gpic.go b/src/orchestrator/pkg/gpic/gpic.go
index f02e5352..256d3b41 100644
--- a/src/orchestrator/pkg/gpic/gpic.go
+++ b/src/orchestrator/pkg/gpic/gpic.go
@@ -22,14 +22,14 @@ package gpic
*/
import (
- "log"
ncmmodule "github.com/onap/multicloud-k8s/src/ncm/pkg/module"
pkgerrors "github.com/pkg/errors"
+ "log"
)
// Clusters has 1 field - a list of ClusterNames
type Clusters struct {
- ClustersWithName []ClusterWithName
+ ClustersWithName []ClusterWithName
}
// ClusterWithName has two fields - ProviderName and ClusterName
@@ -82,7 +82,7 @@ func intentResolverHelper(pn, cn, cln string, clustersWithName []ClusterWithName
for _, eachClusterName := range clusterNamesList {
eachClusterWithPN := ClusterWithName{pn, eachClusterName}
clustersWithName = append(clustersWithName, eachClusterWithPN)
- log.Printf("Added Cluster: %s ", cln)
+ log.Printf("Added Cluster :: %s through its label: %s ", eachClusterName, cln)
}
}
return clustersWithName, nil
@@ -95,13 +95,13 @@ func IntentResolver(intent IntentStruc) (Clusters, error) {
for _, eachAllOf := range intent.AllOfArray {
clustersWithName, err = intentResolverHelper(eachAllOf.ProviderName, eachAllOf.ClusterName, eachAllOf.ClusterLabelName, clustersWithName)
- if err!=nil {
+ 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 {
+ if err != nil {
return Clusters{}, pkgerrors.Wrap(err, "intentResolverHelper error")
}
}
@@ -110,7 +110,7 @@ func IntentResolver(intent IntentStruc) (Clusters, error) {
if len(intent.AnyOfArray) > 0 {
for _, eachAnyOf := range intent.AnyOfArray {
clustersWithName, err = intentResolverHelper(eachAnyOf.ProviderName, eachAnyOf.ClusterName, eachAnyOf.ClusterLabelName, clustersWithName)
- if err!=nil {
+ if err != nil {
return Clusters{}, pkgerrors.Wrap(err, "intentResolverHelper error")
}
}
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
}
diff --git a/src/orchestrator/utils/utils.go b/src/orchestrator/utils/utils.go
index 13c78ba4..22ce903b 100644
--- a/src/orchestrator/utils/utils.go
+++ b/src/orchestrator/utils/utils.go
@@ -19,15 +19,105 @@ package utils
import (
"archive/tar"
"compress/gzip"
+ "strings"
+
"io"
"io/ioutil"
+ "log"
"os"
"path"
"path/filepath"
pkgerrors "github.com/pkg/errors"
+ yaml "gopkg.in/yaml.v3"
)
+// ListYamlStruct is applied when the kind is list
+type ListYamlStruct struct {
+ APIVersion string `yaml:"apiVersion,omitempty"`
+ Kind string `yaml:"kind,omitempty"`
+ items []YamlStruct `yaml:"items,omitempty"`
+}
+
+// YamlStruct represents normal parameters in a manifest file.
+// Over the course of time, Pls add more parameters as and when you require.
+type YamlStruct struct {
+ APIVersion string `yaml:"apiVersion,omitempty"`
+ Kind string `yaml:"kind,omitempty"`
+ Metadata struct {
+ Name string `yaml:"name,omitempty"`
+ Namespace string `yaml:"namespace,omitempty"`
+ Labels struct {
+ RouterDeisIoRoutable string `yaml:"router.deis.io/routable,omitempty"`
+ } `yaml:"labels"`
+ Annotations struct {
+ RouterDeisIoDomains string `yaml:"router.deis.io/domains,omitempty"`
+ } `yaml:"annotations,omitempty"`
+ } `yaml:"metadata,omitempty"`
+ Spec struct {
+ Type string `yaml:"type,omitempty"`
+ Selector struct {
+ App string `yaml:"app,omitempty"`
+ } `yaml:"selector,omitempty"`
+ Ports []struct {
+ Name string `yaml:"name,omitempty"`
+ Port int `yaml:"port,omitempty"`
+ NodePort int `yaml:"nodePort,omitempty"`
+ } `yaml:"ports"`
+ } `yaml:"spec"`
+}
+
+func (y YamlStruct) isValid() bool {
+ if y.APIVersion == "" {
+ log.Printf("apiVersion is missing in manifest file")
+ return false
+ }
+ if y.Kind == "" {
+ log.Printf("kind is missing in manifest file")
+ return false
+ }
+ if y.Metadata.Name == "" {
+ log.Printf("metadata.name is missing in manifest file")
+ return false
+ }
+ return true
+}
+
+// ExtractYamlParameters is a method which takes in the abolute path of a manifest file
+// and returns a struct accordingly
+func ExtractYamlParameters(f string) (YamlStruct, error) {
+ filename, _ := filepath.Abs(f)
+ yamlFile, err := ioutil.ReadFile(filename)
+
+ var yamlStruct YamlStruct
+
+ err = yaml.Unmarshal(yamlFile, &yamlStruct)
+ if err != nil {
+ return YamlStruct{}, pkgerrors.New("Cant unmarshal yaml file ..")
+ }
+
+ /* This is a special case handling when the kind is "List".
+ When the kind is list and the metadata name is empty.
+ We set the metadata name as the file name. For eg:
+ if filename is "/tmp/helm-tmpl-240995533/prometheus/templates/serviceaccount.yaml-0".
+ We set metadata name as "serviceaccount.yaml-0"
+ Usually when the kind is list, the list might contains a list of
+ */
+ if yamlStruct.Kind == "List" && yamlStruct.Metadata.Name == "" {
+ li := strings.LastIndex(filename, "/")
+ fn := string(filename[li+1:])
+ yamlStruct.Metadata.Name = fn
+ log.Printf("Setting the metadata name as :: %s", fn)
+ }
+ if yamlStruct.isValid() {
+ log.Printf("YAML parameters for file ::%s \n %v", f, yamlStruct)
+ return yamlStruct, nil
+ }
+ log.Printf("YAML file ::%s has errors", f)
+ return YamlStruct{}, pkgerrors.Errorf("Cant extract parameters from yaml file :: %s", filename)
+
+}
+
//ExtractTarBall provides functionality to extract a tar.gz file
//into a temporary location for later use.
//It returns the path to the new location
@@ -114,3 +204,13 @@ func EnsureDirectory(f string) error {
}
return os.MkdirAll(base, 0755)
}
+
+// func main() {
+// filename := "./test.yaml"
+// yamlStruct, err := ExtractYamlParameters(filename)
+// if err!=nil {
+// log.Print(err)
+// }
+// fmt.Printf("%s+%s", yamlStruct.Metadata.Name, yamlStruct.Kind)
+// fmt.Printf("%v", yamlStruct)
+// }