summaryrefslogtreecommitdiffstats
path: root/src/orchestrator/pkg
diff options
context:
space:
mode:
authorRajamohan Raj <rajamohan.raj@intel.com>2020-02-24 21:59:44 +0000
committerRajamohan Raj <rajamohan.raj@intel.com>2020-03-03 23:08:13 +0000
commit37aed9b7a0db62b9931d89c614ff6291cc4608cc (patch)
tree51021b0776978d77c4a1cad455be582a4dafa894 /src/orchestrator/pkg
parent7b566f2875230e15f79a6549b17240e767cc98f1 (diff)
Implemented AppIntents and GenPlaceIntents
Implemented the routes for creating, getting, and deleting generic placement intents and App intents. Issue-ID: MULTICLOUD-875 Signed-off-by: Rajamohan Raj <rajamohan.raj@intel.com> Change-Id: Iecb11c442958a43a517772e066de45213e3d7030
Diffstat (limited to 'src/orchestrator/pkg')
-rw-r--r--src/orchestrator/pkg/infra/db/mock.go21
-rw-r--r--src/orchestrator/pkg/infra/db/mongo_test.go3
-rw-r--r--src/orchestrator/pkg/module/app_intent.go195
-rw-r--r--src/orchestrator/pkg/module/app_intent_test.go271
-rw-r--r--src/orchestrator/pkg/module/generic_placement_intent.go165
-rw-r--r--src/orchestrator/pkg/module/generic_placement_intent_test.go184
-rw-r--r--src/orchestrator/pkg/module/module.go10
7 files changed, 844 insertions, 5 deletions
diff --git a/src/orchestrator/pkg/infra/db/mock.go b/src/orchestrator/pkg/infra/db/mock.go
index 6b46a524..79366d10 100644
--- a/src/orchestrator/pkg/infra/db/mock.go
+++ b/src/orchestrator/pkg/infra/db/mock.go
@@ -45,6 +45,10 @@ func (m *MockDB) Create(table string, key Key, tag string, data interface{}) err
return m.Err
}
+func (m *MockDB) Insert(table string, key Key, query interface{}, tag string, data interface{}) error {
+ return m.Err
+}
+
func (m *MockDB) Update(table string, key Key, tag string, data interface{}) error {
return m.Err
}
@@ -73,7 +77,22 @@ func (m *MockDB) Read(table string, key Key, tag string) ([]byte, error) {
return nil, m.Err
}
+func (m *MockDB) Find(table string, key Key, tag string) ([][]byte, error) {
+ if m.Err != nil {
+ return nil, m.Err
+ }
+
+ str := fmt.Sprintf("%v", key)
+ for k, v := range m.Items {
+ if k == str {
+
+ return [][]byte{v[tag]}, nil
+ }
+ }
+
+ return nil, m.Err
+}
+
func (m *MockDB) Delete(table string, key Key, tag string) error {
return m.Err
}
-
diff --git a/src/orchestrator/pkg/infra/db/mongo_test.go b/src/orchestrator/pkg/infra/db/mongo_test.go
index d506dbda..9f813ca4 100644
--- a/src/orchestrator/pkg/infra/db/mongo_test.go
+++ b/src/orchestrator/pkg/infra/db/mongo_test.go
@@ -76,7 +76,7 @@ func (c *mockCollection) DeleteMany(ctx context.Context, filter interface{},
func (c *mockCollection) UpdateOne(ctx context.Context, filter interface{}, update interface{},
opts ...*options.UpdateOptions) (*mongo.UpdateResult, error) {
- return nil, c.Err
+ return nil, c.Err
}
func TestCreate(t *testing.T) {
@@ -463,4 +463,3 @@ func TestDelete(t *testing.T) {
})
}
}
-
diff --git a/src/orchestrator/pkg/module/app_intent.go b/src/orchestrator/pkg/module/app_intent.go
new file mode 100644
index 00000000..70c80dac
--- /dev/null
+++ b/src/orchestrator/pkg/module/app_intent.go
@@ -0,0 +1,195 @@
+/*
+ * 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 module
+
+import (
+ "encoding/json"
+ "reflect"
+
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+
+ pkgerrors "github.com/pkg/errors"
+)
+
+// AppIntent has two components - metadata, spec
+type AppIntent struct {
+ MetaData MetaData `json:"metadata"`
+ Spec SpecData `json:"spec"`
+}
+
+// MetaData has - name, description, userdata1, userdata2
+type MetaData struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+ UserData1 string `json:"userData1"`
+ UserData2 string `json:"userData2"`
+}
+
+// AllOf consists of AnyOfArray and ClusterNames array
+type AllOf struct {
+ ClusterName string `json:"cluster-name,omitempty"`
+ ClusterLabelName string `json:"cluster-label-name,omitempty"`
+ AnyOfArray []AnyOf `json:"anyOf,omitempty"`
+}
+
+// AnyOf consists of Array of ClusterLabelNames
+type AnyOf struct {
+ 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"`
+}
+
+// AppIntentManager is an interface which exposes the
+// AppIntentManager functionalities
+type AppIntentManager interface {
+ CreateAppIntent(a AppIntent, p string, ca string, v string, i string) (AppIntent, error)
+ GetAppIntent(ai string, p string, ca string, v string, i string) (AppIntent, error)
+ DeleteAppIntent(ai string, p string, ca string, v string, i string) error
+}
+
+// AppIntentKey is used as primary key
+type AppIntentKey struct {
+ Name string `json:"name"`
+ Project string `json:"project"`
+ CompositeApp string `json:"compositeapp"`
+ Version string `json:"version"`
+ Intent string `json:"intent-name"`
+}
+
+// We will use json marshalling to convert to string to
+// preserve the underlying structure.
+func (ak AppIntentKey) String() string {
+ out, err := json.Marshal(ak)
+ if err != nil {
+ return ""
+ }
+ return string(out)
+}
+
+// AppIntentClient implements the AppIntentManager interface
+type AppIntentClient struct {
+ storeName string
+ tagMetaData string
+}
+
+// NewAppIntentClient returns an instance of AppIntentClient
+func NewAppIntentClient() *AppIntentClient {
+ return &AppIntentClient{
+ storeName: "orchestrator",
+ tagMetaData: "appintent",
+ }
+}
+
+// CreateAppIntent creates an entry for AppIntent in the db. Other input parameters for it - projectName, compositeAppName, version, intentName.
+func (c *AppIntentClient) CreateAppIntent(a AppIntent, p string, ca string, v string, i string) (AppIntent, error) {
+
+ //Check for the AppIntent already exists here.
+ res, err := c.GetAppIntent(a.MetaData.Name, p, ca, v, i)
+ if !reflect.DeepEqual(res, AppIntent{}) {
+ return AppIntent{}, pkgerrors.New("AppIntent already exists")
+ }
+
+ //Check if project exists
+ _, err = NewProjectClient().GetProject(p)
+ if err != nil {
+ return AppIntent{}, pkgerrors.New("Unable to find the project")
+ }
+
+ // check if compositeApp exists
+ _, err = NewCompositeAppClient().GetCompositeApp(ca, v, p)
+ if err != nil {
+ return AppIntent{}, pkgerrors.New("Unable to find the composite-app")
+ }
+
+ // check if Intent exists
+ _, err = NewGenericPlacementIntentClient().GetGenericPlacementIntent(i, p, ca, v)
+ if err != nil {
+ return AppIntent{}, pkgerrors.New("Unable to find the intent")
+ }
+
+ akey := AppIntentKey{
+ Name: a.MetaData.Name,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ Intent: i,
+ }
+
+ err = db.DBconn.Insert(c.storeName, akey, nil, c.tagMetaData, a)
+ if err != nil {
+ return AppIntent{}, pkgerrors.Wrap(err, "Create DB entry error")
+ }
+
+ return a, nil
+}
+
+// GetAppIntent shall take arguments - name of the app intent, name of the project, name of the composite app, version of the composite app and intent name. It shall return the AppIntent
+func (c *AppIntentClient) GetAppIntent(ai string, p string, ca string, v string, i string) (AppIntent, error) {
+
+ k := AppIntentKey{
+ Name: ai,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ Intent: i,
+ }
+
+ result, err := db.DBconn.Find(c.storeName, k, c.tagMetaData)
+ if err != nil {
+ return AppIntent{}, pkgerrors.Wrap(err, "Get AppIntent error")
+ }
+
+ if result != nil {
+ a := AppIntent{}
+ err = db.DBconn.Unmarshal(result[0], &a)
+ if err != nil {
+ return AppIntent{}, pkgerrors.Wrap(err, "Unmarshalling AppIntent")
+ }
+ return a, nil
+
+ }
+ return AppIntent{}, pkgerrors.New("Error getting AppIntent")
+}
+
+// DeleteAppIntent delete an AppIntent
+func (c *AppIntentClient) DeleteAppIntent(ai string, p string, ca string, v string, i string) error {
+ k := AppIntentKey{
+ Name: ai,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ Intent: i,
+ }
+
+ err := db.DBconn.Remove(c.storeName, k)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Delete Project entry;")
+ }
+ return nil
+
+}
diff --git a/src/orchestrator/pkg/module/app_intent_test.go b/src/orchestrator/pkg/module/app_intent_test.go
new file mode 100644
index 00000000..5a4f7693
--- /dev/null
+++ b/src/orchestrator/pkg/module/app_intent_test.go
@@ -0,0 +1,271 @@
+/*
+ * 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 module
+
+import (
+ "reflect"
+ "strings"
+ "testing"
+
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+)
+
+func TestCreateAppIntent(t *testing.T) {
+ testCases := []struct {
+ label string
+ inputAppIntent AppIntent
+ inputProject string
+ inputCompositeApp string
+ inputCompositeAppVersion string
+ inputGenericPlacementIntent string
+ expectedError string
+ mockdb *db.MockDB
+ expected AppIntent
+ }{
+ {
+ label: "Create AppIntent",
+ inputAppIntent: AppIntent{
+ MetaData: MetaData{
+ Name: "testAppIntent",
+ Description: "A sample AppIntent",
+ UserData1: "userData1",
+ UserData2: "userData2",
+ },
+ Spec: SpecData{
+ AppName: "SampleApp",
+ Intent: IntentStruc{
+ AllOfArray: []AllOf{
+ {
+ ClusterName: "edge1",
+ //ClusterLabelName: "edge1",
+ },
+ {
+ ClusterName: "edge2",
+ //ClusterLabelName: "edge2",
+ },
+ {
+ AnyOfArray: []AnyOf{
+ {ClusterLabelName: "east-us1"},
+ {ClusterLabelName: "east-us2"},
+ //{ClusterName: "east-us1"},
+ //{ClusterName: "east-us2"},
+ },
+ },
+ },
+
+ AnyOfArray: []AnyOf{},
+ },
+ },
+ },
+
+ inputProject: "testProject",
+ inputCompositeApp: "testCompositeApp",
+ inputCompositeAppVersion: "testCompositeAppVersion",
+ inputGenericPlacementIntent: "testIntent",
+ expected: AppIntent{
+ MetaData: MetaData{
+ Name: "testAppIntent",
+ Description: "A sample AppIntent",
+ UserData1: "userData1",
+ UserData2: "userData2",
+ },
+ Spec: SpecData{
+ AppName: "SampleApp",
+ Intent: IntentStruc{
+ AllOfArray: []AllOf{
+ {
+ ClusterName: "edge1",
+ //ClusterLabelName: "edge1",
+ },
+ {
+ ClusterName: "edge2",
+ //ClusterLabelName: "edge2",
+ },
+ {
+ AnyOfArray: []AnyOf{
+ {ClusterLabelName: "east-us1"},
+ {ClusterLabelName: "east-us2"},
+ //{ClusterName: "east-us1"},
+ //{ClusterName: "east-us2"},
+ },
+ },
+ },
+ AnyOfArray: []AnyOf{},
+ },
+ },
+ },
+ expectedError: "",
+ mockdb: &db.MockDB{
+ Items: map[string]map[string][]byte{
+ ProjectKey{ProjectName: "testProject"}.String(): {
+ "projectmetadata": []byte(
+ "{\"project-name\":\"testProject\"," +
+ "\"description\":\"Test project for unit testing\"}"),
+ },
+ CompositeAppKey{CompositeAppName: "testCompositeApp",
+ Version: "testCompositeAppVersion", Project: "testProject"}.String(): {
+ "compositeAppmetadata": []byte(
+ "{\"metadata\":{" +
+ "\"name\":\"testCompositeApp\"," +
+ "\"description\":\"description\"," +
+ "\"userData1\":\"user data\"," +
+ "\"userData2\":\"user data\"" +
+ "}," +
+ "\"spec\":{" +
+ "\"version\":\"version of the composite app\"}}"),
+ },
+ GenericPlacementIntentKey{
+ Name: "testIntent",
+ Project: "testProject",
+ CompositeApp: "testCompositeApp",
+ Version: "testCompositeAppVersion",
+ }.String(): {
+ "genericplacementintent": []byte(
+ "{\"metadata\":{\"Name\":\"testIntent\"," +
+ "\"Description\":\"A sample intent for testing\"," +
+ "\"UserData1\": \"userData1\"," +
+ "\"UserData2\": \"userData2\"}," +
+ "\"spec\":{\"Logical-Cloud\": \"logicalCloud1\"}}"),
+ },
+ },
+ },
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ db.DBconn = testCase.mockdb
+ appIntentCli := NewAppIntentClient()
+ got, err := appIntentCli.CreateAppIntent(testCase.inputAppIntent, testCase.inputProject, testCase.inputCompositeApp, testCase.inputCompositeAppVersion, testCase.inputGenericPlacementIntent)
+ if err != nil {
+ if testCase.expectedError == "" {
+ t.Fatalf("CreateAppIntent returned an unexpected error %s, ", err)
+ }
+ if strings.Contains(err.Error(), testCase.expectedError) == false {
+ t.Fatalf("CreateAppIntent returned an unexpected error %s", err)
+ }
+ } else {
+ if reflect.DeepEqual(testCase.expected, got) == false {
+ t.Errorf("CreateAppIntent returned unexpected body: got %v; "+" expected %v", got, testCase.expected)
+ }
+ }
+ })
+ }
+}
+
+func TestGetAppIntent(t *testing.T) {
+ testCases := []struct {
+ label string
+ expectedError string
+ expected AppIntent
+ mockdb *db.MockDB
+ appIntentName string
+ projectName string
+ compositeAppName string
+ compositeAppVersion string
+ genericPlacementIntent string
+ }{
+ {
+ label: "Get Intent",
+ appIntentName: "testAppIntent",
+ projectName: "testProject",
+ compositeAppName: "testCompositeApp",
+ compositeAppVersion: "testCompositeAppVersion",
+ genericPlacementIntent: "testIntent",
+ expected: AppIntent{
+ MetaData: MetaData{
+ Name: "testAppIntent",
+ Description: "testAppIntent",
+ UserData1: "userData1",
+ UserData2: "userData2",
+ },
+ Spec: SpecData{
+ AppName: "SampleApp",
+ Intent: IntentStruc{
+ AllOfArray: []AllOf{
+ {
+ ClusterName: "edge1",
+ },
+ {
+ ClusterName: "edge2",
+ },
+ {
+ AnyOfArray: []AnyOf{
+ {ClusterLabelName: "east-us1"},
+ {ClusterLabelName: "east-us2"},
+ },
+ },
+ },
+ },
+ },
+ },
+ expectedError: "",
+ mockdb: &db.MockDB{
+ Items: map[string]map[string][]byte{
+ AppIntentKey{
+ Name: "testAppIntent",
+ Project: "testProject",
+ CompositeApp: "testCompositeApp",
+ Version: "testCompositeAppVersion",
+ Intent: "testIntent",
+ }.String(): {
+ "appintent": []byte(
+ "{\"metadata\":{\"Name\":\"testAppIntent\"," +
+ "\"Description\":\"testAppIntent\"," +
+ "\"UserData1\": \"userData1\"," +
+ "\"UserData2\": \"userData2\"}," +
+ "\"spec\":{\"app-name\": \"SampleApp\"," +
+ "\"intent\": {" +
+ "\"allOf\":[" +
+ "{\"cluster-name\":\"edge1\"}," +
+ "{\"cluster-name\":\"edge2\"}," +
+ "{" +
+ "\"anyOf\":[" +
+ "{" +
+ "\"cluster-label-name\":\"east-us1\"}," +
+ "{" +
+ "\"cluster-label-name\":\"east-us2\"}" +
+ "]}]" +
+ "}}}"),
+ },
+ },
+ },
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ db.DBconn = testCase.mockdb
+ appIntentCli := NewAppIntentClient()
+ got, err := appIntentCli.GetAppIntent(testCase.appIntentName, testCase.projectName, testCase.compositeAppName, testCase.compositeAppVersion,
+ testCase.genericPlacementIntent)
+ if err != nil {
+ if testCase.expectedError == "" {
+ t.Fatalf("GetAppIntent returned an unexpected error: %s", err)
+ }
+ if strings.Contains(err.Error(), testCase.expectedError) == false {
+ t.Fatalf("GetAppIntent returned an unexpected error: %s", err)
+ }
+ } else {
+ if reflect.DeepEqual(testCase.expected, got) == false {
+ t.Errorf("GetAppIntent returned unexpected body: got %v;"+
+ " expected %v", got, testCase.expected)
+ }
+ }
+
+ })
+ }
+}
diff --git a/src/orchestrator/pkg/module/generic_placement_intent.go b/src/orchestrator/pkg/module/generic_placement_intent.go
new file mode 100644
index 00000000..4098194e
--- /dev/null
+++ b/src/orchestrator/pkg/module/generic_placement_intent.go
@@ -0,0 +1,165 @@
+/*
+ * 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 module
+
+import (
+ "encoding/json"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+
+ pkgerrors "github.com/pkg/errors"
+)
+
+// GenericPlacementIntent shall have 2 fields - metadata and spec
+type GenericPlacementIntent struct {
+ MetaData IntentMetaData `json:"metadata"`
+ Spec IntentSpecData `json:"spec"`
+}
+
+// IntentMetaData has name, description, userdata1, userdata2
+type IntentMetaData struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+ UserData1 string `json:"userData1"`
+ UserData2 string `json:"userData2"`
+}
+
+// IntentSpecData has logical-cloud-name
+type IntentSpecData struct {
+ LogicalCloud string `json:"logical-cloud"`
+}
+
+// GenericPlacementIntentManager is an interface which exposes the GenericPlacementIntentManager functionality
+type GenericPlacementIntentManager interface {
+ CreateGenericPlacementIntent(g GenericPlacementIntent, p string, ca string,
+ v string) (GenericPlacementIntent, error)
+ GetGenericPlacementIntent(intentName string, projectName string,
+ compositeAppName string, version string) (GenericPlacementIntent, error)
+ DeleteGenericPlacementIntent(intentName string, projectName string,
+ compositeAppName string, version string) error
+}
+
+// GenericPlacementIntentKey is used as the primary key
+type GenericPlacementIntentKey struct {
+ Name string `json:"name"`
+ Project string `json:"project"`
+ CompositeApp string `json:"compositeapp"`
+ Version string `json:"version"`
+}
+
+// We will use json marshalling to convert to string to
+// preserve the underlying structure.
+func (gk GenericPlacementIntentKey) String() string {
+ out, err := json.Marshal(gk)
+ if err != nil {
+ return ""
+ }
+ return string(out)
+}
+
+// GenericPlacementIntentClient implements the GenericPlacementIntentManager interface
+type GenericPlacementIntentClient struct {
+ storeName string
+ tagMetaData string
+}
+
+// NewGenericPlacementIntentClient return an instance of GenericPlacementIntentClient which implements GenericPlacementIntentManager
+func NewGenericPlacementIntentClient() *GenericPlacementIntentClient {
+ return &GenericPlacementIntentClient{
+ storeName: "orchestrator",
+ tagMetaData: "genericplacementintent",
+ }
+}
+
+// CreateGenericPlacementIntent creates an entry for GenericPlacementIntent in the database. Other Input parameters for it - projectName, compositeAppName, version
+func (c *GenericPlacementIntentClient) CreateGenericPlacementIntent(g GenericPlacementIntent, p string, ca string,
+ v string) (GenericPlacementIntent, error) {
+
+ // check if the genericPlacement already exists.
+ res, err := c.GetGenericPlacementIntent(g.MetaData.Name, p, ca, v)
+ if res != (GenericPlacementIntent{}) {
+ return GenericPlacementIntent{}, pkgerrors.New("Intent already exists")
+ }
+
+ //Check if project exists
+ _, err = NewProjectClient().GetProject(p)
+ if err != nil {
+ return GenericPlacementIntent{}, pkgerrors.New("Unable to find the project")
+ }
+
+ // check if compositeApp exists
+ _, err = NewCompositeAppClient().GetCompositeApp(ca, v, p)
+ if err != nil {
+ return GenericPlacementIntent{}, pkgerrors.New("Unable to find the composite-app")
+ }
+
+ gkey := GenericPlacementIntentKey{
+ Name: g.MetaData.Name,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ }
+
+ err = db.DBconn.Insert(c.storeName, gkey, nil, c.tagMetaData, g)
+ if err != nil {
+ return GenericPlacementIntent{}, pkgerrors.Wrap(err, "Create DB entry error")
+ }
+
+ return g, nil
+}
+
+// GetGenericPlacementIntent shall take arguments - name of the intent, name of the project, name of the composite app and version of the composite app. It shall return the genericPlacementIntent if its present.
+func (c *GenericPlacementIntentClient) GetGenericPlacementIntent(i string, p string, ca string, v string) (GenericPlacementIntent, error) {
+ key := GenericPlacementIntentKey{
+ Name: i,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ }
+
+ result, err := db.DBconn.Find(c.storeName, key, c.tagMetaData)
+ if err != nil {
+ return GenericPlacementIntent{}, pkgerrors.Wrap(err, "Get Intent error")
+ }
+
+ if result != nil {
+ g := GenericPlacementIntent{}
+ err = db.DBconn.Unmarshal(result[0], &g)
+ if err != nil {
+ return GenericPlacementIntent{}, pkgerrors.Wrap(err, "Unmarshalling GenericPlacement Intent")
+ }
+ return g, nil
+ }
+
+ return GenericPlacementIntent{}, pkgerrors.New("Error getting GenericPlacementIntent")
+
+}
+
+// DeleteGenericPlacementIntent the intent from the database
+func (c *GenericPlacementIntentClient) DeleteGenericPlacementIntent(i string, p string, ca string, v string) error {
+ key := GenericPlacementIntentKey{
+ Name: i,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ }
+
+ err := db.DBconn.Remove(c.storeName, key)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Delete Project entry;")
+ }
+ return nil
+}
diff --git a/src/orchestrator/pkg/module/generic_placement_intent_test.go b/src/orchestrator/pkg/module/generic_placement_intent_test.go
new file mode 100644
index 00000000..3cb29e61
--- /dev/null
+++ b/src/orchestrator/pkg/module/generic_placement_intent_test.go
@@ -0,0 +1,184 @@
+/*
+ * 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 module
+
+import (
+ "reflect"
+ "strings"
+ "testing"
+
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+)
+
+func TestCreateGenericPlacementIntent(t *testing.T) {
+ testCases := []struct {
+ label string
+ inputIntent GenericPlacementIntent
+ inputProject string
+ inputCompositeApp string
+ inputCompositeAppVersion string
+ expectedError string
+ mockdb *db.MockDB
+ expected GenericPlacementIntent
+ }{
+ {
+ label: "Create GenericPlacementIntent",
+ inputIntent: GenericPlacementIntent{
+ MetaData: IntentMetaData{
+ Name: "testGenericPlacement",
+ Description: " A sample intent for testing",
+ UserData1: "userData1",
+ UserData2: "userData2",
+ },
+ Spec: IntentSpecData{
+ LogicalCloud: "logicalCloud1",
+ },
+ },
+ inputProject: "testProject",
+ inputCompositeApp: "testCompositeApp",
+ inputCompositeAppVersion: "testCompositeAppVersion",
+ expected: GenericPlacementIntent{
+ MetaData: IntentMetaData{
+ Name: "testGenericPlacement",
+ Description: " A sample intent for testing",
+ UserData1: "userData1",
+ UserData2: "userData2",
+ },
+ Spec: IntentSpecData{
+ LogicalCloud: "logicalCloud1",
+ },
+ },
+ expectedError: "",
+ mockdb: &db.MockDB{
+ Items: map[string]map[string][]byte{
+ ProjectKey{ProjectName: "testProject"}.String(): {
+ "projectmetadata": []byte(
+ "{\"project-name\":\"testProject\"," +
+ "\"description\":\"Test project for unit testing\"}"),
+ },
+ CompositeAppKey{CompositeAppName: "testCompositeApp",
+ Version: "testCompositeAppVersion", Project: "testProject"}.String(): {
+ "compositeAppmetadata": []byte(
+ "{\"metadata\":{" +
+ "\"name\":\"testCompositeApp\"," +
+ "\"description\":\"description\"," +
+ "\"userData1\":\"user data\"," +
+ "\"userData2\":\"user data\"" +
+ "}," +
+ "\"spec\":{" +
+ "\"version\":\"version of the composite app\"}}"),
+ },
+ },
+ },
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ db.DBconn = testCase.mockdb
+ intentCli := NewGenericPlacementIntentClient()
+ got, err := intentCli.CreateGenericPlacementIntent(testCase.inputIntent, testCase.inputProject, testCase.inputCompositeApp, testCase.inputCompositeAppVersion)
+ if err != nil {
+ if testCase.expectedError == "" {
+ t.Fatalf("CreateGenericPlacementIntent returned an unexpected error %s", err)
+ }
+ if strings.Contains(err.Error(), testCase.expectedError) == false {
+ t.Fatalf("CreateGenericPlacementIntent returned an unexpected error %s", err)
+ }
+ } else {
+ if reflect.DeepEqual(testCase.expected, got) == false {
+ t.Errorf("CreateGenericPlacementIntent returned unexpected body: got %v; "+" expected %v", got, testCase.expected)
+ }
+ }
+ })
+
+ }
+}
+
+func TestGetGenericPlacementIntent(t *testing.T) {
+
+ testCases := []struct {
+ label string
+ expectedError string
+ expected GenericPlacementIntent
+ mockdb *db.MockDB
+ intentName string
+ projectName string
+ compositeAppName string
+ compositeAppVersion string
+ }{
+ {
+ label: "Get Intent",
+ intentName: "testIntent",
+ projectName: "testProject",
+ compositeAppName: "testCompositeApp",
+ compositeAppVersion: "testVersion",
+ expected: GenericPlacementIntent{
+ MetaData: IntentMetaData{
+ Name: "testIntent",
+ Description: "A sample intent for testing",
+ UserData1: "userData1",
+ UserData2: "userData2",
+ },
+ Spec: IntentSpecData{
+ LogicalCloud: "logicalCloud1",
+ },
+ },
+ expectedError: "",
+ mockdb: &db.MockDB{
+ Items: map[string]map[string][]byte{
+ GenericPlacementIntentKey{
+ Name: "testIntent",
+ Project: "testProject",
+ CompositeApp: "testCompositeApp",
+ Version: "testVersion",
+ }.String(): {
+ "genericplacementintent": []byte(
+ "{\"metadata\":{\"Name\":\"testIntent\"," +
+ "\"Description\":\"A sample intent for testing\"," +
+ "\"UserData1\": \"userData1\"," +
+ "\"UserData2\": \"userData2\"}," +
+ "\"spec\":{\"Logical-Cloud\": \"logicalCloud1\"}}"),
+ },
+ },
+ },
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ db.DBconn = testCase.mockdb
+ intentCli := NewGenericPlacementIntentClient()
+ got, err := intentCli.GetGenericPlacementIntent(testCase.intentName, testCase.projectName, testCase.compositeAppName, testCase.compositeAppVersion)
+ if err != nil {
+ if testCase.expectedError == "" {
+ t.Fatalf("GetGenericPlacementIntent returned an unexpected error: %s", err)
+ }
+ if strings.Contains(err.Error(), testCase.expectedError) == false {
+ t.Fatalf("GetGenericPlacementIntent returned an unexpected error: %s", err)
+ }
+ } else {
+ if reflect.DeepEqual(testCase.expected, got) == false {
+ t.Errorf("GetGenericPlacementIntent returned unexpected body: got %v;"+
+ " expected %v", got, testCase.expected)
+ }
+ }
+
+ })
+ }
+
+}
diff --git a/src/orchestrator/pkg/module/module.go b/src/orchestrator/pkg/module/module.go
index f80ff55b..34a84624 100644
--- a/src/orchestrator/pkg/module/module.go
+++ b/src/orchestrator/pkg/module/module.go
@@ -20,18 +20,24 @@ package module
type Client struct {
Project *ProjectClient
CompositeApp *CompositeAppClient
- Controller *ControllerClient
- Cluster *ClusterClient
+ Controller *ControllerClient
+ Cluster *ClusterClient
// Add Clients for API's here
+ GenericPlacementIntent *GenericPlacementIntentClient
+ AppIntent *AppIntentClient
}
// NewClient creates a new client for using the services
func NewClient() *Client {
c := &Client{}
+ // Add Client API handlers here
c.Project = NewProjectClient()
c.CompositeApp = NewCompositeAppClient()
c.Controller = NewControllerClient()
c.Cluster = NewClusterClient()
// Add Client API handlers here
+ c.GenericPlacementIntent = NewGenericPlacementIntentClient()
+ c.AppIntent = NewAppIntentClient()
+
return c
}