APIs for network, workload and interface intents 00/104100/12
authorEric Multanen <eric.w.multanen@intel.com>
Thu, 19 Mar 2020 23:07:43 +0000 (16:07 -0700)
committerRitu Sood <Ritu.Sood@intel.com>
Fri, 10 Apr 2020 20:36:32 +0000 (20:36 +0000)
Includes network controller intent and underlying
network workload intent and workload interface
intent APIs.

Issue-ID: MULTICLOUD-1029
Signed-off-by: Eric Multanen <eric.w.multanen@intel.com>
Change-Id: I9bb34e42785b16f39af81335b1f94dd5bb15d931

src/ncm/api/api.go
src/ncm/api/netcontrolintenthandler.go [new file with mode: 0644]
src/ncm/api/workloadifintenthandler.go [new file with mode: 0644]
src/ncm/api/workloadintenthandler.go [new file with mode: 0644]
src/ncm/pkg/module/module.go
src/ncm/pkg/module/module_definitions.go
src/ncm/pkg/module/netcontrolintent.go [new file with mode: 0644]
src/ncm/pkg/module/workloadifintent.go [new file with mode: 0644]
src/ncm/pkg/module/workloadintent.go [new file with mode: 0644]

index 3ff8671..fcef7b4 100644 (file)
@@ -51,6 +51,27 @@ func setClient(client, testClient interface{}) interface{} {
                                return c
                        }
                }
+       case *moduleLib.NetControlIntentClient:
+               if testClient != nil && reflect.TypeOf(testClient).Implements(reflect.TypeOf((*moduleLib.NetControlIntentManager)(nil)).Elem()) {
+                       c, ok := testClient.(moduleLib.NetControlIntentManager)
+                       if ok {
+                               return c
+                       }
+               }
+       case *moduleLib.WorkloadIntentClient:
+               if testClient != nil && reflect.TypeOf(testClient).Implements(reflect.TypeOf((*moduleLib.WorkloadIntentManager)(nil)).Elem()) {
+                       c, ok := testClient.(moduleLib.WorkloadIntentManager)
+                       if ok {
+                               return c
+                       }
+               }
+       case *moduleLib.WorkloadIfIntentClient:
+               if testClient != nil && reflect.TypeOf(testClient).Implements(reflect.TypeOf((*moduleLib.WorkloadIfIntentManager)(nil)).Elem()) {
+                       c, ok := testClient.(moduleLib.WorkloadIfIntentManager)
+                       if ok {
+                               return c
+                       }
+               }
        default:
                fmt.Printf("unknown type %T\n", cl)
        }
@@ -104,5 +125,32 @@ func NewRouter(testClient interface{}) *mux.Router {
        router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/provider-networks/{name}", providernetHandler.getProviderNetHandler).Methods("GET")
        router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/provider-networks/{name}", providernetHandler.deleteProviderNetHandler).Methods("DELETE")
 
+       netcontrolintentHandler := netcontrolintentHandler{
+               client: setClient(moduleClient.NetControlIntent, testClient).(moduleLib.NetControlIntentManager),
+       }
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent", netcontrolintentHandler.createHandler).Methods("POST")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent", netcontrolintentHandler.getHandler).Methods("GET")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{name}", netcontrolintentHandler.putHandler).Methods("PUT")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{name}", netcontrolintentHandler.getHandler).Methods("GET")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{name}", netcontrolintentHandler.deleteHandler).Methods("DELETE")
+
+       workloadintentHandler := workloadintentHandler{
+               client: setClient(moduleClient.WorkloadIntent, testClient).(moduleLib.WorkloadIntentManager),
+       }
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{net-control-intent}/workload-intents", workloadintentHandler.createHandler).Methods("POST")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{net-control-intent}/workload-intents", workloadintentHandler.getHandler).Methods("GET")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{net-control-intent}/workload-intents/{name}", workloadintentHandler.putHandler).Methods("PUT")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{net-control-intent}/workload-intents/{name}", workloadintentHandler.getHandler).Methods("GET")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{net-control-intent}/workload-intents/{name}", workloadintentHandler.deleteHandler).Methods("DELETE")
+
+       workloadifintentHandler := workloadifintentHandler{
+               client: setClient(moduleClient.WorkloadIfIntent, testClient).(moduleLib.WorkloadIfIntentManager),
+       }
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{net-control-intent}/workload-intents/{workload-intent}/interfaces", workloadifintentHandler.createHandler).Methods("POST")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{net-control-intent}/workload-intents/{workload-intent}/interfaces", workloadifintentHandler.getHandler).Methods("GET")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{net-control-intent}/workload-intents/{workload-intent}/interfaces/{name}", workloadifintentHandler.putHandler).Methods("PUT")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{net-control-intent}/workload-intents/{workload-intent}/interfaces/{name}", workloadifintentHandler.getHandler).Methods("GET")
+       router.HandleFunc("/projects/{project}/composite-apps/{composite-app-name}/{version}/network-controller-intent/{net-control-intent}/workload-intents/{workload-intent}/interfaces/{name}", workloadifintentHandler.deleteHandler).Methods("DELETE")
+
        return router
 }
