summaryrefslogtreecommitdiffstats
path: root/src/orchestrator
diff options
context:
space:
mode:
Diffstat (limited to 'src/orchestrator')
-rw-r--r--src/orchestrator/api/add_intents_handler.go1
-rw-r--r--src/orchestrator/api/api.go3
-rw-r--r--src/orchestrator/api/composite_profilehandler_test.go2
-rw-r--r--src/orchestrator/api/controllerhandler.go106
-rw-r--r--src/orchestrator/api/controllerhandler_test.go57
-rw-r--r--src/orchestrator/api/projecthandler_test.go4
-rw-r--r--src/orchestrator/pkg/appcontext/appcontext.go34
-rw-r--r--src/orchestrator/pkg/gpic/gpic.go120
-rw-r--r--src/orchestrator/pkg/infra/contextdb/mock.go2
-rw-r--r--src/orchestrator/pkg/infra/validation/validation.go23
-rw-r--r--src/orchestrator/pkg/module/add_intents.go5
-rw-r--r--src/orchestrator/pkg/module/app.go1
-rw-r--r--src/orchestrator/pkg/module/app_intent.go33
-rw-r--r--src/orchestrator/pkg/module/app_intent_test.go23
-rw-r--r--src/orchestrator/pkg/module/controller.go75
-rw-r--r--src/orchestrator/pkg/module/controller_test.go39
-rw-r--r--src/orchestrator/pkg/module/instantiation.go50
-rw-r--r--src/orchestrator/pkg/module/module.go41
18 files changed, 519 insertions, 100 deletions
diff --git a/src/orchestrator/api/add_intents_handler.go b/src/orchestrator/api/add_intents_handler.go
index fbf9007d..ac8b400d 100644
--- a/src/orchestrator/api/add_intents_handler.go
+++ b/src/orchestrator/api/add_intents_handler.go
@@ -94,7 +94,6 @@ func (h intentHandler) getIntentByNameHandler(w http.ResponseWriter, r *http.Req
return
}
-
mapOfIntents, err := h.client.GetIntentByName(iN, p, ca, v, di)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
diff --git a/src/orchestrator/api/api.go b/src/orchestrator/api/api.go
index 6277d994..8b4b91a1 100644
--- a/src/orchestrator/api/api.go
+++ b/src/orchestrator/api/api.go
@@ -111,7 +111,8 @@ func NewRouter(projectClient moduleLib.ProjectManager,
router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/composite-profiles/{composite-profile-name}/profiles/{app-profile}", appProfileHandler.deleteAppProfileHandler).Methods("DELETE")
router.HandleFunc("/controllers", controlHandler.createHandler).Methods("POST")
- router.HandleFunc("/controllers", controlHandler.createHandler).Methods("PUT")
+ router.HandleFunc("/controllers", controlHandler.getHandler).Methods("GET")
+ router.HandleFunc("/controllers/{controller-name}", controlHandler.putHandler).Methods("PUT")
router.HandleFunc("/controllers/{controller-name}", controlHandler.getHandler).Methods("GET")
router.HandleFunc("/controllers/{controller-name}", controlHandler.deleteHandler).Methods("DELETE")
//setting routes for genericPlacementIntent
diff --git a/src/orchestrator/api/composite_profilehandler_test.go b/src/orchestrator/api/composite_profilehandler_test.go
index 42b9b3a1..ec3ec24b 100644
--- a/src/orchestrator/api/composite_profilehandler_test.go
+++ b/src/orchestrator/api/composite_profilehandler_test.go
@@ -105,7 +105,7 @@ func Test_compositeProfileHandler_createHandler(t *testing.T) {
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",
diff --git a/src/orchestrator/api/controllerhandler.go b/src/orchestrator/api/controllerhandler.go
index 4f98c023..1dad2bf8 100644
--- a/src/orchestrator/api/controllerhandler.go
+++ b/src/orchestrator/api/controllerhandler.go
@@ -22,7 +22,9 @@ import (
"net/http"
"github.com/gorilla/mux"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/validation"
moduleLib "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
+ pkgerrors "github.com/pkg/errors"
)
// Used to store backend implementations objects
@@ -33,6 +35,43 @@ type controllerHandler struct {
client moduleLib.ControllerManager
}
+// Check for valid format of input parameters
+func validateControllerInputs(c moduleLib.Controller) error {
+ // validate metadata
+ err := moduleLib.IsValidMetadata(c.Metadata)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Invalid controller metadata")
+ }
+
+ errs := validation.IsValidName(c.Spec.Host)
+ if len(errs) > 0 {
+ return pkgerrors.Errorf("Invalid host name for controller %v, errors: %v", c.Spec.Host, errs)
+ }
+
+ errs = validation.IsValidNumber(c.Spec.Port, 0, 65535)
+ if len(errs) > 0 {
+ return pkgerrors.Errorf("Invalid controller port [%v], errors: %v", c.Spec.Port, errs)
+ }
+
+ found := false
+ for _, val := range moduleLib.CONTROLLER_TYPES {
+ if c.Spec.Type == val {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return pkgerrors.Errorf("Invalid controller type: %v", c.Spec.Type)
+ }
+
+ errs = validation.IsValidNumber(c.Spec.Priority, moduleLib.MinControllerPriority, moduleLib.MaxControllerPriority)
+ if len(errs) > 0 {
+ return pkgerrors.Errorf("Invalid controller priority = [%v], errors: %v", c.Spec.Priority, errs)
+ }
+
+ return nil
+}
+
// Create handles creation of the controller entry in the database
func (h controllerHandler) createHandler(w http.ResponseWriter, r *http.Request) {
var m moduleLib.Controller
@@ -48,12 +87,12 @@ func (h controllerHandler) createHandler(w http.ResponseWriter, r *http.Request)
}
// Name is required.
- if m.Name == "" {
+ if m.Metadata.Name == "" {
http.Error(w, "Missing name in POST request", http.StatusBadRequest)
return
}
- ret, err := h.client.CreateController(m)
+ ret, err := h.client.CreateController(m, false)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -68,19 +107,74 @@ func (h controllerHandler) createHandler(w http.ResponseWriter, r *http.Request)
}
}
-// Get handles GET operations on a particular controller Name
-// Returns a controller
-func (h controllerHandler) getHandler(w http.ResponseWriter, r *http.Request) {
+// Put handles creation or update of the controller entry in the database
+func (h controllerHandler) putHandler(w http.ResponseWriter, r *http.Request) {
+ var m moduleLib.Controller
vars := mux.Vars(r)
name := vars["controller-name"]
- ret, err := h.client.GetController(name)
+ err := json.NewDecoder(r.Body).Decode(&m)
+ switch {
+ case err == io.EOF:
+ http.Error(w, "Empty body", http.StatusBadRequest)
+ return
+ case err != nil:
+ http.Error(w, err.Error(), http.StatusUnprocessableEntity)
+ return
+ }
+
+ // Name is required.
+ if m.Metadata.Name == "" {
+ http.Error(w, "Missing name in POST request", http.StatusBadRequest)
+ return
+ }
+
+ // name in URL should match name in body
+ if m.Metadata.Name != name {
+ http.Error(w, "Mismatched name in PUT request", http.StatusBadRequest)
+ return
+ }
+
+ ret, err := h.client.CreateController(m, true)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusCreated)
+ err = json.NewEncoder(w).Encode(ret)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+}
+
+// Get handles GET operations on a particular controller Name
+// Returns a controller
+func (h controllerHandler) getHandler(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ name := vars["controller-name"]
+ var ret interface{}
+ var err error
+
+ // handle the get all controllers case
+ if len(name) == 0 {
+ ret, err = h.client.GetControllers()
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ } else {
+
+ ret, err = h.client.GetController(name)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
+
+ w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
err = json.NewEncoder(w).Encode(ret)
if err != nil {
diff --git a/src/orchestrator/api/controllerhandler_test.go b/src/orchestrator/api/controllerhandler_test.go
index 3c543cb8..a2f93ea7 100644
--- a/src/orchestrator/api/controllerhandler_test.go
+++ b/src/orchestrator/api/controllerhandler_test.go
@@ -40,7 +40,7 @@ type mockControllerManager struct {
Err error
}
-func (m *mockControllerManager) CreateController(inp moduleLib.Controller) (moduleLib.Controller, error) {
+func (m *mockControllerManager) CreateController(inp moduleLib.Controller, mayExist bool) (moduleLib.Controller, error) {
if m.Err != nil {
return moduleLib.Controller{}, m.Err
}
@@ -56,6 +56,14 @@ func (m *mockControllerManager) GetController(name string) (moduleLib.Controller
return m.Items[0], nil
}
+func (m *mockControllerManager) GetControllers() ([]moduleLib.Controller, error) {
+ if m.Err != nil {
+ return []moduleLib.Controller{}, m.Err
+ }
+
+ return m.Items, nil
+}
+
func (m *mockControllerManager) DeleteController(name string) error {
return m.Err
}
@@ -77,22 +85,33 @@ func TestControllerCreateHandler(t *testing.T) {
label: "Create Controller",
expectedCode: http.StatusCreated,
reader: bytes.NewBuffer([]byte(`{
- "name":"testController",
+ "metadata": {
+ "name":"testController"
+ },
+ "spec": {
"ip-address":"10.188.234.1",
- "port":8080
+ "port":8080 }
}`)),
expected: moduleLib.Controller{
- Name: "testController",
- Host: "10.188.234.1",
- Port: 8080,
+ Metadata: moduleLib.Metadata{
+ Name: "testController",
+ },
+ Spec: moduleLib.ControllerSpec{
+ Host: "10.188.234.1",
+ Port: 8080,
+ },
},
controllerClient: &mockControllerManager{
//Items that will be returned by the mocked Client
Items: []moduleLib.Controller{
{
- Name: "testController",
- Host: "10.188.234.1",
- Port: 8080,
+ Metadata: moduleLib.Metadata{
+ Name: "testController",
+ },
+ Spec: moduleLib.ControllerSpec{
+ Host: "10.188.234.1",
+ Port: 8080,
+ },
},
},
},
@@ -144,17 +163,25 @@ func TestControllerGetHandler(t *testing.T) {
label: "Get Controller",
expectedCode: http.StatusOK,
expected: moduleLib.Controller{
- Name: "testController",
- Host: "10.188.234.1",
- Port: 8080,
+ Metadata: moduleLib.Metadata{
+ Name: "testController",
+ },
+ Spec: moduleLib.ControllerSpec{
+ Host: "10.188.234.1",
+ Port: 8080,
+ },
},
name: "testController",
controllerClient: &mockControllerManager{
Items: []moduleLib.Controller{
{
- Name: "testController",
- Host: "10.188.234.1",
- Port: 8080,
+ Metadata: moduleLib.Metadata{
+ Name: "testController",
+ },
+ Spec: moduleLib.ControllerSpec{
+ Host: "10.188.234.1",
+ Port: 8080,
+ },
},
},
},
diff --git a/src/orchestrator/api/projecthandler_test.go b/src/orchestrator/api/projecthandler_test.go
index 5e820aa2..0212e57a 100644
--- a/src/orchestrator/api/projecthandler_test.go
+++ b/src/orchestrator/api/projecthandler_test.go
@@ -95,7 +95,7 @@ func TestProjectCreateHandler(t *testing.T) {
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",
@@ -163,7 +163,7 @@ func TestProjectGetHandler(t *testing.T) {
name: "testProject",
projectClient: &mockProjectManager{
Items: []moduleLib.Project{
- moduleLib.Project{
+ {
MetaData: moduleLib.ProjectMetaData{
Name: "testProject",
Description: "Test Project used for unit testing",
diff --git a/src/orchestrator/pkg/appcontext/appcontext.go b/src/orchestrator/pkg/appcontext/appcontext.go
index bad5fa47..d92b1d11 100644
--- a/src/orchestrator/pkg/appcontext/appcontext.go
+++ b/src/orchestrator/pkg/appcontext/appcontext.go
@@ -18,6 +18,8 @@ package appcontext
import (
"fmt"
+ "strings"
+
"github.com/onap/multicloud-k8s/src/orchestrator/pkg/rtcontext"
pkgerrors "github.com/pkg/errors"
)
@@ -160,6 +162,36 @@ func (ac *AppContext) GetClusterHandle(appname string, clustername string) (inte
return nil, pkgerrors.Errorf("No handle was found for the given cluster")
}
+//Returns a list of all clusters for a given app
+func (ac *AppContext) GetClusterNames(appname string) ([]string, error) {
+ if appname == "" {
+ return nil, pkgerrors.Errorf("Not a valid run time context app name")
+ }
+
+ rh, err := ac.rtc.RtcGet()
+ if err != nil {
+ return nil, err
+ }
+
+ prefix := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/"
+ hs, err := ac.rtc.RtcGetHandles(prefix)
+ if err != nil {
+ return nil, pkgerrors.Errorf("Error getting handles for %v", prefix)
+ }
+ var cs []string
+ for _, h := range hs {
+ hstr := fmt.Sprintf("%v", h)
+ ks := strings.Split(hstr, prefix)
+ for _, k := range ks {
+ ck := strings.Split(k, "/")
+ if len(ck) == 2 && ck[1] == "" {
+ cs = append(cs, ck[0])
+ }
+ }
+ }
+ return cs, nil
+}
+
//Add resource under app and cluster
func (ac *AppContext) AddResource(handle interface{}, resname string, value interface{}) (interface{}, error) {
h, err := ac.rtc.RtcAddResource(handle, resname, value)
@@ -266,7 +298,7 @@ func (ac *AppContext) GetResourceInstruction(appname string, clustername string,
if err != nil {
return nil, err
}
- s := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/" + clustername + "/resource/instruction/" + insttype
+ s := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/" + clustername + "/resource/instruction/" + insttype + "/"
var v string
err = ac.rtc.RtcGetValue(s, &v)
if err != nil {
diff --git a/src/orchestrator/pkg/gpic/gpic.go b/src/orchestrator/pkg/gpic/gpic.go
new file mode 100644
index 00000000..f02e5352
--- /dev/null
+++ b/src/orchestrator/pkg/gpic/gpic.go
@@ -0,0 +1,120 @@
+/*
+ * 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
+}
diff --git a/src/orchestrator/pkg/infra/contextdb/mock.go b/src/orchestrator/pkg/infra/contextdb/mock.go
index fc0f8ff7..9aaed750 100644
--- a/src/orchestrator/pkg/infra/contextdb/mock.go
+++ b/src/orchestrator/pkg/infra/contextdb/mock.go
@@ -47,7 +47,7 @@ func (c *MockEtcd) Delete(key string) error {
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
diff --git a/src/orchestrator/pkg/infra/validation/validation.go b/src/orchestrator/pkg/infra/validation/validation.go
index 448ea5de..c43d29ec 100644
--- a/src/orchestrator/pkg/infra/validation/validation.go
+++ b/src/orchestrator/pkg/infra/validation/validation.go
@@ -23,6 +23,7 @@ import (
"io"
"net"
"regexp"
+ "strconv"
"strings"
pkgerrors "github.com/pkg/errors"
@@ -280,6 +281,28 @@ func IsValidNumber(value, min, max int) []string {
return errs
}
+func IsValidNumberStr(value string, min, max int) []string {
+ var errs []string
+
+ if min > max {
+ errs = append(errs, "invalid constraints")
+ return errs
+ }
+
+ n, err := strconv.Atoi(value)
+ if err != nil {
+ errs = append(errs, err.Error())
+ return errs
+ }
+ if n < min {
+ errs = append(errs, "value less than minimum")
+ }
+ if n > max {
+ errs = append(errs, "value greater than maximum")
+ }
+ return errs
+}
+
/*
IsValidParameterPresent method takes in a vars map and a array of string parameters
that you expect to be present in the GET request.
diff --git a/src/orchestrator/pkg/module/add_intents.go b/src/orchestrator/pkg/module/add_intents.go
index a4d677b7..89bf255f 100644
--- a/src/orchestrator/pkg/module/add_intents.go
+++ b/src/orchestrator/pkg/module/add_intents.go
@@ -49,13 +49,11 @@ type IntentSpecData struct {
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)
@@ -175,7 +173,6 @@ func (c *IntentClient) GetIntent(i string, p string, ca string, v string, di str
return Intent{}, pkgerrors.New("Error getting Intent")
}
-
/*
GetIntentByName takes in IntentName, projectName, CompositeAppName, CompositeAppVersion
and deploymentIntentGroupName returns the list of intents under the IntentName.
@@ -200,7 +197,6 @@ func (c IntentClient) GetIntentByName(i string, p string, ca string, v string, d
return a.Spec, nil
}
-
/*
GetAllIntents takes in projectName, CompositeAppName, CompositeAppVersion,
DeploymentIntentName . It returns ListOfIntents.
@@ -236,7 +232,6 @@ func (c IntentClient) GetAllIntents(p string, ca string, v string, di string) (L
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{
diff --git a/src/orchestrator/pkg/module/app.go b/src/orchestrator/pkg/module/app.go
index 40659de8..1e1a5974 100644
--- a/src/orchestrator/pkg/module/app.go
+++ b/src/orchestrator/pkg/module/app.go
@@ -38,7 +38,6 @@ type AppMetaData struct {
}
//AppContent contains fileContent
-// TODO : This should have been []byte
type AppContent struct {
FileContent string
}
diff --git a/src/orchestrator/pkg/module/app_intent.go b/src/orchestrator/pkg/module/app_intent.go
index 5f4acb4d..9da252e5 100644
--- a/src/orchestrator/pkg/module/app_intent.go
+++ b/src/orchestrator/pkg/module/app_intent.go
@@ -25,8 +25,8 @@ import (
"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"
)
@@ -44,31 +44,10 @@ type MetaData struct {
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
@@ -112,9 +91,9 @@ type ApplicationsAndClusterInfo struct {
// 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
diff --git a/src/orchestrator/pkg/module/app_intent_test.go b/src/orchestrator/pkg/module/app_intent_test.go
index 726ce0a3..089f09ff 100644
--- a/src/orchestrator/pkg/module/app_intent_test.go
+++ b/src/orchestrator/pkg/module/app_intent_test.go
@@ -21,6 +21,7 @@ import (
"strings"
"testing"
+ gpic "github.com/onap/multicloud-k8s/src/orchestrator/pkg/gpic"
"github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
)
@@ -47,8 +48,8 @@ func TestCreateAppIntent(t *testing.T) {
},
Spec: SpecData{
AppName: "SampleApp",
- Intent: IntentStruc{
- AllOfArray: []AllOf{
+ Intent: gpic.IntentStruc{
+ AllOfArray: []gpic.AllOf{
{
ProviderName: "aws",
ClusterName: "edge1",
@@ -60,7 +61,7 @@ func TestCreateAppIntent(t *testing.T) {
//ClusterLabelName: "edge2",
},
{
- AnyOfArray: []AnyOf{
+ AnyOfArray: []gpic.AnyOf{
{ProviderName: "aws",
ClusterLabelName: "east-us1"},
{ProviderName: "aws",
@@ -71,7 +72,7 @@ func TestCreateAppIntent(t *testing.T) {
},
},
- AnyOfArray: []AnyOf{},
+ AnyOfArray: []gpic.AnyOf{},
},
},
},
@@ -89,8 +90,8 @@ func TestCreateAppIntent(t *testing.T) {
},
Spec: SpecData{
AppName: "SampleApp",
- Intent: IntentStruc{
- AllOfArray: []AllOf{
+ Intent: gpic.IntentStruc{
+ AllOfArray: []gpic.AllOf{
{
ProviderName: "aws",
ClusterName: "edge1",
@@ -102,7 +103,7 @@ func TestCreateAppIntent(t *testing.T) {
//ClusterLabelName: "edge2",
},
{
- AnyOfArray: []AnyOf{
+ AnyOfArray: []gpic.AnyOf{
{ProviderName: "aws",
ClusterLabelName: "east-us1"},
{ProviderName: "aws",
@@ -112,7 +113,7 @@ func TestCreateAppIntent(t *testing.T) {
},
},
},
- AnyOfArray: []AnyOf{},
+ AnyOfArray: []gpic.AnyOf{},
},
},
},
@@ -202,8 +203,8 @@ func TestGetAppIntent(t *testing.T) {
},
Spec: SpecData{
AppName: "SampleApp",
- Intent: IntentStruc{
- AllOfArray: []AllOf{
+ Intent: gpic.IntentStruc{
+ AllOfArray: []gpic.AllOf{
{
ProviderName: "aws",
ClusterName: "edge1",
@@ -213,7 +214,7 @@ func TestGetAppIntent(t *testing.T) {
ClusterName: "edge2",
},
{
- AnyOfArray: []AnyOf{
+ AnyOfArray: []gpic.AnyOf{
{ProviderName: "aws",
ClusterLabelName: "east-us1"},
{ProviderName: "aws",
diff --git a/src/orchestrator/pkg/module/controller.go b/src/orchestrator/pkg/module/controller.go
index 35d6f892..976b8988 100644
--- a/src/orchestrator/pkg/module/controller.go
+++ b/src/orchestrator/pkg/module/controller.go
@@ -27,13 +27,24 @@ import (
// Controller contains the parameters needed for Controllers
// It implements the interface for managing the Controllers
type Controller struct {
- Name string `json:"name"`
-
- Host string `json:"host"`
+ Metadata Metadata `json:"metadata"`
+ Spec ControllerSpec `json:"spec"`
+}
- Port int64 `json:"port"`
+type ControllerSpec struct {
+ Host string `json:"host"`
+ Port int `json:"port"`
+ Type string `json:"type"`
+ Priority int `json:"priority"`
}
+const MinControllerPriority = 1
+const MaxControllerPriority = 1000000
+const CONTROLLER_TYPE_ACTION string = "action"
+const CONTROLLER_TYPE_PLACEMENT string = "placement"
+
+var CONTROLLER_TYPES = [...]string{CONTROLLER_TYPE_ACTION, CONTROLLER_TYPE_PLACEMENT}
+
// ControllerKey is the key structure that is used in the database
type ControllerKey struct {
ControllerName string `json:"controller-name"`
@@ -52,8 +63,9 @@ func (mk ControllerKey) String() string {
// ControllerManager is an interface exposes the Controller functionality
type ControllerManager interface {
- CreateController(ms Controller) (Controller, error)
+ CreateController(ms Controller, mayExist bool) (Controller, error)
GetController(name string) (Controller, error)
+ GetControllers() ([]Controller, error)
DeleteController(name string) error
}
@@ -74,20 +86,20 @@ func NewControllerClient() *ControllerClient {
}
// CreateController a new collection based on the Controller
-func (mc *ControllerClient) CreateController(m Controller) (Controller, error) {
+func (mc *ControllerClient) CreateController(m Controller, mayExist bool) (Controller, error) {
//Construct the composite key to select the entry
key := ControllerKey{
- ControllerName: m.Name,
+ ControllerName: m.Metadata.Name,
}
//Check if this Controller already exists
- _, err := mc.GetController(m.Name)
- if err == nil {
+ _, err := mc.GetController(m.Metadata.Name)
+ if err == nil && !mayExist {
return Controller{}, pkgerrors.New("Controller already exists")
}
- err = db.DBconn.Create(mc.collectionName, key, mc.tagMeta, m)
+ err = db.DBconn.Insert(mc.collectionName, key, nil, mc.tagMeta, m)
if err != nil {
return Controller{}, pkgerrors.Wrap(err, "Creating DB Entry")
}
@@ -102,15 +114,14 @@ func (mc *ControllerClient) GetController(name string) (Controller, error) {
key := ControllerKey{
ControllerName: name,
}
- value, err := db.DBconn.Read(mc.collectionName, key, mc.tagMeta)
+ value, err := db.DBconn.Find(mc.collectionName, key, mc.tagMeta)
if err != nil {
return Controller{}, pkgerrors.Wrap(err, "Get Controller")
}
- //value is a byte array
if value != nil {
microserv := Controller{}
- err = db.DBconn.Unmarshal(value, &microserv)
+ err = db.DBconn.Unmarshal(value[0], &microserv)
if err != nil {
return Controller{}, pkgerrors.Wrap(err, "Unmarshaling Value")
}
@@ -120,6 +131,42 @@ func (mc *ControllerClient) GetController(name string) (Controller, error) {
return Controller{}, pkgerrors.New("Error getting Controller")
}
+// GetControllers returns all the Controllers that are registered
+func (mc *ControllerClient) GetControllers() ([]Controller, error) {
+
+ //Construct the composite key to select the entry
+ key := ControllerKey{
+ ControllerName: "",
+ }
+
+ var resp []Controller
+ values, err := db.DBconn.Find(mc.collectionName, key, mc.tagMeta)
+ if err != nil {
+ return []Controller{}, pkgerrors.Wrap(err, "Get Controller")
+ }
+
+ for _, value := range values {
+ microserv := Controller{}
+ err = db.DBconn.Unmarshal(value, &microserv)
+ if err != nil {
+ return []Controller{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+ }
+
+ // run healthcheck
+ /*
+ err = mc.HealthCheck(microserv.Name)
+ if err != nil {
+ log.Warn("HealthCheck Failed", log.Fields{
+ "Controller": microserv.Name,
+ })
+ }
+ */
+ resp = append(resp, microserv)
+ }
+
+ return resp, nil
+}
+
// DeleteController the Controller from database
func (mc *ControllerClient) DeleteController(name string) error {
@@ -127,7 +174,7 @@ func (mc *ControllerClient) DeleteController(name string) error {
key := ControllerKey{
ControllerName: name,
}
- err := db.DBconn.Delete(name, key, mc.tagMeta)
+ err := db.DBconn.Remove(mc.collectionName, key)
if err != nil {
return pkgerrors.Wrap(err, "Delete Controller Entry;")
}
diff --git a/src/orchestrator/pkg/module/controller_test.go b/src/orchestrator/pkg/module/controller_test.go
index 2e783c13..a13f43a5 100644
--- a/src/orchestrator/pkg/module/controller_test.go
+++ b/src/orchestrator/pkg/module/controller_test.go
@@ -37,14 +37,22 @@ func TestCreateController(t *testing.T) {
{
label: "Create Controller",
inp: Controller{
- Name: "testController",
- Host: "132.156.0.10",
- Port: 8080,
+ Metadata: Metadata{
+ Name: "testController",
+ },
+ Spec: ControllerSpec{
+ Host: "132.156.0.10",
+ Port: 8080,
+ },
},
expected: Controller{
- Name: "testController",
- Host: "132.156.0.10",
- Port: 8080,
+ Metadata: Metadata{
+ Name: "testController",
+ },
+ Spec: ControllerSpec{
+ Host: "132.156.0.10",
+ Port: 8080,
+ },
},
expectedError: "",
mockdb: &db.MockDB{},
@@ -62,7 +70,7 @@ func TestCreateController(t *testing.T) {
t.Run(testCase.label, func(t *testing.T) {
db.DBconn = testCase.mockdb
impl := NewControllerClient()
- got, err := impl.CreateController(testCase.inp)
+ got, err := impl.CreateController(testCase.inp, false)
if err != nil {
if testCase.expectedError == "" {
t.Fatalf("Create returned an unexpected error %s", err)
@@ -94,18 +102,25 @@ func TestGetController(t *testing.T) {
label: "Get Controller",
name: "testController",
expected: Controller{
- Name: "testController",
- Host: "132.156.0.10",
- Port: 8080,
+ Metadata: Metadata{
+ Name: "testController",
+ },
+ Spec: ControllerSpec{
+ Host: "132.156.0.10",
+ Port: 8080,
+ },
},
expectedError: "",
mockdb: &db.MockDB{
Items: map[string]map[string][]byte{
ControllerKey{ControllerName: "testController"}.String(): {
"controllermetadata": []byte(
- "{\"name\":\"testController\"," +
+ "{\"metadata\":{" +
+ "\"name\":\"testController\"" +
+ "}," +
+ "\"spec\":{" +
"\"host\":\"132.156.0.10\"," +
- "\"port\":8080}"),
+ "\"port\": 8080 }}"),
},
},
},
diff --git a/src/orchestrator/pkg/module/instantiation.go b/src/orchestrator/pkg/module/instantiation.go
index 5fabe81e..56021547 100644
--- a/src/orchestrator/pkg/module/instantiation.go
+++ b/src/orchestrator/pkg/module/instantiation.go
@@ -18,17 +18,22 @@ package module
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
@@ -64,6 +69,30 @@ func getOverrideValuesByAppName(ov []OverrideValues, a string) map[string]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) {
@@ -124,6 +153,12 @@ 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)
+ 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 {
@@ -136,6 +171,17 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin
}
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
diff --git a/src/orchestrator/pkg/module/module.go b/src/orchestrator/pkg/module/module.go
index e05b8753..463a55b3 100644
--- a/src/orchestrator/pkg/module/module.go
+++ b/src/orchestrator/pkg/module/module.go
@@ -16,6 +16,11 @@
package module
+import (
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/validation"
+ pkgerrors "github.com/pkg/errors"
+)
+
// Client for using the services in the orchestrator
type Client struct {
Project *ProjectClient
@@ -49,3 +54,39 @@ func NewClient() *Client {
c.Instantiation = NewInstantiationClient()
return c
}
+
+// It implements the interface for managing the ClusterProviders
+const MAX_DESCRIPTION_LEN int = 1024
+const MAX_USERDATA_LEN int = 4096
+
+type Metadata struct {
+ Name string `json:"name" yaml:"name"`
+ Description string `json:"description" yaml:"-"`
+ UserData1 string `json:"userData1" yaml:"-"`
+ UserData2 string `json:"userData2" yaml:"-"`
+}
+
+// Check for valid format Metadata
+func IsValidMetadata(metadata Metadata) error {
+ errs := validation.IsValidName(metadata.Name)
+ if len(errs) > 0 {
+ return pkgerrors.Errorf("Invalid Metadata name=[%v], errors: %v", metadata.Name, errs)
+ }
+
+ errs = validation.IsValidString(metadata.Description, 0, MAX_DESCRIPTION_LEN, validation.VALID_ANY_STR)
+ if len(errs) > 0 {
+ return pkgerrors.Errorf("Invalid Metadata description=[%v], errors: %v", metadata.Description, errs)
+ }
+
+ errs = validation.IsValidString(metadata.UserData1, 0, MAX_DESCRIPTION_LEN, validation.VALID_ANY_STR)
+ if len(errs) > 0 {
+ return pkgerrors.Errorf("Invalid Metadata description=[%v], errors: %v", metadata.UserData1, errs)
+ }
+
+ errs = validation.IsValidString(metadata.UserData2, 0, MAX_DESCRIPTION_LEN, validation.VALID_ANY_STR)
+ if len(errs) > 0 {
+ return pkgerrors.Errorf("Invalid Metadata description=[%v], errors: %v", metadata.UserData2, errs)
+ }
+
+ return nil
+}