aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajamohan Raj <rajamohan.raj@intel.com>2020-02-26 02:07:34 +0000
committerRajamohan Raj <rajamohan.raj@intel.com>2020-03-04 23:43:43 +0000
commitff03456548dac309461f402738ac344046de8057 (patch)
tree479b113227ba2d67636aa68a165cb5e484071d72
parent37aed9b7a0db62b9931d89c614ff6291cc4608cc (diff)
Add DeploymentIntentGroup APIs
Implemented the routes for creation, deletion and getting DeploymentIntentGroup. Added routes for adding, getting and deleting intents. Issue-ID: MULTICLOUD-1002 Signed-off-by: Rajamohan Raj <rajamohan.raj@intel.com> Change-Id: I07ba3744107bcf30aa30ed89caa21bf474c0d92a
-rw-r--r--src/orchestrator/api/add_intents_handler.go136
-rw-r--r--src/orchestrator/api/api.go29
-rw-r--r--src/orchestrator/api/clusterhandler.go8
-rw-r--r--src/orchestrator/api/clusterhandler_test.go34
-rw-r--r--src/orchestrator/api/controllerhandler_test.go6
-rw-r--r--src/orchestrator/api/deployment_intent_groups_handler.go133
-rw-r--r--src/orchestrator/api/projecthandler_test.go6
-rw-r--r--src/orchestrator/cmd/main.go2
-rw-r--r--src/orchestrator/go.mod3
-rw-r--r--src/orchestrator/go.sum1
-rw-r--r--src/orchestrator/pkg/module/add_intents.go184
-rw-r--r--src/orchestrator/pkg/module/deployment_intent_groups.go177
-rw-r--r--src/orchestrator/pkg/module/deployment_intent_groups_test.go230
-rw-r--r--src/orchestrator/pkg/module/generic_placement_intent.go12
-rw-r--r--src/orchestrator/pkg/module/generic_placement_intent_test.go12
-rw-r--r--src/orchestrator/pkg/module/module.go15
16 files changed, 941 insertions, 47 deletions
diff --git a/src/orchestrator/api/add_intents_handler.go b/src/orchestrator/api/add_intents_handler.go
new file mode 100644
index 00000000..dfe1a496
--- /dev/null
+++ b/src/orchestrator/api/add_intents_handler.go
@@ -0,0 +1,136 @@
+/*
+ * 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 api
+
+import (
+ "encoding/json"
+ "io"
+ "net/http"
+
+ moduleLib "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
+
+ "github.com/gorilla/mux"
+)
+
+type intentHandler struct {
+ client moduleLib.IntentManager
+}
+
+func (h intentHandler) addIntentHandler(w http.ResponseWriter, r *http.Request) {
+ var i moduleLib.Intent
+
+ err := json.NewDecoder(r.Body).Decode(&i)
+ switch {
+ case err == io.EOF:
+ http.Error(w, "Empty body", http.StatusBadRequest)
+ return
+
+ case err != nil:
+ http.Error(w, err.Error(), http.StatusUnprocessableEntity)
+ return
+ }
+
+ if i.MetaData.Name == "" {
+ http.Error(w, "Missing Intent in POST request", http.StatusBadRequest)
+ return
+ }
+
+ vars := mux.Vars(r)
+ p := vars["project-name"]
+ ca := vars["composite-app-name"]
+ v := vars["composite-app-version"]
+ d := vars["deployment-intent-group-name"]
+
+ intent, addError := h.client.AddIntent(i, p, ca, v, d)
+ if addError != nil {
+ http.Error(w, addError.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusCreated)
+ err = json.NewEncoder(w).Encode(intent)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+}
+
+func (h intentHandler) getIntentHandler(w http.ResponseWriter, r *http.Request) {
+
+ vars := mux.Vars(r)
+
+ i := vars["intent-name"]
+ if i == "" {
+ http.Error(w, "Missing intentName in GET request", http.StatusBadRequest)
+ return
+ }
+
+ p := vars["project-name"]
+ if p == "" {
+ http.Error(w, "Missing projectName in GET request", http.StatusBadRequest)
+ return
+ }
+ ca := vars["composite-app-name"]
+ if ca == "" {
+ http.Error(w, "Missing compositeAppName in GET request", http.StatusBadRequest)
+ return
+ }
+
+ v := vars["composite-app-version"]
+ if v == "" {
+ http.Error(w, "Missing version of compositeApp in GET request", http.StatusBadRequest)
+ return
+ }
+
+ di := vars["deployment-intent-group-name"]
+ if di == "" {
+ http.Error(w, "Missing name of DeploymentIntentGroup in GET request", http.StatusBadRequest)
+ return
+ }
+
+ intent, err := h.client.GetIntent(i, p, ca, v, di)
+ 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(intent)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+}
+
+func (h intentHandler) deleteIntentHandler(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+
+ i := vars["intent-name"]
+ p := vars["project-name"]
+ ca := vars["composite-app-name"]
+ v := vars["composite-app-version"]
+ di := vars["deployment-intent-group-name"]
+
+ err := h.client.DeleteIntent(i, p, ca, v, di)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ w.WriteHeader(http.StatusNoContent)
+}
diff --git a/src/orchestrator/api/api.go b/src/orchestrator/api/api.go
index f4381e6c..f3e3b177 100644
--- a/src/orchestrator/api/api.go
+++ b/src/orchestrator/api/api.go
@@ -28,7 +28,9 @@ func NewRouter(projectClient moduleLib.ProjectManager,
ControllerClient moduleLib.ControllerManager,
clusterClient moduleLib.ClusterManager,
genericPlacementIntentClient moduleLib.GenericPlacementIntentManager,
- appIntentClient moduleLib.AppIntentManager) *mux.Router {
+ appIntentClient moduleLib.AppIntentManager,
+ deploymentIntentGrpClient moduleLib.DeploymentIntentGroupManager,
+ intentClient moduleLib.IntentManager) *mux.Router {
router := mux.NewRouter().PathPrefix("/v2").Subrouter()
@@ -114,5 +116,30 @@ func NewRouter(projectClient moduleLib.ProjectManager,
router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/generic-placement-intents/{intent-name}/app-intents/{app-intent-name}", appIntentHandler.getAppIntentHandler).Methods("GET")
router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/generic-placement-intents/{intent-name}/app-intents/{app-intent-name}", appIntentHandler.deleteAppIntentHandler).Methods("DELETE")
+ //setting routes for deploymentIntentGroup
+ if deploymentIntentGrpClient == nil {
+ deploymentIntentGrpClient = moduleClient.DeploymentIntentGroup
+ }
+
+ deploymentIntentGrpHandler := deploymentIntentGroupHandler{
+ client: deploymentIntentGrpClient,
+ }
+ router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups", deploymentIntentGrpHandler.createDeploymentIntentGroupHandler).Methods("POST")
+ router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}", deploymentIntentGrpHandler.getDeploymentIntentGroupHandler).Methods("GET")
+ router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}", deploymentIntentGrpHandler.deleteDeploymentIntentGroupHandler).Methods("DELETE")
+
+ // setting routes for AddingIntents
+ if intentClient == nil {
+ intentClient = moduleClient.Intent
+ }
+
+ intentHandler := intentHandler{
+ client: intentClient,
+ }
+
+ router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/intents", intentHandler.addIntentHandler).Methods("POST")
+ router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/intents/{intent-name}", intentHandler.getIntentHandler).Methods("GET")
+ router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/intents/{intent-name}", intentHandler.deleteIntentHandler).Methods("DELETE")
+
return router
}
diff --git a/src/orchestrator/api/clusterhandler.go b/src/orchestrator/api/clusterhandler.go
index 7e769f31..ac4191e1 100644
--- a/src/orchestrator/api/clusterhandler.go
+++ b/src/orchestrator/api/clusterhandler.go
@@ -255,12 +255,12 @@ func (h clusterHandler) getClusterHandler(w http.ResponseWriter, r *http.Request
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- kc_bytes, err := base64.StdEncoding.DecodeString(retKubeconfig.Kubeconfig)
+ kcBytes, err := base64.StdEncoding.DecodeString(retKubeconfig.Kubeconfig)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- _, err = pw.Write(kc_bytes)
+ _, err = pw.Write(kcBytes)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -276,12 +276,12 @@ func (h clusterHandler) getClusterHandler(w http.ResponseWriter, r *http.Request
case "application/octet-stream":
w.Header().Set("Content-Type", "application/octet-stream")
w.WriteHeader(http.StatusOK)
- kc_bytes, err := base64.StdEncoding.DecodeString(retKubeconfig.Kubeconfig)
+ kcBytes, err := base64.StdEncoding.DecodeString(retKubeconfig.Kubeconfig)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- _, err = w.Write(kc_bytes)
+ _, err = w.Write(kcBytes)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
diff --git a/src/orchestrator/api/clusterhandler_test.go b/src/orchestrator/api/clusterhandler_test.go
index ad7635e2..a32bf021 100644
--- a/src/orchestrator/api/clusterhandler_test.go
+++ b/src/orchestrator/api/clusterhandler_test.go
@@ -229,7 +229,7 @@ func TestClusterProviderCreateHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("POST", "/v2/cluster-providers", testCase.reader)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -307,7 +307,7 @@ func TestClusterProviderGetAllHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v2/cluster-providers", nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -377,7 +377,7 @@ func TestClusterProviderGetHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v2/cluster-providers/"+testCase.name, nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -426,7 +426,7 @@ func TestClusterProviderDeleteHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("DELETE", "/v2/cluster-providers/"+testCase.name, nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -538,7 +538,7 @@ of clusterTest
request := httptest.NewRequest("POST", "/v2/cluster-providers/clusterProvider1/clusters", bytes.NewBuffer(body.Bytes()))
request.Header.Set("Content-Type", multiwr.FormDataContentType())
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -625,7 +625,7 @@ func TestClusterGetAllHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v2/cluster-providers/clusterProvder1/clusters", nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -706,7 +706,7 @@ func TestClusterGetHandler(t *testing.T) {
if len(testCase.accept) > 0 {
request.Header.Set("Accept", testCase.accept)
}
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -784,7 +784,7 @@ of clusterTest
if len(testCase.accept) > 0 {
request.Header.Set("Accept", testCase.accept)
}
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -834,7 +834,7 @@ func TestClusterDeleteHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("DELETE", "/v2/cluster-providers/clusterProvider1/clusters/"+testCase.name, nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -880,7 +880,7 @@ func TestClusterLabelCreateHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("POST", "/v2/cluster-providers/cp1/clusters/cl1/labels", testCase.reader)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -944,7 +944,7 @@ func TestClusterLabelsGetHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v2/cluster-providers/cp1/clusters/cl1/labels", nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -1004,7 +1004,7 @@ func TestClusterLabelGetHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v2/cluster-providers/clusterProvider1/clusters/cl1/labels/"+testCase.name, nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -1053,7 +1053,7 @@ func TestClusterLabelDeleteHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("DELETE", "/v2/cluster-providers/cp1/clusters/cl1/labels/"+testCase.name, nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -1144,7 +1144,7 @@ func TestClusterKvPairsCreateHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("POST", "/v2/cluster-providers/cp1/clusters/cl1/kv-pairs", testCase.reader)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -1262,7 +1262,7 @@ func TestClusterKvPairsGetAllHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v2/cluster-providers/cp1/clusters/cl1/kv-pairs", nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -1352,7 +1352,7 @@ func TestClusterKvPairsGetHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v2/cluster-providers/clusterProvider1/clusters/cl1/kv-pairs/"+testCase.name, nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -1401,7 +1401,7 @@ func TestClusterKvPairsDeleteHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("DELETE", "/v2/cluster-providers/cp1/clusters/cl1/kv-pairs/"+testCase.name, nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, testCase.clusterClient, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
diff --git a/src/orchestrator/api/controllerhandler_test.go b/src/orchestrator/api/controllerhandler_test.go
index bcc06f98..dd542de7 100644
--- a/src/orchestrator/api/controllerhandler_test.go
+++ b/src/orchestrator/api/controllerhandler_test.go
@@ -110,7 +110,7 @@ func TestControllerCreateHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("POST", "/v2/controllers", testCase.reader)
- resp := executeRequest(request, NewRouter(nil, nil, testCase.controllerClient, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.controllerClient, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -173,7 +173,7 @@ func TestControllerGetHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v2/controllers/"+testCase.name, nil)
- resp := executeRequest(request, NewRouter(nil, nil, testCase.controllerClient, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.controllerClient, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -222,7 +222,7 @@ func TestControllerDeleteHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("DELETE", "/v2/controllers/"+testCase.name, nil)
- resp := executeRequest(request, NewRouter(nil, nil, testCase.controllerClient, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.controllerClient, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
diff --git a/src/orchestrator/api/deployment_intent_groups_handler.go b/src/orchestrator/api/deployment_intent_groups_handler.go
new file mode 100644
index 00000000..3f5b3969
--- /dev/null
+++ b/src/orchestrator/api/deployment_intent_groups_handler.go
@@ -0,0 +1,133 @@
+/*
+ * 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 api
+
+import (
+ "encoding/json"
+ "io"
+ "net/http"
+
+ moduleLib "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
+
+ "github.com/gorilla/mux"
+)
+
+/* Used to store backend implementation objects
+Also simplifies mocking for unit testing purposes
+*/
+type deploymentIntentGroupHandler struct {
+ client moduleLib.DeploymentIntentGroupManager
+}
+
+// createDeploymentIntentGroupHandler handles the create operation of DeploymentIntentGroup
+func (h deploymentIntentGroupHandler) createDeploymentIntentGroupHandler(w http.ResponseWriter, r *http.Request) {
+
+ var d moduleLib.DeploymentIntentGroup
+
+ err := json.NewDecoder(r.Body).Decode(&d)
+ switch {
+ case err == io.EOF:
+ http.Error(w, "Empty body", http.StatusBadRequest)
+ return
+ case err != nil:
+ http.Error(w, err.Error(), http.StatusUnprocessableEntity)
+ return
+ }
+
+ if d.MetaData.Name == "" {
+ http.Error(w, "Missing deploymentIntentGroupName in POST request", http.StatusBadRequest)
+ return
+ }
+
+ vars := mux.Vars(r)
+ projectName := vars["project-name"]
+ compositeAppName := vars["composite-app-name"]
+ version := vars["composite-app-version"]
+
+ dIntent, createErr := h.client.CreateDeploymentIntentGroup(d, projectName, compositeAppName, version)
+ if createErr != nil {
+ http.Error(w, createErr.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusCreated)
+ err = json.NewEncoder(w).Encode(dIntent)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+}
+
+func (h deploymentIntentGroupHandler) getDeploymentIntentGroupHandler(w http.ResponseWriter, r *http.Request) {
+
+ vars := mux.Vars(r)
+
+ p := vars["project-name"]
+ if p == "" {
+ http.Error(w, "Missing projectName in GET request", http.StatusBadRequest)
+ return
+ }
+ ca := vars["composite-app-name"]
+ if ca == "" {
+ http.Error(w, "Missing compositeAppName in GET request", http.StatusBadRequest)
+ return
+ }
+
+ v := vars["composite-app-version"]
+ if v == "" {
+ http.Error(w, "Missing version of compositeApp in GET request", http.StatusBadRequest)
+ return
+ }
+
+ di := vars["deployment-intent-group-name"]
+ if v == "" {
+ http.Error(w, "Missing name of DeploymentIntentGroup in GET request", http.StatusBadRequest)
+ return
+ }
+
+ dIntentGrp, err := h.client.GetDeploymentIntentGroup(di, p, ca, v)
+ 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(dIntentGrp)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+}
+
+func (h deploymentIntentGroupHandler) deleteDeploymentIntentGroupHandler(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+
+ p := vars["project-name"]
+ ca := vars["composite-app-name"]
+ v := vars["composite-app-version"]
+ di := vars["deployment-intent-group-name"]
+
+ err := h.client.DeleteDeploymentIntentGroup(di, p, ca, v)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ w.WriteHeader(http.StatusNoContent)
+}
diff --git a/src/orchestrator/api/projecthandler_test.go b/src/orchestrator/api/projecthandler_test.go
index 84e67521..eccccb90 100644
--- a/src/orchestrator/api/projecthandler_test.go
+++ b/src/orchestrator/api/projecthandler_test.go
@@ -119,7 +119,7 @@ func TestProjectCreateHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("POST", "/v2/projects", testCase.reader)
- resp := executeRequest(request, NewRouter(testCase.projectClient, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(testCase.projectClient, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -188,7 +188,7 @@ func TestProjectGetHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v2/projects/"+testCase.name, nil)
- resp := executeRequest(request, NewRouter(testCase.projectClient, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(testCase.projectClient, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -237,7 +237,7 @@ func TestProjectDeleteHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("DELETE", "/v2/projects/"+testCase.name, nil)
- resp := executeRequest(request, NewRouter(testCase.projectClient, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(testCase.projectClient, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
diff --git a/src/orchestrator/cmd/main.go b/src/orchestrator/cmd/main.go
index cf1faf41..9296a54c 100644
--- a/src/orchestrator/cmd/main.go
+++ b/src/orchestrator/cmd/main.go
@@ -47,7 +47,7 @@ func main() {
log.Fatalln("Exiting...")
}
- httpRouter := api.NewRouter(nil, nil, nil, nil, nil, nil)
+ httpRouter := api.NewRouter(nil, nil, nil, nil, nil, nil, nil, nil)
loggedRouter := handlers.LoggingHandler(os.Stdout, httpRouter)
log.Println("Starting Kubernetes Multicloud API")
diff --git a/src/orchestrator/go.mod b/src/orchestrator/go.mod
index d6fada43..547fa8ed 100644
--- a/src/orchestrator/go.mod
+++ b/src/orchestrator/go.mod
@@ -1,6 +1,7 @@
module github.com/onap/multicloud-k8s/src/orchestrator
require (
+ github.com/coreos/etcd v3.3.12+incompatible
github.com/docker/engine v0.0.0-20190620014054-c513a4c6c298
github.com/ghodss/yaml v1.0.0
github.com/gogo/protobuf v1.3.1 // indirect
@@ -32,3 +33,5 @@ replace (
k8s.io/client-go => k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible
k8s.io/cloud-provider => k8s.io/cloud-provider v0.0.0-20190409023720-1bc0c81fa51d
)
+
+go 1.13
diff --git a/src/orchestrator/go.sum b/src/orchestrator/go.sum
index d2015406..aeab3b50 100644
--- a/src/orchestrator/go.sum
+++ b/src/orchestrator/go.sum
@@ -172,6 +172,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onap/multicloud-k8s v0.0.0-20191115005109-f168ebb73d8d h1:3uFucXVv6gqa3H1u85CjoLOvGraREfD8/NL7m/9W9tc=
github.com/onap/multicloud-k8s v0.0.0-20200131010833-90e13d101cf0 h1:2qDo6s4pdg/g7Vj6QGrCK02EP4jjwVehgEObnAfipSM=
+github.com/onap/multicloud-k8s v0.0.0-20200229013830-7b566f287523 h1:hVu6djUEav5nKQvVZZa3FT71ZD9QbCcTI3dM+1chvFU=
github.com/onap/multicloud-k8s/src/k8splugin v0.0.0-20191115005109-f168ebb73d8d h1:ucIEjqzNVeFPnQofeuBfUqro0OnilX//fajEFxuLsgA=
github.com/onap/multicloud-k8s/src/k8splugin v0.0.0-20191115005109-f168ebb73d8d/go.mod h1:EnQd/vQGZR1/55IihaHxiux4ZUig/zfXZux7bfmU0S8=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
diff --git a/src/orchestrator/pkg/module/add_intents.go b/src/orchestrator/pkg/module/add_intents.go
new file mode 100644
index 00000000..a657cce7
--- /dev/null
+++ b/src/orchestrator/pkg/module/add_intents.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 Addlicable 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"
+)
+
+// Intent shall have 2 fields - MetaData and Spec
+type Intent 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 Intent
+type IntentSpecData struct {
+ Intent IntentObj `json:"intent"`
+}
+
+// IntentObj has name of the generic placement intent
+type IntentObj struct {
+ Generic string `json:"generic"`
+}
+
+// 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)
+ GetIntent(i string, p string, ca string, v string, di string) (Intent, error)
+ DeleteIntent(i string, p string, ca string, v string, di string) error
+}
+
+// IntentKey consists of Name if the intent, Project name, CompositeApp name,
+// CompositeApp version
+type IntentKey struct {
+ Name string `json:"name"`
+ Project string `json:"project"`
+ CompositeApp string `json:"compositeapp"`
+ Version string `json:"version"`
+ DeploymentIntentGroup string `json:"deployment-intent-group-name"`
+}
+
+// We will use json marshalling to convert to string to
+// preserve the underlying structure.
+func (ik IntentKey) String() string {
+ out, err := json.Marshal(ik)
+ if err != nil {
+ return ""
+ }
+ return string(out)
+}
+
+// IntentClient implements the AddIntentManager interface
+type IntentClient struct {
+ storeName string
+ tagMetaData string
+}
+
+// NewIntentClient returns an instance of AddIntentClient
+func NewIntentClient() *IntentClient {
+ return &IntentClient{
+ storeName: "orchestrator",
+ tagMetaData: "addintent",
+ }
+}
+
+// AddIntent adds a given intent to the deployment-intent-group and stores in the db. Other input parameters for it - projectName, compositeAppName, version, DeploymentIntentgroupName
+func (c *IntentClient) AddIntent(a Intent, p string, ca string, v string, di string) (Intent, error) {
+
+ //Check for the AddIntent already exists here.
+ res, err := c.GetIntent(a.MetaData.Name, p, ca, v, di)
+ if !reflect.DeepEqual(res, Intent{}) {
+ return Intent{}, pkgerrors.New("AppIntent already exists")
+ }
+
+ //Check if project exists
+ _, err = NewProjectClient().GetProject(p)
+ if err != nil {
+ return Intent{}, pkgerrors.New("Unable to find the project")
+ }
+
+ //check if compositeApp exists
+ _, err = NewCompositeAppClient().GetCompositeApp(ca, v, p)
+ if err != nil {
+ return Intent{}, pkgerrors.New("Unable to find the composite-app")
+ }
+
+ //check if DeploymentIntentGroup exists
+ _, err = NewDeploymentIntentGroupClient().GetDeploymentIntentGroup(di, p, ca, v)
+ if err != nil {
+ return Intent{}, pkgerrors.New("Unable to find the intent")
+ }
+
+ akey := IntentKey{
+ Name: a.MetaData.Name,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ DeploymentIntentGroup: di,
+ }
+
+ err = db.DBconn.Insert(c.storeName, akey, nil, c.tagMetaData, a)
+ if err != nil {
+ return Intent{}, pkgerrors.Wrap(err, "Create DB entry error")
+ }
+ return a, nil
+}
+
+// GetIntent returns an Intent
+func (c *IntentClient) GetIntent(i string, p string, ca string, v string, di string) (Intent, error) {
+
+ k := IntentKey{
+ Name: i,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ DeploymentIntentGroup: di,
+ }
+
+ result, err := db.DBconn.Find(c.storeName, k, c.tagMetaData)
+ if err != nil {
+ return Intent{}, pkgerrors.Wrap(err, "Get AppIntent error")
+ }
+
+ if result != nil {
+ a := Intent{}
+ err = db.DBconn.Unmarshal(result[0], &a)
+ if err != nil {
+ return Intent{}, pkgerrors.Wrap(err, "Unmarshalling AppIntent")
+ }
+ return a, nil
+
+ }
+ return Intent{}, pkgerrors.New("Error getting AppIntent")
+}
+
+// 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{
+ Name: i,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ DeploymentIntentGroup: di,
+ }
+
+ 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/deployment_intent_groups.go b/src/orchestrator/pkg/module/deployment_intent_groups.go
new file mode 100644
index 00000000..fe622771
--- /dev/null
+++ b/src/orchestrator/pkg/module/deployment_intent_groups.go
@@ -0,0 +1,177 @@
+/*
+ * 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"
+ "reflect"
+
+ pkgerrors "github.com/pkg/errors"
+)
+
+// DeploymentIntentGroup shall have 2 fields - MetaData and Spec
+type DeploymentIntentGroup struct {
+ MetaData DepMetaData `json:"metadata"`
+ Spec DepSpecData `json:"spec"`
+}
+
+// DepMetaData has Name, description, userdata1, userdata2
+type DepMetaData struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+ UserData1 string `json:"userData1"`
+ UserData2 string `json:"userData2"`
+}
+
+// DepSpecData has profile, version, OverrideValuesObj
+type DepSpecData struct {
+ Profile string `json:"profile"`
+ Version string `json:"version"`
+ OverrideValuesObj []OverrideValues `json:"override-values"`
+}
+
+// OverrideValues has appName and ValuesObj
+type OverrideValues struct {
+ AppName string `json:"app-name"`
+ ValuesObj map[string]string `json:"values"`
+}
+
+// Values has ImageRepository
+// type Values struct {
+// ImageRepository string `json:"imageRepository"`
+// }
+
+// DeploymentIntentGroupManager is an interface which exposes the DeploymentIntentGroupManager functionality
+type DeploymentIntentGroupManager interface {
+ CreateDeploymentIntentGroup(d DeploymentIntentGroup, p string, ca string, v string) (DeploymentIntentGroup, error)
+ GetDeploymentIntentGroup(di string, p string, ca string, v string) (DeploymentIntentGroup, error)
+ DeleteDeploymentIntentGroup(di string, p string, ca string, v string) error
+}
+
+// DeploymentIntentGroupKey consists of Name of the deployment group, project name, CompositeApp name, CompositeApp version
+type DeploymentIntentGroupKey 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 (dk DeploymentIntentGroupKey) String() string {
+ out, err := json.Marshal(dk)
+ if err != nil {
+ return ""
+ }
+ return string(out)
+}
+
+// DeploymentIntentGroupClient implements the DeploymentIntentGroupManager interface
+type DeploymentIntentGroupClient struct {
+ storeName string
+ tagMetaData string
+}
+
+// NewDeploymentIntentGroupClient return an instance of DeploymentIntentGroupClient which implements DeploymentIntentGroupManager
+func NewDeploymentIntentGroupClient() *DeploymentIntentGroupClient {
+ return &DeploymentIntentGroupClient{
+ storeName: "orchestrator",
+ tagMetaData: "deploymentintentgroup",
+ }
+}
+
+// CreateDeploymentIntentGroup creates an entry for a given DeploymentIntentGroup in the database. Other Input parameters for it - projectName, compositeAppName, version
+func (c *DeploymentIntentGroupClient) CreateDeploymentIntentGroup(d DeploymentIntentGroup, p string, ca string,
+ v string) (DeploymentIntentGroup, error) {
+
+ res, err := c.GetDeploymentIntentGroup(d.MetaData.Name, p, ca, v)
+ if !reflect.DeepEqual(res, DeploymentIntentGroup{}) {
+ return DeploymentIntentGroup{}, pkgerrors.New("AppIntent already exists")
+ }
+
+ //Check if project exists
+ _, err = NewProjectClient().GetProject(p)
+ if err != nil {
+ return DeploymentIntentGroup{}, pkgerrors.New("Unable to find the project")
+ }
+
+ //check if compositeApp exists
+ _, err = NewCompositeAppClient().GetCompositeApp(ca, v, p)
+ if err != nil {
+ return DeploymentIntentGroup{}, pkgerrors.New("Unable to find the composite-app")
+ }
+
+ gkey := DeploymentIntentGroupKey{
+ Name: d.MetaData.Name,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ }
+
+ err = db.DBconn.Insert(c.storeName, gkey, nil, c.tagMetaData, d)
+ if err != nil {
+ return DeploymentIntentGroup{}, pkgerrors.Wrap(err, "Create DB entry error")
+ }
+
+ return d, nil
+}
+
+// GetDeploymentIntentGroup returns the DeploymentIntentGroup with a given name, project, compositeApp and version of compositeApp
+func (c *DeploymentIntentGroupClient) GetDeploymentIntentGroup(di string, p string, ca string, v string) (DeploymentIntentGroup, error) {
+
+ key := DeploymentIntentGroupKey{
+ Name: di,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ }
+
+ result, err := db.DBconn.Find(c.storeName, key, c.tagMetaData)
+ if err != nil {
+ return DeploymentIntentGroup{}, pkgerrors.Wrap(err, "Get DeploymentIntentGroup error")
+ }
+
+ if result != nil {
+ d := DeploymentIntentGroup{}
+ err = db.DBconn.Unmarshal(result[0], &d)
+ if err != nil {
+ return DeploymentIntentGroup{}, pkgerrors.Wrap(err, "Unmarshalling DeploymentIntentGroup")
+ }
+ return d, nil
+ }
+
+ return DeploymentIntentGroup{}, pkgerrors.New("Error getting DeploymentIntentGroup")
+
+}
+
+// DeleteDeploymentIntentGroup deletes a DeploymentIntentGroup
+func (c *DeploymentIntentGroupClient) DeleteDeploymentIntentGroup(di string, p string, ca string, v string) error {
+ k := DeploymentIntentGroupKey{
+ Name: di,
+ Project: p,
+ CompositeApp: ca,
+ Version: v,
+ }
+
+ err := db.DBconn.Remove(c.storeName, k)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Delete DeploymentIntentGroup entry;")
+ }
+ return nil
+
+}
diff --git a/src/orchestrator/pkg/module/deployment_intent_groups_test.go b/src/orchestrator/pkg/module/deployment_intent_groups_test.go
new file mode 100644
index 00000000..c0876ceb
--- /dev/null
+++ b/src/orchestrator/pkg/module/deployment_intent_groups_test.go
@@ -0,0 +1,230 @@
+/*
+ * 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 TestCreateDeploymentIntentGroup(t *testing.T) {
+ testCases := []struct {
+ label string
+ inputDeploymentIntentGrp DeploymentIntentGroup
+ inputProject string
+ inputCompositeApp string
+ inputCompositeAppVersion string
+ expectedError string
+ mockdb *db.MockDB
+ expected DeploymentIntentGroup
+ }{
+ {
+ label: "Create DeploymentIntentGroup",
+ inputDeploymentIntentGrp: DeploymentIntentGroup{
+ MetaData: DepMetaData{
+ Name: "testDeploymentIntentGroup",
+ Description: "DescriptionTestDeploymentIntentGroup",
+ UserData1: "userData1",
+ UserData2: "userData2",
+ },
+ Spec: DepSpecData{
+ Profile: "Testprofile",
+ Version: "version of deployment",
+ OverrideValuesObj: []OverrideValues{
+ {AppName: "TestAppName",
+ ValuesObj: map[string]string{
+ "imageRepository": "registry.hub.docker.com",
+ }},
+ {AppName: "TestAppName",
+ ValuesObj: map[string]string{
+ "imageRepository": "registry.hub.docker.com",
+ }},
+ },
+ },
+ },
+ inputProject: "testProject",
+ inputCompositeApp: "testCompositeApp",
+ inputCompositeAppVersion: "testCompositeAppVersion",
+ expected: DeploymentIntentGroup{
+ MetaData: DepMetaData{
+ Name: "testDeploymentIntentGroup",
+ Description: "DescriptionTestDeploymentIntentGroup",
+ UserData1: "userData1",
+ UserData2: "userData2",
+ },
+ Spec: DepSpecData{
+ Profile: "Testprofile",
+ Version: "version of deployment",
+ OverrideValuesObj: []OverrideValues{
+ {AppName: "TestAppName",
+ ValuesObj: map[string]string{
+ "imageRepository": "registry.hub.docker.com",
+ }},
+ {AppName: "TestAppName",
+ ValuesObj: map[string]string{
+ "imageRepository": "registry.hub.docker.com",
+ }},
+ },
+ },
+ },
+ 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
+ depIntentCli := NewDeploymentIntentGroupClient()
+ got, err := depIntentCli.CreateDeploymentIntentGroup(testCase.inputDeploymentIntentGrp, testCase.inputProject, testCase.inputCompositeApp, testCase.inputCompositeAppVersion)
+ if err != nil {
+ if testCase.expectedError == "" {
+ t.Fatalf("CreateDeploymentIntentGroup returned an unexpected error %s, ", err)
+ }
+ if strings.Contains(err.Error(), testCase.expectedError) == false {
+ t.Fatalf("CreateDeploymentIntentGroup returned an unexpected error %s", err)
+ }
+ } else {
+ if reflect.DeepEqual(testCase.expected, got) == false {
+ t.Errorf("CreateDeploymentIntentGroup returned unexpected body: got %v; "+" expected %v", got, testCase.expected)
+ }
+ }
+ })
+ }
+}
+
+func TestGetDeploymentIntentGroup(t *testing.T) {
+ testCases := []struct {
+ label string
+ inputDeploymentIntentGrp string
+ inputProject string
+ inputCompositeApp string
+ inputCompositeAppVersion string
+ expected DeploymentIntentGroup
+ expectedError string
+ mockdb *db.MockDB
+ }{
+ {
+ label: "Get DeploymentIntentGroup",
+ inputDeploymentIntentGrp: "testDeploymentIntentGroup",
+ inputProject: "testProject",
+ inputCompositeApp: "testCompositeApp",
+ inputCompositeAppVersion: "testCompositeAppVersion",
+ expected: DeploymentIntentGroup{
+ MetaData: DepMetaData{
+ Name: "testDeploymentIntentGroup",
+ Description: "DescriptionTestDeploymentIntentGroup",
+ UserData1: "userData1",
+ UserData2: "userData2",
+ },
+ Spec: DepSpecData{
+ Profile: "Testprofile",
+ Version: "version of deployment",
+ OverrideValuesObj: []OverrideValues{
+ {AppName: "TestAppName",
+ ValuesObj: map[string]string{
+ "imageRepository": "registry.hub.docker.com",
+ }},
+ {AppName: "TestAppName",
+ ValuesObj: map[string]string{
+ "imageRepository": "registry.hub.docker.com",
+ }},
+ },
+ },
+ },
+ expectedError: "",
+ mockdb: &db.MockDB{
+ Items: map[string]map[string][]byte{
+ DeploymentIntentGroupKey{
+ Name: "testDeploymentIntentGroup",
+ Project: "testProject",
+ CompositeApp: "testCompositeApp",
+ Version: "testCompositeAppVersion",
+ }.String(): {
+ "deploymentintentgroup": []byte(
+ "{\"metadata\":{\"name\":\"testDeploymentIntentGroup\"," +
+ "\"description\":\"DescriptionTestDeploymentIntentGroup\"," +
+ "\"userData1\": \"userData1\"," +
+ "\"userData2\": \"userData2\"}," +
+ "\"spec\":{\"profile\": \"Testprofile\"," +
+ "\"version\": \"version of deployment\"," +
+ "\"override-values\":[" +
+ "{" +
+ "\"app-name\": \"TestAppName\"," +
+ "\"values\": " +
+ "{" +
+ "\"imageRepository\":\"registry.hub.docker.com\"" +
+ "}" +
+ "}," +
+ "{" +
+ "\"app-name\": \"TestAppName\"," +
+ "\"values\": " +
+ "{" +
+ "\"imageRepository\":\"registry.hub.docker.com\"" +
+ "}" +
+ "}" +
+ "]}}"),
+ },
+ },
+ },
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ db.DBconn = testCase.mockdb
+ depIntentCli := NewDeploymentIntentGroupClient()
+ got, err := depIntentCli.GetDeploymentIntentGroup(testCase.inputDeploymentIntentGrp, testCase.inputProject, testCase.inputCompositeApp, testCase.inputCompositeAppVersion)
+ if err != nil {
+ if testCase.expectedError == "" {
+ t.Fatalf("GetDeploymentIntentGroup returned an unexpected error: %s", err)
+ }
+ if strings.Contains(err.Error(), testCase.expectedError) == false {
+ t.Fatalf("GetDeploymentIntentGroup returned an unexpected error: %s", err)
+ }
+ } else {
+ if reflect.DeepEqual(testCase.expected, got) == false {
+ t.Errorf("GetDeploymentIntentGroup 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
index 4098194e..8e739fc8 100644
--- a/src/orchestrator/pkg/module/generic_placement_intent.go
+++ b/src/orchestrator/pkg/module/generic_placement_intent.go
@@ -25,20 +25,20 @@ import (
// GenericPlacementIntent shall have 2 fields - metadata and spec
type GenericPlacementIntent struct {
- MetaData IntentMetaData `json:"metadata"`
- Spec IntentSpecData `json:"spec"`
+ MetaData GenIntentMetaData `json:"metadata"`
+ Spec GenIntentSpecData `json:"spec"`
}
-// IntentMetaData has name, description, userdata1, userdata2
-type IntentMetaData struct {
+// GenIntentMetaData has name, description, userdata1, userdata2
+type GenIntentMetaData 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 {
+// GenIntentSpecData has logical-cloud-name
+type GenIntentSpecData struct {
LogicalCloud string `json:"logical-cloud"`
}
diff --git a/src/orchestrator/pkg/module/generic_placement_intent_test.go b/src/orchestrator/pkg/module/generic_placement_intent_test.go
index 3cb29e61..c87f9ddc 100644
--- a/src/orchestrator/pkg/module/generic_placement_intent_test.go
+++ b/src/orchestrator/pkg/module/generic_placement_intent_test.go
@@ -38,13 +38,13 @@ func TestCreateGenericPlacementIntent(t *testing.T) {
{
label: "Create GenericPlacementIntent",
inputIntent: GenericPlacementIntent{
- MetaData: IntentMetaData{
+ MetaData: GenIntentMetaData{
Name: "testGenericPlacement",
Description: " A sample intent for testing",
UserData1: "userData1",
UserData2: "userData2",
},
- Spec: IntentSpecData{
+ Spec: GenIntentSpecData{
LogicalCloud: "logicalCloud1",
},
},
@@ -52,13 +52,13 @@ func TestCreateGenericPlacementIntent(t *testing.T) {
inputCompositeApp: "testCompositeApp",
inputCompositeAppVersion: "testCompositeAppVersion",
expected: GenericPlacementIntent{
- MetaData: IntentMetaData{
+ MetaData: GenIntentMetaData{
Name: "testGenericPlacement",
Description: " A sample intent for testing",
UserData1: "userData1",
UserData2: "userData2",
},
- Spec: IntentSpecData{
+ Spec: GenIntentSpecData{
LogicalCloud: "logicalCloud1",
},
},
@@ -128,13 +128,13 @@ func TestGetGenericPlacementIntent(t *testing.T) {
compositeAppName: "testCompositeApp",
compositeAppVersion: "testVersion",
expected: GenericPlacementIntent{
- MetaData: IntentMetaData{
+ MetaData: GenIntentMetaData{
Name: "testIntent",
Description: "A sample intent for testing",
UserData1: "userData1",
UserData2: "userData2",
},
- Spec: IntentSpecData{
+ Spec: GenIntentSpecData{
LogicalCloud: "logicalCloud1",
},
},
diff --git a/src/orchestrator/pkg/module/module.go b/src/orchestrator/pkg/module/module.go
index 34a84624..b46c6068 100644
--- a/src/orchestrator/pkg/module/module.go
+++ b/src/orchestrator/pkg/module/module.go
@@ -18,13 +18,15 @@ package module
// Client for using the services in the orchestrator
type Client struct {
- Project *ProjectClient
- CompositeApp *CompositeAppClient
- Controller *ControllerClient
- Cluster *ClusterClient
- // Add Clients for API's here
+ Project *ProjectClient
+ CompositeApp *CompositeAppClient
+ Controller *ControllerClient
+ Cluster *ClusterClient
GenericPlacementIntent *GenericPlacementIntentClient
AppIntent *AppIntentClient
+ // Add Clients for API's here
+ DeploymentIntentGroup *DeploymentIntentGroupClient
+ Intent *IntentClient
}
// NewClient creates a new client for using the services
@@ -38,6 +40,7 @@ func NewClient() *Client {
// Add Client API handlers here
c.GenericPlacementIntent = NewGenericPlacementIntentClient()
c.AppIntent = NewAppIntentClient()
-
+ c.DeploymentIntentGroup = NewDeploymentIntentGroupClient()
+ c.Intent = NewIntentClient()
return c
}