diff --git a/src/ncm/api/netcontrolintenthandler.go b/src/ncm/api/netcontrolintenthandler.go
new file mode 100644 (file)
index 0000000..c59a389
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * 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"
+       "fmt"
+       "io"
+       "net/http"
+
+       moduleLib "github.com/onap/multicloud-k8s/src/ncm/pkg/module"
+       pkgerrors "github.com/pkg/errors"
+
+       "github.com/gorilla/mux"
+)
+
+// Used to store backend implementations objects
+// Also simplifies mocking for unit testing purposes
+type netcontrolintentHandler struct {
+       // Interface that implements Cluster operations
+       // We will set this variable with a mock interface for testing
+       client moduleLib.NetControlIntentManager
+}
+
+// Check for valid format of input parameters
+func validateNetControlIntentInputs(nci moduleLib.NetControlIntent) error {
+       // validate metadata
+       err := moduleLib.IsValidMetadata(nci.Metadata)
+       if err != nil {
+               return pkgerrors.Wrap(err, "Invalid network controller intent metadata")
+       }
+       return nil
+}
+
+// Create handles creation of the NetControlIntent entry in the database
+func (h netcontrolintentHandler) createHandler(w http.ResponseWriter, r *http.Request) {
+       var nci moduleLib.NetControlIntent
+       vars := mux.Vars(r)
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+
+       err := json.NewDecoder(r.Body).Decode(&nci)
+
+       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 nci.Metadata.Name == "" {
+               http.Error(w, "Missing name in POST request", http.StatusBadRequest)
+               return
+       }
+
+       err = validateNetControlIntentInputs(nci)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusBadRequest)
+               return
+       }
+
+       ret, err := h.client.CreateNetControlIntent(nci, project, compositeApp, compositeAppVersion, false)
+       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
+       }
+}
+
+// Put handles creation/update of the NetControlIntent entry in the database
+func (h netcontrolintentHandler) putHandler(w http.ResponseWriter, r *http.Request) {
+       var nci moduleLib.NetControlIntent
+       vars := mux.Vars(r)
+       name := vars["name"]
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+
+       err := json.NewDecoder(r.Body).Decode(&nci)
+
+       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 nci.Metadata.Name == "" {
+               http.Error(w, "Missing name in PUT request", http.StatusBadRequest)
+               return
+       }
+
+       // Name in URL should match name in body
+       if nci.Metadata.Name != name {
+               fmt.Printf("bodyname = %v, name= %v\n", nci.Metadata.Name, name)
+               http.Error(w, "Mismatched name in PUT request", http.StatusBadRequest)
+               return
+       }
+
+       err = validateNetControlIntentInputs(nci)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusBadRequest)
+               return
+       }
+
+       ret, err := h.client.CreateNetControlIntent(nci, project, compositeApp, compositeAppVersion, 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 NetControlIntent Name
+// Returns a NetControlIntent
+func (h netcontrolintentHandler) getHandler(w http.ResponseWriter, r *http.Request) {
+       vars := mux.Vars(r)
+       name := vars["name"]
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+       var ret interface{}
+       var err error
+
+       if len(name) == 0 {
+               ret, err = h.client.GetNetControlIntents(project, compositeApp, compositeAppVersion)
+               if err != nil {
+                       http.Error(w, err.Error(), http.StatusInternalServerError)
+                       return
+               }
+       } else {
+               ret, err = h.client.GetNetControlIntent(name, project, compositeApp, compositeAppVersion)
+               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 {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+}
+
+// Delete handles DELETE operations on a particular NetControlIntent  Name
+func (h netcontrolintentHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
+       vars := mux.Vars(r)
+       name := vars["name"]
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+
+       err := h.client.DeleteNetControlIntent(name, project, compositeApp, compositeAppVersion)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+
+       w.WriteHeader(http.StatusNoContent)
+}
diff --git a/src/ncm/api/workloadifintenthandler.go b/src/ncm/api/workloadifintenthandler.go
new file mode 100644 (file)
index 0000000..31472a5
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * 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"
+       "fmt"
+       "io"
+       "net/http"
+
+       moduleLib "github.com/onap/multicloud-k8s/src/ncm/pkg/module"
+       "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/validation"
+       pkgerrors "github.com/pkg/errors"
+
+       "github.com/gorilla/mux"
+)
+
+// Used to store backend implementations objects
+// Also simplifies mocking for unit testing purposes
+type workloadifintentHandler struct {
+       // Interface that implements workload intent operations
+       // We will set this variable with a mock interface for testing
+       client moduleLib.WorkloadIfIntentManager
+}
+
+// Check for valid format of input parameters
+func validateWorkloadIfIntentInputs(wif moduleLib.WorkloadIfIntent) error {
+       // validate metadata
+       err := moduleLib.IsValidMetadata(wif.Metadata)
+       if err != nil {
+               return pkgerrors.Wrap(err, "Invalid network controller intent metadata")
+       }
+
+       errs := validation.IsValidName(wif.Spec.IfName)
+       if len(errs) > 0 {
+               return pkgerrors.Errorf("Invalid interface name = [%v], errors: %v", wif.Spec.IfName, errs)
+       }
+
+       errs = validation.IsValidName(wif.Spec.NetworkName)
+       if len(errs) > 0 {
+               return pkgerrors.Errorf("Invalid network name = [%v], errors: %v", wif.Spec.NetworkName, errs)
+       }
+
+       // optional - only validate if supplied
+       if len(wif.Spec.DefaultGateway) > 0 {
+               errs = validation.IsValidName(wif.Spec.DefaultGateway)
+               if len(errs) > 0 {
+                       return pkgerrors.Errorf("Invalid default interface = [%v], errors: %v", wif.Spec.DefaultGateway, errs)
+               }
+       }
+
+       // optional - only validate if supplied
+       if len(wif.Spec.IpAddr) > 0 {
+               err = validation.IsIp(wif.Spec.IpAddr)
+               if err != nil {
+                       return pkgerrors.Errorf("Invalid IP address = [%v], errors: %v", wif.Spec.IpAddr, err)
+               }
+       }
+
+       // optional - only validate if supplied
+       if len(wif.Spec.MacAddr) > 0 {
+               err = validation.IsMac(wif.Spec.MacAddr)
+               if err != nil {
+                       return pkgerrors.Errorf("Invalid MAC address = [%v], errors: %v", wif.Spec.MacAddr, err)
+               }
+       }
+       return nil
+}
+
+// Create handles creation of the Network entry in the database
+func (h workloadifintentHandler) createHandler(w http.ResponseWriter, r *http.Request) {
+       var wif moduleLib.WorkloadIfIntent
+       vars := mux.Vars(r)
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+       netControlIntent := vars["net-control-intent"]
+       workloadIntent := vars["workload-intent"]
+
+       err := json.NewDecoder(r.Body).Decode(&wif)
+
+       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 wif.Metadata.Name == "" {
+               http.Error(w, "Missing name in POST request", http.StatusBadRequest)
+               return
+       }
+
+       // set default value
+       if len(wif.Spec.DefaultGateway) == 0 {
+               wif.Spec.DefaultGateway = "false" // set default value
+       }
+
+       err = validateWorkloadIfIntentInputs(wif)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusBadRequest)
+               return
+       }
+
+       ret, err := h.client.CreateWorkloadIfIntent(wif, project, compositeApp, compositeAppVersion, netControlIntent, workloadIntent, false)
+       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
+       }
+}
+
+// Put handles creation/update of the Network entry in the database
+func (h workloadifintentHandler) putHandler(w http.ResponseWriter, r *http.Request) {
+       var wif moduleLib.WorkloadIfIntent
+       vars := mux.Vars(r)
+       name := vars["name"]
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+       netControlIntent := vars["net-control-intent"]
+       workloadIntent := vars["workload-intent"]
+
+       err := json.NewDecoder(r.Body).Decode(&wif)
+
+       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 wif.Metadata.Name == "" {
+               http.Error(w, "Missing name in PUT request", http.StatusBadRequest)
+               return
+       }
+
+       // Name in URL should match name in body
+       if wif.Metadata.Name != name {
+               fmt.Printf("bodyname = %v, name= %v\n", wif.Metadata.Name, name)
+               http.Error(w, "Mismatched name in PUT request", http.StatusBadRequest)
+               return
+       }
+
+       // set default value
+       if len(wif.Spec.DefaultGateway) == 0 {
+               wif.Spec.DefaultGateway = "false" // set default value
+       }
+
+       err = validateWorkloadIfIntentInputs(wif)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusBadRequest)
+               return
+       }
+
+       ret, err := h.client.CreateWorkloadIfIntent(wif, project, compositeApp, compositeAppVersion, netControlIntent, workloadIntent, 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 Network Name
+// Returns a Network
+func (h workloadifintentHandler) getHandler(w http.ResponseWriter, r *http.Request) {
+       vars := mux.Vars(r)
+       name := vars["name"]
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+       netControlIntent := vars["net-control-intent"]
+       workloadIntent := vars["workload-intent"]
+       var ret interface{}
+       var err error
+
+       if len(name) == 0 {
+               ret, err = h.client.GetWorkloadIfIntents(project, compositeApp, compositeAppVersion, netControlIntent, workloadIntent)
+               if err != nil {
+                       http.Error(w, err.Error(), http.StatusInternalServerError)
+                       return
+               }
+       } else {
+               ret, err = h.client.GetWorkloadIfIntent(name, project, compositeApp, compositeAppVersion, netControlIntent, workloadIntent)
+               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 {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+}
+
+// Delete handles DELETE operations on a particular Network  Name
+func (h workloadifintentHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
+       vars := mux.Vars(r)
+       name := vars["name"]
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+       netControlIntent := vars["net-control-intent"]
+       workloadIntent := vars["workload-intent"]
+
+       err := h.client.DeleteWorkloadIfIntent(name, project, compositeApp, compositeAppVersion, netControlIntent, workloadIntent)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+
+       w.WriteHeader(http.StatusNoContent)
+}
diff --git a/src/ncm/api/workloadintenthandler.go b/src/ncm/api/workloadintenthandler.go
new file mode 100644 (file)
index 0000000..f1d0093
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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"
+       "fmt"
+       "io"
+       "net/http"
+
+       moduleLib "github.com/onap/multicloud-k8s/src/ncm/pkg/module"
+       "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/validation"
+       pkgerrors "github.com/pkg/errors"
+
+       "github.com/gorilla/mux"
+)
+
+// Used to store backend implementations objects
+// Also simplifies mocking for unit testing purposes
+type workloadintentHandler struct {
+       // Interface that implements workload intent operations
+       // We will set this variable with a mock interface for testing
+       client moduleLib.WorkloadIntentManager
+}
+
+// Check for valid format of input parameters
+func validateWorkloadIntentInputs(wi moduleLib.WorkloadIntent) error {
+       // validate metadata
+       err := moduleLib.IsValidMetadata(wi.Metadata)
+       if err != nil {
+               return pkgerrors.Wrap(err, "Invalid network controller intent metadata")
+       }
+
+       errs := validation.IsValidName(wi.Spec.AppName)
+       if len(errs) > 0 {
+               return pkgerrors.Errorf("Invalid application name = [%v], errors: %v", wi.Spec.AppName, errs)
+       }
+
+       errs = validation.IsValidName(wi.Spec.WorkloadResource)
+       if len(errs) > 0 {
+               return pkgerrors.Errorf("Invalid workload resource = [%v], errors: %v", wi.Spec.WorkloadResource, errs)
+       }
+
+       errs = validation.IsValidName(wi.Spec.Type)
+       if len(errs) > 0 {
+               return pkgerrors.Errorf("Invalid workload type = [%v], errors: %v", wi.Spec.Type, errs)
+       }
+       return nil
+}
+
+// Create handles creation of the Network entry in the database
+func (h workloadintentHandler) createHandler(w http.ResponseWriter, r *http.Request) {
+       var wi moduleLib.WorkloadIntent
+       vars := mux.Vars(r)
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+       netControlIntent := vars["net-control-intent"]
+
+       err := json.NewDecoder(r.Body).Decode(&wi)
+
+       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 wi.Metadata.Name == "" {
+               http.Error(w, "Missing name in POST request", http.StatusBadRequest)
+               return
+       }
+
+       err = validateWorkloadIntentInputs(wi)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusBadRequest)
+               return
+       }
+
+       ret, err := h.client.CreateWorkloadIntent(wi, project, compositeApp, compositeAppVersion, netControlIntent, false)
+       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
+       }
+}
+
+// Put handles creation/update of the Network entry in the database
+func (h workloadintentHandler) putHandler(w http.ResponseWriter, r *http.Request) {
+       var wi moduleLib.WorkloadIntent
+       vars := mux.Vars(r)
+       name := vars["name"]
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+       netControlIntent := vars["net-control-intent"]
+
+       err := json.NewDecoder(r.Body).Decode(&wi)
+
+       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 wi.Metadata.Name == "" {
+               http.Error(w, "Missing name in PUT request", http.StatusBadRequest)
+               return
+       }
+
+       // Name in URL should match name in body
+       if wi.Metadata.Name != name {
+               fmt.Printf("bodyname = %v, name= %v\n", wi.Metadata.Name, name)
+               http.Error(w, "Mismatched name in PUT request", http.StatusBadRequest)
+               return
+       }
+
+       err = validateWorkloadIntentInputs(wi)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusBadRequest)
+               return
+       }
+
+       ret, err := h.client.CreateWorkloadIntent(wi, project, compositeApp, compositeAppVersion, netControlIntent, 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 Network Name
+// Returns a Network
+func (h workloadintentHandler) getHandler(w http.ResponseWriter, r *http.Request) {
+       vars := mux.Vars(r)
+       name := vars["name"]
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+       netControlIntent := vars["net-control-intent"]
+       var ret interface{}
+       var err error
+
+       if len(name) == 0 {
+               ret, err = h.client.GetWorkloadIntents(project, compositeApp, compositeAppVersion, netControlIntent)
+               if err != nil {
+                       http.Error(w, err.Error(), http.StatusInternalServerError)
+                       return
+               }
+       } else {
+               ret, err = h.client.GetWorkloadIntent(name, project, compositeApp, compositeAppVersion, netControlIntent)
+               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 {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+}
+
+// Delete handles DELETE operations on a particular Network  Name
+func (h workloadintentHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
+       vars := mux.Vars(r)
+       name := vars["name"]
+       project := vars["project"]
+       compositeApp := vars["composite-app-name"]
+       compositeAppVersion := vars["version"]
+       netControlIntent := vars["net-control-intent"]
+
+       err := h.client.DeleteWorkloadIntent(name, project, compositeApp, compositeAppVersion, netControlIntent)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+
+       w.WriteHeader(http.StatusNoContent)
+}
index a995090..9655c1d 100644 (file)
 
 package module
 
-// Client for using the services in the orchestrator
+// Client for using the services in the ncm
 type Client struct {
-       Cluster     *ClusterClient
-       Network     *NetworkClient
-       ProviderNet *ProviderNetClient
+       Cluster          *ClusterClient
+       Network          *NetworkClient
+       ProviderNet      *ProviderNetClient
+       NetControlIntent *NetControlIntentClient
+       WorkloadIntent   *WorkloadIntentClient
+       WorkloadIfIntent *WorkloadIfIntentClient
        // Add Clients for API's here
 }
 
@@ -30,6 +33,9 @@ func NewClient() *Client {
        c.Cluster = NewClusterClient()
        c.Network = NewNetworkClient()
        c.ProviderNet = NewProviderNetClient()
+       c.NetControlIntent = NewNetControlIntentClient()
+       c.WorkloadIntent = NewWorkloadIntentClient()
+       c.WorkloadIfIntent = NewWorkloadIfIntentClient()
        // Add Client API handlers here
        return c
 }
index 1e83901..729a9db 100644 (file)
@@ -32,6 +32,9 @@ const CNI_TYPE_OVN4NFV string = "ovn4nfv"
 var CNI_TYPES = [...]string{CNI_TYPE_OVN4NFV}
 
 // 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"`
        Description string `json:"description"`
@@ -65,6 +68,31 @@ type Vlan struct {
        NodeLabelList         []string `json:"nodeLabelList"`
 }
 
+// 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
+}
+
 // Check for valid format of an Ipv4Subnet
 func ValidateSubnet(sub Ipv4Subnet) error {
        // verify subnet is in valid cidr format
diff --git a/src/ncm/pkg/module/netcontrolintent.go b/src/ncm/pkg/module/netcontrolintent.go
new file mode 100644 (file)
index 0000000..e94dd9d
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * 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 (
+       "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+       orchestrator "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
+
+       pkgerrors "github.com/pkg/errors"
+)
+
+// NetControlIntent contains the parameters needed for dynamic networks
+type NetControlIntent struct {
+       Metadata Metadata `json:"metadata"`
+}
+
+// NetControlIntentKey is the key structure that is used in the database
+type NetControlIntentKey struct {
+       NetControlIntent    string `json:"netcontrolintent"`
+       Project             string `json:"project"`
+       CompositeApp        string `json:"compositeapp"`
+       CompositeAppVersion string `json:"compositeappversion"`
+}
+
+// Manager is an interface exposing the NetControlIntent functionality
+type NetControlIntentManager interface {
+       CreateNetControlIntent(nci NetControlIntent, project, compositeapp, compositeappversion string, exists bool) (NetControlIntent, error)
+       GetNetControlIntent(name, project, compositeapp, compositeappversion string) (NetControlIntent, error)
+       GetNetControlIntents(project, compositeapp, compositeappversion string) ([]NetControlIntent, error)
+       DeleteNetControlIntent(name, project, compositeapp, compositeappversion string) error
+}
+
+// NetControlIntentClient implements the Manager
+// It will also be used to maintain some localized state
+type NetControlIntentClient struct {
+       db ClientDbInfo
+}
+
+// NewNetControlIntentClient returns an instance of the NetControlIntentClient
+// which implements the Manager
+func NewNetControlIntentClient() *NetControlIntentClient {
+       return &NetControlIntentClient{
+               db: ClientDbInfo{
+                       storeName: "orchestrator",
+                       tagMeta:   "netcontrolintentmetadata",
+               },
+       }
+}
+
+// CreateNetControlIntent - create a new NetControlIntent
+func (v *NetControlIntentClient) CreateNetControlIntent(nci NetControlIntent, project, compositeapp, compositeappversion string, exists bool) (NetControlIntent, error) {
+
+       //Construct key and tag to select the entry
+       key := NetControlIntentKey{
+               NetControlIntent:    nci.Metadata.Name,
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+       }
+
+       //Check if composite app/version exists
+       _, err := orchestrator.NewCompositeAppClient().GetCompositeApp(compositeapp, compositeappversion, project)
+       if err != nil {
+               return NetControlIntent{}, pkgerrors.New("Unable to find the composite app/version")
+       }
+
+       //Check if this NetControlIntent already exists
+       _, err = v.GetNetControlIntent(nci.Metadata.Name, project, compositeapp, compositeappversion)
+       if err == nil && !exists {
+               return NetControlIntent{}, pkgerrors.New("NetControlIntent already exists")
+       }
+
+       err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagMeta, nci)
+       if err != nil {
+               return NetControlIntent{}, pkgerrors.Wrap(err, "Creating DB Entry")
+       }
+
+       return nci, nil
+}
+
+// GetNetControlIntent returns the NetControlIntent for corresponding name
+func (v *NetControlIntentClient) GetNetControlIntent(name, project, compositeapp, compositeappversion string) (NetControlIntent, error) {
+
+       //Construct key and tag to select the entry
+       key := NetControlIntentKey{
+               NetControlIntent:    name,
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+       }
+
+       value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
+       if err != nil {
+               return NetControlIntent{}, pkgerrors.Wrap(err, "Get NetControlIntent")
+       }
+
+       //value is a byte array
+       if value != nil {
+               nci := NetControlIntent{}
+               err = db.DBconn.Unmarshal(value[0], &nci)
+               if err != nil {
+                       return NetControlIntent{}, pkgerrors.Wrap(err, "Unmarshalling Value")
+               }
+               return nci, nil
+       }
+
+       return NetControlIntent{}, pkgerrors.New("Error getting NetControlIntent")
+}
+
+// GetNetControlIntentList returns all of the NetControlIntent for corresponding name
+func (v *NetControlIntentClient) GetNetControlIntents(project, compositeapp, compositeappversion string) ([]NetControlIntent, error) {
+
+       //Construct key and tag to select the entry
+       key := NetControlIntentKey{
+               NetControlIntent:    "",
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+       }
+
+       var resp []NetControlIntent
+       values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
+       if err != nil {
+               return []NetControlIntent{}, pkgerrors.Wrap(err, "Get NetControlIntents")
+       }
+
+       for _, value := range values {
+               nci := NetControlIntent{}
+               err = db.DBconn.Unmarshal(value, &nci)
+               if err != nil {
+                       return []NetControlIntent{}, pkgerrors.Wrap(err, "Unmarshalling Value")
+               }
+               resp = append(resp, nci)
+       }
+
+       return resp, nil
+}
+
+// Delete the  NetControlIntent from database
+func (v *NetControlIntentClient) DeleteNetControlIntent(name, project, compositeapp, compositeappversion string) error {
+
+       //Construct key and tag to select the entry
+       key := NetControlIntentKey{
+               NetControlIntent:    name,
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+       }
+
+       err := db.DBconn.Remove(v.db.storeName, key)
+       if err != nil {
+               return pkgerrors.Wrap(err, "Delete NetControlIntent Entry;")
+       }
+
+       return nil
+}
diff --git a/src/ncm/pkg/module/workloadifintent.go b/src/ncm/pkg/module/workloadifintent.go
new file mode 100644 (file)
index 0000000..5506256
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * 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 (
+       "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+
+       pkgerrors "github.com/pkg/errors"
+)
+
+// WorkloadIfIntent contains the parameters needed for dynamic networks
+type WorkloadIfIntent struct {
+       Metadata Metadata             `json:"metadata"`
+       Spec     WorkloadIfIntentSpec `json:"spec"`
+}
+
+type WorkloadIfIntentSpec struct {
+       IfName         string `json:"interface"`
+       NetworkName    string `json:"name"`
+       DefaultGateway string `json:"defaultGateway"`       // optional, default value is "false"
+       IpAddr         string `json:"ipAddress,omitempty"`  // optional, if not provided then will be dynamically allocated
+       MacAddr        string `json:"macAddress,omitempty"` // optional, if not provided then will be dynamically allocated
+}
+
+// WorkloadIfIntentKey is the key structure that is used in the database
+type WorkloadIfIntentKey struct {
+       Project             string `json:"provider"`
+       CompositeApp        string `json:"compositeapp"`
+       CompositeAppVersion string `json:"compositeappversion"`
+       NetControlIntent    string `json:"netcontrolintent"`
+       WorkloadIntent      string `json:"workloadintent"`
+       WorkloadIfIntent    string `json:"workloadifintent"`
+}
+
+// Manager is an interface exposing the WorkloadIfIntent functionality
+type WorkloadIfIntentManager interface {
+       CreateWorkloadIfIntent(wi WorkloadIfIntent, project, compositeapp, compositeappversion, netcontrolintent, workloadintent string, exists bool) (WorkloadIfIntent, error)
+       GetWorkloadIfIntent(name, project, compositeapp, compositeappversion, netcontrolintent, workloadintent string) (WorkloadIfIntent, error)
+       GetWorkloadIfIntents(project, compositeapp, compositeappversion, netcontrolintent, workloadintent string) ([]WorkloadIfIntent, error)
+       DeleteWorkloadIfIntent(name, project, compositeapp, compositeappversion, netcontrolintent, workloadintent string) error
+}
+
+// WorkloadIfIntentClient implements the Manager
+// It will also be used to maintain some localized state
+type WorkloadIfIntentClient struct {
+       db ClientDbInfo
+}
+
+// NewWorkloadIfIntentClient returns an instance of the WorkloadIfIntentClient
+// which implements the Manager
+func NewWorkloadIfIntentClient() *WorkloadIfIntentClient {
+       return &WorkloadIfIntentClient{
+               db: ClientDbInfo{
+                       storeName: "orchestrator",
+                       tagMeta:   "workloadifintentmetadata",
+               },
+       }
+}
+
+// CreateWorkloadIfIntent - create a new WorkloadIfIntent
+func (v *WorkloadIfIntentClient) CreateWorkloadIfIntent(wif WorkloadIfIntent, project, compositeapp, compositeappversion, netcontrolintent, workloadintent string, exists bool) (WorkloadIfIntent, error) {
+
+       //Construct key and tag to select the entry
+       key := WorkloadIfIntentKey{
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+               NetControlIntent:    netcontrolintent,
+               WorkloadIntent:      workloadintent,
+               WorkloadIfIntent:    wif.Metadata.Name,
+       }
+
+       //Check if the Workload Intent exists
+       _, err := NewWorkloadIntentClient().GetWorkloadIntent(workloadintent, project, compositeapp, compositeappversion, netcontrolintent)
+       if err != nil {
+               return WorkloadIfIntent{}, pkgerrors.Errorf("Workload Intent %v does not exist", workloadintent)
+       }
+
+       //Check if this WorkloadIfIntent already exists
+       _, err = v.GetWorkloadIfIntent(wif.Metadata.Name, project, compositeapp, compositeappversion, netcontrolintent, workloadintent)
+       if err == nil && !exists {
+               return WorkloadIfIntent{}, pkgerrors.New("WorkloadIfIntent already exists")
+       }
+
+       err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagMeta, wif)
+       if err != nil {
+               return WorkloadIfIntent{}, pkgerrors.Wrap(err, "Creating DB Entry")
+       }
+
+       return wif, nil
+}
+
+// GetWorkloadIfIntent returns the WorkloadIfIntent for corresponding name
+func (v *WorkloadIfIntentClient) GetWorkloadIfIntent(name, project, compositeapp, compositeappversion, netcontrolintent, workloadintent string) (WorkloadIfIntent, error) {
+
+       //Construct key and tag to select the entry
+       key := WorkloadIfIntentKey{
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+               NetControlIntent:    netcontrolintent,
+               WorkloadIntent:      workloadintent,
+               WorkloadIfIntent:    name,
+       }
+
+       value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
+       if err != nil {
+               return WorkloadIfIntent{}, pkgerrors.Wrap(err, "Get WorkloadIfIntent")
+       }
+
+       //value is a byte array
+       if value != nil {
+               wif := WorkloadIfIntent{}
+               err = db.DBconn.Unmarshal(value[0], &wif)
+               if err != nil {
+                       return WorkloadIfIntent{}, pkgerrors.Wrap(err, "Unmarshalling Value")
+               }
+               return wif, nil
+       }
+
+       return WorkloadIfIntent{}, pkgerrors.New("Error getting WorkloadIfIntent")
+}
+
+// GetWorkloadIfIntentList returns all of the WorkloadIfIntent for corresponding name
+func (v *WorkloadIfIntentClient) GetWorkloadIfIntents(project, compositeapp, compositeappversion, netcontrolintent, workloadintent string) ([]WorkloadIfIntent, error) {
+
+       //Construct key and tag to select the entry
+       key := WorkloadIfIntentKey{
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+               NetControlIntent:    netcontrolintent,
+               WorkloadIntent:      workloadintent,
+               WorkloadIfIntent:    "",
+       }
+
+       var resp []WorkloadIfIntent
+       values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
+       if err != nil {
+               return []WorkloadIfIntent{}, pkgerrors.Wrap(err, "Get WorkloadIfIntents")
+       }
+
+       for _, value := range values {
+               wif := WorkloadIfIntent{}
+               err = db.DBconn.Unmarshal(value, &wif)
+               if err != nil {
+                       return []WorkloadIfIntent{}, pkgerrors.Wrap(err, "Unmarshalling Value")
+               }
+               resp = append(resp, wif)
+       }
+
+       return resp, nil
+}
+
+// Delete the  WorkloadIfIntent from database
+func (v *WorkloadIfIntentClient) DeleteWorkloadIfIntent(name, project, compositeapp, compositeappversion, netcontrolintent, workloadintent string) error {
+
+       //Construct key and tag to select the entry
+       key := WorkloadIfIntentKey{
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+               NetControlIntent:    netcontrolintent,
+               WorkloadIntent:      workloadintent,
+               WorkloadIfIntent:    name,
+       }
+
+       err := db.DBconn.Remove(v.db.storeName, key)
+       if err != nil {
+               return pkgerrors.Wrap(err, "Delete WorkloadIfIntent Entry;")
+       }
+
+       return nil
+}
diff --git a/src/ncm/pkg/module/workloadintent.go b/src/ncm/pkg/module/workloadintent.go
new file mode 100644 (file)
index 0000000..e691695
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * 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 (
+       "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+
+       pkgerrors "github.com/pkg/errors"
+)
+
+// WorkloadIntent contains the parameters needed for dynamic networks
+type WorkloadIntent struct {
+       Metadata Metadata           `json:"metadata"`
+       Spec     WorkloadIntentSpec `json:"spec"`
+}
+
+type WorkloadIntentSpec struct {
+       AppName          string `json:"application-name"`
+       WorkloadResource string `json:"workload-resource"`
+       Type             string `json:"type"`
+}
+
+// WorkloadIntentKey is the key structure that is used in the database
+type WorkloadIntentKey struct {
+       Project             string `json:"provider"`
+       CompositeApp        string `json:"compositeapp"`
+       CompositeAppVersion string `json:"compositeappversion"`
+       NetControlIntent    string `json:"netcontrolintent"`
+       WorkloadIntent      string `json:"workloadintent"`
+}
+
+// Manager is an interface exposing the WorkloadIntent functionality
+type WorkloadIntentManager interface {
+       CreateWorkloadIntent(wi WorkloadIntent, project, compositeapp, compositeappversion, netcontrolintent string, exists bool) (WorkloadIntent, error)
+       GetWorkloadIntent(name, project, compositeapp, compositeappversion, netcontrolintent string) (WorkloadIntent, error)
+       GetWorkloadIntents(project, compositeapp, compositeappversion, netcontrolintent string) ([]WorkloadIntent, error)
+       DeleteWorkloadIntent(name, project, compositeapp, compositeappversion, netcontrolintent string) error
+}
+
+// WorkloadIntentClient implements the Manager
+// It will also be used to maintain some localized state
+type WorkloadIntentClient struct {
+       db ClientDbInfo
+}
+
+// NewWorkloadIntentClient returns an instance of the WorkloadIntentClient
+// which implements the Manager
+func NewWorkloadIntentClient() *WorkloadIntentClient {
+       return &WorkloadIntentClient{
+               db: ClientDbInfo{
+                       storeName: "orchestrator",
+                       tagMeta:   "workloadintentmetadata",
+               },
+       }
+}
+
+// CreateWorkloadIntent - create a new WorkloadIntent
+func (v *WorkloadIntentClient) CreateWorkloadIntent(wi WorkloadIntent, project, compositeapp, compositeappversion, netcontrolintent string, exists bool) (WorkloadIntent, error) {
+
+       //Construct key and tag to select the entry
+       key := WorkloadIntentKey{
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+               NetControlIntent:    netcontrolintent,
+               WorkloadIntent:      wi.Metadata.Name,
+       }
+
+       //Check if the Network Control Intent exists
+       _, err := NewNetControlIntentClient().GetNetControlIntent(netcontrolintent, project, compositeapp, compositeappversion)
+       if err != nil {
+               return WorkloadIntent{}, pkgerrors.Errorf("Network Control Intent %v does not exist", netcontrolintent)
+       }
+
+       //Check if this WorkloadIntent already exists
+       _, err = v.GetWorkloadIntent(wi.Metadata.Name, project, compositeapp, compositeappversion, netcontrolintent)
+       if err == nil && !exists {
+               return WorkloadIntent{}, pkgerrors.New("WorkloadIntent already exists")
+       }
+
+       err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagMeta, wi)
+       if err != nil {
+               return WorkloadIntent{}, pkgerrors.Wrap(err, "Creating DB Entry")
+       }
+
+       return wi, nil
+}
+
+// GetWorkloadIntent returns the WorkloadIntent for corresponding name
+func (v *WorkloadIntentClient) GetWorkloadIntent(name, project, compositeapp, compositeappversion, netcontrolintent string) (WorkloadIntent, error) {
+
+       //Construct key and tag to select the entry
+       key := WorkloadIntentKey{
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+               NetControlIntent:    netcontrolintent,
+               WorkloadIntent:      name,
+       }
+
+       value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
+       if err != nil {
+               return WorkloadIntent{}, pkgerrors.Wrap(err, "Get WorkloadIntent")
+       }
+
+       //value is a byte array
+       if value != nil {
+               wi := WorkloadIntent{}
+               err = db.DBconn.Unmarshal(value[0], &wi)
+               if err != nil {
+                       return WorkloadIntent{}, pkgerrors.Wrap(err, "Unmarshalling Value")
+               }
+               return wi, nil
+       }
+
+       return WorkloadIntent{}, pkgerrors.New("Error getting WorkloadIntent")
+}
+
+// GetWorkloadIntentList returns all of the WorkloadIntent for corresponding name
+func (v *WorkloadIntentClient) GetWorkloadIntents(project, compositeapp, compositeappversion, netcontrolintent string) ([]WorkloadIntent, error) {
+
+       //Construct key and tag to select the entry
+       key := WorkloadIntentKey{
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+               NetControlIntent:    netcontrolintent,
+               WorkloadIntent:      "",
+       }
+
+       var resp []WorkloadIntent
+       values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
+       if err != nil {
+               return []WorkloadIntent{}, pkgerrors.Wrap(err, "Get WorkloadIntents")
+       }
+
+       for _, value := range values {
+               wi := WorkloadIntent{}
+               err = db.DBconn.Unmarshal(value, &wi)
+               if err != nil {
+                       return []WorkloadIntent{}, pkgerrors.Wrap(err, "Unmarshalling Value")
+               }
+               resp = append(resp, wi)
+       }
+
+       return resp, nil
+}
+
+// Delete the  WorkloadIntent from database
+func (v *WorkloadIntentClient) DeleteWorkloadIntent(name, project, compositeapp, compositeappversion, netcontrolintent string) error {
+
+       //Construct key and tag to select the entry
+       key := WorkloadIntentKey{
+               Project:             project,
+               CompositeApp:        compositeapp,
+               CompositeAppVersion: compositeappversion,
+               NetControlIntent:    netcontrolintent,
+               WorkloadIntent:      name,
+       }
+
+       err := db.DBconn.Remove(v.db.storeName, key)
+       if err != nil {
+               return pkgerrors.Wrap(err, "Delete WorkloadIntent Entry;")
+       }
+
+       return nil
+}