summaryrefslogtreecommitdiffstats
path: root/src/dcm/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'src/dcm/pkg')
-rw-r--r--src/dcm/pkg/module/apply.go451
-rw-r--r--src/dcm/pkg/module/cluster.go205
-rw-r--r--src/dcm/pkg/module/cluster_test.go115
-rw-r--r--src/dcm/pkg/module/keyvalue.go205
-rw-r--r--src/dcm/pkg/module/keyvalue_test.go115
-rw-r--r--src/dcm/pkg/module/logicalcloud.go291
-rw-r--r--src/dcm/pkg/module/logicalcloud_test.go157
-rw-r--r--src/dcm/pkg/module/module.go39
-rw-r--r--src/dcm/pkg/module/quota.go222
-rw-r--r--src/dcm/pkg/module/quota_test.go115
-rw-r--r--src/dcm/pkg/module/userpermissions.go193
-rw-r--r--src/dcm/pkg/module/userpermissions_test.go110
12 files changed, 2218 insertions, 0 deletions
diff --git a/src/dcm/pkg/module/apply.go b/src/dcm/pkg/module/apply.go
new file mode 100644
index 00000000..c918f749
--- /dev/null
+++ b/src/dcm/pkg/module/apply.go
@@ -0,0 +1,451 @@
+/*
+* 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 (
+ "strings"
+ "fmt"
+ "crypto/rsa"
+ "crypto/rand"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/json"
+ "encoding/pem"
+ "encoding/base64"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext"
+ log "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/logutils"
+ "gopkg.in/yaml.v2"
+ pkgerrors "github.com/pkg/errors"
+
+)
+
+type Resource struct {
+ ApiVersion string `yaml:"apiVersion"`
+ Kind string `yaml:"kind"`
+ MetaData MetaDatas `yaml:"metadata"`
+ Specification Specs `yaml:"spec,omitempty"`
+ Rules []RoleRules `yaml:"rules,omitempty"`
+ Subjects []RoleSubjects `yaml:"subjects,omitempty"`
+ RoleRefs RoleRef `yaml:"roleRef,omitempty"`
+}
+
+type MetaDatas struct {
+ Name string `yaml:"name"`
+ Namespace string `yaml:"namespace,omitempty"`
+}
+
+type Specs struct {
+ Request string `yaml:"request,omitempty"`
+ Usages []string `yaml:"usages,omitempty"`
+ //Hard logicalcloud.QSpec `yaml:"hard,omitempty"`
+ Hard QSpec `yaml:"hard,omitempty"`
+}
+
+type RoleRules struct {
+ ApiGroups []string `yaml:"apiGroups"`
+ Resources []string `yaml:"resources"`
+ Verbs []string `yaml:"verbs"`
+}
+
+type RoleSubjects struct {
+ Kind string `yaml:"kind"`
+ Name string `yaml:"name"`
+ ApiGroup string `yaml:"apiGroup"`
+}
+
+type RoleRef struct {
+ Kind string `yaml:"kind"`
+ Name string `yaml:"name"`
+ ApiGroup string `yaml:"apiGroup"`
+}
+
+
+func createNamespace(logicalcloud LogicalCloud) (string, error) {
+
+ namespace := Resource{
+ ApiVersion: "v1",
+ Kind: "Namespace",
+ MetaData: MetaDatas{
+ Name: logicalcloud.Specification.NameSpace,
+ },
+ }
+
+ nsData, err := yaml.Marshal(&namespace)
+ if err != nil {
+ return "", err
+ }
+
+
+ return string(nsData), nil
+}
+
+func createRole(logicalcloud LogicalCloud) (string, error) {
+
+ userPermissions := logicalcloud.Specification.User.UserPermissions[0]
+
+ role := Resource{
+ ApiVersion: "rbac.authorization.k8s.io/v1beta1",
+ Kind: "Role",
+ MetaData: MetaDatas{
+ Name: strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "-role"}, ""),
+ Namespace: logicalcloud.Specification.NameSpace,
+ },
+ Rules: []RoleRules{ RoleRules{
+ ApiGroups: userPermissions.APIGroups,
+ Resources: userPermissions.Resources,
+ Verbs: userPermissions.Verbs,
+ },
+ },
+
+ }
+
+ roleData, err := yaml.Marshal(&role)
+ if err != nil {
+ return "", err
+ }
+
+ return string(roleData), nil
+}
+
+func createRoleBinding(logicalcloud LogicalCloud) (string, error) {
+
+ roleBinding := Resource{
+ ApiVersion: "rbac.authorization.k8s.io/v1beta1",
+ Kind: "RoleBinding",
+ MetaData: MetaDatas{
+ Name: strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "-roleBinding"}, ""),
+ Namespace: logicalcloud.Specification.NameSpace,
+ },
+ Subjects: []RoleSubjects{ RoleSubjects{
+ Kind: "User",
+ Name: logicalcloud.Specification.User.UserName,
+ ApiGroup: "",
+ },
+ },
+
+ RoleRefs: RoleRef{
+ Kind: "Role",
+ Name: strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "-role"}, ""),
+ ApiGroup: "",
+ },
+ }
+
+ rBData, err := yaml.Marshal(&roleBinding)
+ if err != nil {
+ return "", err
+ }
+
+
+ return string(rBData), nil
+
+}
+
+func createQuota(quota []Quota, namespace string) (string, error) {
+ lcQuota := quota[0]
+
+ q := Resource{
+ ApiVersion: "v1",
+ Kind: "ResourceQuota",
+ MetaData: MetaDatas{
+ Name: lcQuota.MetaData.QuotaName,
+ Namespace: namespace,
+ },
+ Specification: Specs{
+ Hard: lcQuota.Specification,
+ },
+ }
+
+ qData, err := yaml.Marshal(&q)
+ if err != nil {
+ return "", err
+ }
+
+
+
+ return string(qData), nil
+
+}
+
+func createUserCSR(logicalcloud LogicalCloud) (string, error) {
+ KEYSIZE := 4096
+ userName := logicalcloud.Specification.User.UserName
+
+ key, err := rsa.GenerateKey(rand.Reader, KEYSIZE)
+ if err != nil {
+ return "", err
+ }
+
+ csrTemplate := x509.CertificateRequest{Subject: pkix.Name{CommonName: userName,},
+ }
+
+ csrCert, err := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, key)
+ if err != nil {
+ return "", err
+ }
+
+ //Encode csr
+ csr := pem.EncodeToMemory(&pem.Block{
+ Type: "CERTIFICATE REQUEST",
+ Bytes: csrCert,
+ })
+
+ csrObj := Resource{
+ ApiVersion: "certificates.k8s.io/v1beta1",
+ Kind: "CertificateSigningRequest",
+ MetaData: MetaDatas{
+ Name: strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "-user-csr"}, ""),
+ Namespace: logicalcloud.Specification.NameSpace,
+ },
+ Specification: Specs{
+ Request: base64.StdEncoding.EncodeToString(csr),
+ Usages: []string{"digital signature", "key encipherment"},
+ },
+ }
+
+ csrData, err := yaml.Marshal(&csrObj)
+ if err != nil {
+ return "", err
+ }
+
+
+ return string(csrData), nil
+
+
+}
+
+// TODO:
+// Install istio
+// Store user key for user creation
+// Code to run kubectl commands for user
+// kubectl certificate approve lc1-user-cert
+// kubectl get csr lc1-user-cert -o jsonpath='{.status.certificate}' | base64 --decode > user.crt
+// kubectl config set-credentials user --client-certificate=<user.crt> --client-key=<user.key>
+// kubectl config set-context user-context --cluster=cluster-name --namespace=lc1 --user=user
+
+
+func CreateEtcdContext(logicalcloud LogicalCloud, clusterList []Cluster,
+ quotaList []Quota ) error {
+
+ APP := "logical-cloud"
+ logicalCloudName := logicalcloud.MetaData.LogicalCloudName
+
+
+ //Resource Names
+ namespaceName := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "+namespace"}, "")
+ roleName := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "+role"}, "")
+ roleBindingName := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "+roleBinding"}, "")
+ quotaName := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "+quota"}, "")
+ csrName := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "+CertificateSigningRequest"}, "")
+
+ // Get resources to be added
+ namespace, err := createNamespace(logicalcloud)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error Creating Namespace YAML for logical cloud")
+ }
+
+ role, err := createRole(logicalcloud)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error Creating Role YAML for logical cloud")
+ }
+
+ roleBinding, err := createRoleBinding(logicalcloud)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error Creating RoleBinding YAML for logical cloud")
+ }
+
+ quota, err := createQuota(quotaList, logicalcloud.Specification.NameSpace)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error Creating Quota YAML for logical cloud")
+ }
+
+ csr, err := createUserCSR(logicalcloud)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error Creating User CSR for logical cloud")
+ }
+
+
+ context := appcontext.AppContext{}
+ ctxVal, err := context.InitAppContext()
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error creating AppContext")
+ }
+
+ fmt.Printf("%v\n", ctxVal)
+
+ handle, err := context.CreateCompositeApp()
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error creating AppContext CompositeApp")
+ }
+
+
+ appHandle, err := context.AddApp(handle, APP)
+ if err != nil {
+ cleanuperr := context.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Warn("Error cleaning AppContext CompositeApp create failure", log.Fields{
+ "logical-cloud": logicalCloudName,
+ })
+ }
+ return pkgerrors.Wrap(err, "Error adding App to AppContext")
+ }
+
+
+ // Iterate through cluster list and add all the clusters
+ for _, cluster:= range clusterList {
+ clusterName := strings.Join([]string{cluster.Specification.ClusterProvider, "+", cluster.Specification.ClusterName, }, "")
+ clusterHandle, err := context.AddCluster(appHandle, clusterName)
+
+ if err != nil {
+ cleanuperr := context.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Warn("Error cleaning AppContext after add cluster failure", log.Fields{
+ "cluster-provider": cluster.Specification.ClusterProvider,
+ "cluster": cluster.Specification.ClusterName,
+ "logical-cloud": logicalCloudName,
+
+ })
+ }
+ return pkgerrors.Wrap(err, "Error adding Cluster to AppContext")
+ }
+
+ // Add namespace resource to each cluster
+ _, err = context.AddResource(clusterHandle, namespaceName, namespace)
+ if err != nil {
+ cleanuperr := context.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Warn("Error cleaning AppContext after add namespace resource failure", log.Fields{
+ "cluster-provider": cluster.Specification.ClusterProvider,
+ "cluster": cluster.Specification.ClusterName,
+ "logical-cloud": logicalCloudName,
+
+ })
+ }
+ return pkgerrors.Wrap(err, "Error adding Namespace Resource to AppContext")
+ }
+
+ // Add csr resource to each cluster
+ _, err = context.AddResource(clusterHandle, csrName, csr)
+ if err != nil {
+ cleanuperr := context.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Warn("Error cleaning AppContext after add CSR resource failure", log.Fields{
+ "cluster-provider": cluster.Specification.ClusterProvider,
+ "cluster": cluster.Specification.ClusterName,
+ "logical-cloud": logicalCloudName,
+
+ })
+ }
+ return pkgerrors.Wrap(err, "Error adding CSR Resource to AppContext")
+ }
+
+
+
+ // Add Role resource to each cluster
+ _, err = context.AddResource(clusterHandle, roleName, role)
+ if err != nil {
+ cleanuperr := context.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Warn("Error cleaning AppContext after add role resource failure", log.Fields{
+ "cluster-provider": cluster.Specification.ClusterProvider,
+ "cluster": cluster.Specification.ClusterName,
+ "logical-cloud": logicalCloudName,
+
+ })
+ }
+ return pkgerrors.Wrap(err, "Error adding role Resource to AppContext")
+ }
+
+ // Add RoleBinding resource to each cluster
+ _, err = context.AddResource(clusterHandle, roleBindingName, roleBinding)
+ if err != nil {
+ cleanuperr := context.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Warn("Error cleaning AppContext after add roleBinding resource failure", log.Fields{
+ "cluster-provider": cluster.Specification.ClusterProvider,
+ "cluster": cluster.Specification.ClusterName,
+ "logical-cloud": logicalCloudName,
+
+ })
+ }
+ return pkgerrors.Wrap(err, "Error adding roleBinding Resource to AppContext")
+ }
+
+ // Add quota resource to each cluster
+ _, err = context.AddResource(clusterHandle, quotaName, quota)
+ if err != nil {
+ cleanuperr := context.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Warn("Error cleaning AppContext after add quota resource failure", log.Fields{
+ "cluster-provider": cluster.Specification.ClusterProvider,
+ "cluster": cluster.Specification.ClusterName,
+ "logical-cloud": logicalCloudName,
+
+ })
+ }
+ return pkgerrors.Wrap(err, "Error adding quota Resource to AppContext")
+ }
+
+ // Add Resource Order and Resource Dependency
+ resOrder, err := json.Marshal(map[string][]string{"resorder" : []string{namespaceName, quotaName, csrName, roleName, roleBindingName}})
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error creating resource order JSON")
+ }
+
+ resDependency, err := json.Marshal(map[string]map[string]string{"resdependency" : map[string]string{namespaceName : "go",
+ quotaName : strings.Join([]string{"wait on ", namespaceName}, ""), csrName: strings.Join([]string{"wait on ", quotaName}, ""),
+ roleName : strings.Join([]string{"wait on ", csrName}, ""), roleBindingName: strings.Join([]string{"wait on ", roleName}, ""),}})
+
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error creating resource dependency JSON")
+ }
+
+ _, err = context.AddInstruction(clusterHandle, "resource", "order", string(resOrder))
+ if err != nil {
+ cleanuperr := context.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Warn("Error cleaning AppContext after add instruction failure", log.Fields{
+ "cluster-provider": cluster.Specification.ClusterProvider,
+ "cluster": cluster.Specification.ClusterName,
+ "logical-cloud": logicalCloudName,
+
+ })
+ }
+ return pkgerrors.Wrap(err, "Error adding instruction order to AppContext")
+ }
+
+ _, err = context.AddInstruction(clusterHandle, "resource", "dependency", string(resDependency))
+ if err != nil {
+ cleanuperr := context.DeleteCompositeApp()
+ if cleanuperr != nil {
+ log.Warn("Error cleaning AppContext after add instruction failure", log.Fields{
+ "cluster-provider": cluster.Specification.ClusterProvider,
+ "cluster": cluster.Specification.ClusterName,
+ "logical-cloud": logicalCloudName,
+
+ })
+ }
+ return pkgerrors.Wrap(err, "Error adding instruction dependency to AppContext")
+ }
+
+
+
+ }
+
+ return nil
+
+
+}
diff --git a/src/dcm/pkg/module/cluster.go b/src/dcm/pkg/module/cluster.go
new file mode 100644
index 00000000..38848990
--- /dev/null
+++ b/src/dcm/pkg/module/cluster.go
@@ -0,0 +1,205 @@
+/*
+* 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 (
+ pkgerrors "github.com/pkg/errors"
+)
+
+// Cluster contains the parameters needed for a Cluster
+type Cluster struct {
+ MetaData ClusterMeta `json:"metadata"`
+ Specification ClusterSpec `json:"spec"`
+}
+
+type ClusterMeta struct {
+ ClusterReference string `json:"name"`
+ Description string `json:"description"`
+ UserData1 string `json:"userData1"`
+ UserData2 string `json:"userData2"`
+}
+
+type ClusterSpec struct {
+ ClusterProvider string `json:"cluster-provider"`
+ ClusterName string `json:"cluster-name"`
+ LoadBalancerIP string `json:"loadbalancer-ip"`
+}
+
+
+type ClusterKey struct {
+ Project string `json:"project"`
+ LogicalCloudName string `json:"logical-cloud-name"`
+ ClusterReference string `json:"clname"`
+}
+
+// ClusterManager is an interface that exposes the connection
+// functionality
+type ClusterManager interface {
+ CreateCluster(project, logicalCloud string, c Cluster) (Cluster, error)
+ GetCluster(project, logicalCloud, name string) (Cluster, error)
+ GetAllClusters(project, logicalCloud string) ([]Cluster, error)
+ DeleteCluster(project, logicalCloud, name string) error
+ UpdateCluster(project, logicalCloud, name string, c Cluster) (Cluster, error)
+}
+
+// ClusterClient implements the ClusterManager
+// It will also be used to maintain some localized state
+type ClusterClient struct {
+ storeName string
+ tagMeta string
+ util Utility
+}
+
+// ClusterClient returns an instance of the ClusterClient
+// which implements the ClusterManager
+func NewClusterClient() *ClusterClient {
+ service := DBService{}
+ return &ClusterClient{
+ storeName: "orchestrator",
+ tagMeta: "cluster",
+ util: service,
+ }
+}
+
+// Create entry for the cluster reference resource in the database
+func (v *ClusterClient) CreateCluster(project, logicalCloud string, c Cluster) (Cluster, error) {
+
+ //Construct key consisting of name
+ key := ClusterKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ ClusterReference: c.MetaData.ClusterReference,
+ }
+
+ //Check if project exists
+ err := v.util.CheckProject(project)
+ if err != nil {
+ return Cluster{}, pkgerrors.New("Unable to find the project")
+ }
+ //check if logical cloud exists
+ err = v.util.CheckLogicalCloud(project, logicalCloud)
+ if err != nil {
+ return Cluster{}, pkgerrors.New("Unable to find the logical cloud")
+ }
+ //Check if this Cluster reference already exists
+ _, err = v.GetCluster(project, logicalCloud, c.MetaData.ClusterReference)
+ if err == nil {
+ return Cluster{}, pkgerrors.New("Cluster reference already exists")
+ }
+
+ err = v.util.DBInsert(v.storeName, key, nil, v.tagMeta, c)
+ if err != nil {
+ return Cluster{}, pkgerrors.Wrap(err, "Creating DB Entry")
+ }
+
+ return c, nil
+}
+
+// Get returns Cluster for corresponding cluster reference
+func (v *ClusterClient) GetCluster(project, logicalCloud, clusterReference string)(Cluster, error) {
+
+ //Construct the composite key to select the entry
+ key := ClusterKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ ClusterReference: clusterReference,
+ }
+
+ value, err := v.util.DBFind(v.storeName, key, v.tagMeta)
+ if err != nil {
+ return Cluster{}, pkgerrors.Wrap(err, "Get Cluster reference")
+ }
+
+ //value is a byte array
+ if value != nil {
+ cl := Cluster{}
+ err = v.util.DBUnmarshal(value[0], &cl)
+ if err != nil {
+ return Cluster{}, pkgerrors.Wrap(err, "Unmarshaling value")
+ }
+ return cl, nil
+ }
+
+ return Cluster{}, pkgerrors.New("Error getting Cluster")
+}
+
+
+// GetAll returns all cluster references in the logical cloud
+func (v *ClusterClient) GetAllClusters(project, logicalCloud string)([]Cluster, error) {
+ //Construct the composite key to select clusters
+ key := ClusterKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ ClusterReference: "",
+ }
+ var resp []Cluster
+ values, err := v.util.DBFind(v.storeName, key, v.tagMeta)
+ if err != nil {
+ return []Cluster{}, pkgerrors.Wrap(err, "Get All Cluster references")
+ }
+
+ for _, value := range values {
+ cl := Cluster{}
+ err = v.util.DBUnmarshal(value, &cl)
+ if err != nil {
+ return []Cluster{}, pkgerrors.Wrap(err, "Unmarshaling values")
+ }
+ resp = append(resp, cl)
+ }
+
+ return resp, nil
+}
+
+// Delete the Cluster reference entry from database
+func (v *ClusterClient) DeleteCluster(project, logicalCloud, clusterReference string) error {
+ //Construct the composite key to select the entry
+ key := ClusterKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ ClusterReference: clusterReference,
+ }
+ err := v.util.DBRemove(v.storeName, key)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Delete Cluster Reference")
+ }
+ return nil
+}
+
+// Update an entry for the Cluster reference in the database
+func (v *ClusterClient) UpdateCluster(project, logicalCloud, clusterReference string, c Cluster) (Cluster, error) {
+
+ key := ClusterKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ ClusterReference: clusterReference,
+ }
+
+ //Check for name mismatch in cluster reference
+ if c.MetaData.ClusterReference != clusterReference {
+ return Cluster{}, pkgerrors.New("Update Error - Cluster reference mismatch")
+ }
+ //Check if this Cluster reference exists
+ _, err := v.GetCluster(project, logicalCloud, clusterReference)
+ if err != nil {
+ return Cluster{}, pkgerrors.New("Update Error - Cluster reference doesn't exist")
+ }
+ err = v.util.DBInsert(v.storeName, key, nil, v.tagMeta, c)
+ if err != nil {
+ return Cluster{}, pkgerrors.Wrap(err, "Updating DB Entry")
+ }
+ return c, nil
+}
diff --git a/src/dcm/pkg/module/cluster_test.go b/src/dcm/pkg/module/cluster_test.go
new file mode 100644
index 00000000..d42935db
--- /dev/null
+++ b/src/dcm/pkg/module/cluster_test.go
@@ -0,0 +1,115 @@
+package module
+
+import (
+ "testing"
+
+ "github.com/pkg/errors"
+
+)
+
+
+func TestCreateCluster(t *testing.T) {
+
+ mData := ClusterMeta{
+ ClusterReference: "test_cluster",
+ }
+
+ cl := Cluster {
+ MetaData: mData,
+ }
+ data1 := [][]byte{}
+
+
+ key := ClusterKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ ClusterReference: "test_cluster",
+ }
+ myMocks := new(mockValues)
+ // just to get an error value
+ err1 := errors.New("math: square root of negative number")
+
+ myMocks.On("CheckProject", "test_project").Return(nil)
+ myMocks.On("CheckLogicalCloud", "test_project", "test_asdf").Return(nil)
+ myMocks.On("DBInsert", "test_dcm", key, nil, "test_meta", cl).Return(nil)
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, err1)
+
+ clClient := ClusterClient{"test_dcm", "test_meta", myMocks}
+ _, err := clClient.CreateCluster("test_project", "test_asdf", cl)
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
+
+func TestGetCluster(t *testing.T) {
+ key := ClusterKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ ClusterReference: "test_cluster",
+ }
+
+ data1 := [][]byte{
+ []byte("abc"),
+ }
+
+ data2 := []byte("abc")
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, nil)
+ myMocks.On("DBUnmarshal", data2).Return(nil)
+ clClient := ClusterClient{"test_dcm", "test_meta", myMocks}
+ _, err := clClient.GetCluster("test_project", "test_asdf", "test_cluster")
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
+
+func TestDeleteCluster(t *testing.T) {
+
+ key := ClusterKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ ClusterReference: "test_cluster",
+ }
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBRemove", "test_dcm", key).Return(nil)
+
+ clClient := ClusterClient{"test_dcm", "test_meta", myMocks}
+ err := clClient.DeleteCluster("test_project", "test_asdf", "test_cluster")
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+
+}
+
+func TestUpdateCluster(t *testing.T) {
+ key := ClusterKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ ClusterReference: "test_cluster",
+ }
+ mData := ClusterMeta{
+ ClusterReference: "test_cluster",
+ }
+ cl := Cluster{
+ MetaData: mData,
+ }
+ data1 := [][]byte{
+ []byte("abc"),
+ }
+ data2 := []byte("abc")
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBInsert", "test_dcm", key, nil, "test_meta", cl).Return(nil)
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, nil)
+ myMocks.On("DBUnmarshal", data2).Return(nil)
+ clClient := ClusterClient{"test_dcm", "test_meta", myMocks}
+ _, err := clClient.UpdateCluster("test_project", "test_asdf", "test_cluster", cl)
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
diff --git a/src/dcm/pkg/module/keyvalue.go b/src/dcm/pkg/module/keyvalue.go
new file mode 100644
index 00000000..4e3e0fab
--- /dev/null
+++ b/src/dcm/pkg/module/keyvalue.go
@@ -0,0 +1,205 @@
+/*
+* 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 (
+ pkgerrors "github.com/pkg/errors"
+)
+
+// KeyValue contains the parameters needed for a key value
+type KeyValue struct {
+ MetaData KVMetaDataList `json:"metadata"`
+ Specification KVSpec `json:"spec"`
+}
+
+
+// MetaData contains the parameters needed for metadata
+type KVMetaDataList struct {
+ KeyValueName string `json:"name"`
+ Description string `json:"description"`
+ UserData1 string `json:"userData1"`
+ UserData2 string `json:"userData2"`
+}
+
+// Spec contains the parameters needed for spec
+type KVSpec struct {
+ Kv []map[string]interface{} `json:"kv"`
+}
+
+// KeyValueKey is the key structure that is used in the database
+type KeyValueKey struct {
+ Project string `json:"project"`
+ LogicalCloudName string `json:"logical-cloud-name"`
+ KeyValueName string `json:"kvname"`
+}
+
+// KeyValueManager is an interface that exposes the connection
+// functionality
+type KeyValueManager interface {
+ CreateKVPair(project, logicalCloud string, c KeyValue) (KeyValue, error)
+ GetKVPair(project, logicalCloud, name string) (KeyValue, error)
+ GetAllKVPairs(project, logicalCloud string) ([]KeyValue, error)
+ DeleteKVPair(project, logicalCloud, name string) error
+ UpdateKVPair(project, logicalCloud, name string, c KeyValue) (KeyValue, error)
+}
+
+// KeyValueClient implements the KeyValueManager
+// It will also be used to maintain some localized state
+type KeyValueClient struct {
+ storeName string
+ tagMeta string
+ util Utility
+}
+
+// KeyValueClient returns an instance of the KeyValueClient
+// which implements the KeyValueManager
+func NewKeyValueClient() *KeyValueClient {
+ service := DBService{}
+ return &KeyValueClient{
+ storeName: "orchestrator",
+ tagMeta: "keyvalue",
+ util: service,
+ }
+}
+
+// Create entry for the key value resource in the database
+func (v *KeyValueClient) CreateKVPair(project, logicalCloud string, c KeyValue) (KeyValue, error) {
+
+ //Construct key consisting of name
+ key := KeyValueKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ KeyValueName: c.MetaData.KeyValueName,
+ }
+
+ //Check if project exist
+ err := v.util.CheckProject(project)
+ if err != nil {
+ return KeyValue{}, pkgerrors.New("Unable to find the project")
+ }
+ //check if logical cloud exists
+ err = v.util.CheckLogicalCloud(project, logicalCloud)
+ if err != nil {
+ return KeyValue{}, pkgerrors.New("Unable to find the logical cloud")
+ }
+ //Check if this Key Value already exists
+ _, err = v.GetKVPair(project, logicalCloud, c.MetaData.KeyValueName)
+ if err == nil {
+ return KeyValue{}, pkgerrors.New("Key Value already exists")
+ }
+
+ err = v.util.DBInsert(v.storeName, key, nil, v.tagMeta, c)
+ if err != nil {
+ return KeyValue{}, pkgerrors.Wrap(err, "Creating DB Entry")
+ }
+
+ return c, nil
+}
+
+// Get returns Key Value for correspondin name
+func (v *KeyValueClient) GetKVPair(project, logicalCloud, kvPairName string) (KeyValue, error) {
+
+ //Construct the composite key to select the entry
+ key := KeyValueKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ KeyValueName: kvPairName,
+ }
+ value, err := v.util.DBFind(v.storeName, key, v.tagMeta)
+ if err != nil {
+ return KeyValue{}, pkgerrors.Wrap(err, "Get Key Value")
+ }
+
+ //value is a byte array
+ if value != nil {
+ kv := KeyValue{}
+ err = v.util.DBUnmarshal(value[0], &kv)
+ if err != nil {
+ return KeyValue{}, pkgerrors.Wrap(err, "Unmarshaling value")
+ }
+ return kv, nil
+ }
+
+ return KeyValue{}, pkgerrors.New("Error getting Key Value")
+}
+
+// Get All lists all key value pairs
+func (v *KeyValueClient) GetAllKVPairs(project, logicalCloud string) ([]KeyValue, error) {
+
+ //Construct the composite key to select the entry
+ key := KeyValueKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ KeyValueName: "",
+ }
+ var resp []KeyValue
+ values, err := v.util.DBFind(v.storeName, key, v.tagMeta)
+ if err != nil {
+ return []KeyValue{}, pkgerrors.Wrap(err, "Get Key Value")
+ }
+
+ for _, value := range values {
+ kv := KeyValue{}
+ err = v.util.DBUnmarshal(value, &kv)
+ if err != nil {
+ return []KeyValue{}, pkgerrors.Wrap(err, "Unmarshaling value")
+ }
+ resp = append(resp, kv)
+ }
+
+ return resp, nil
+}
+
+// Delete the Key Value entry from database
+func (v *KeyValueClient) DeleteKVPair(project, logicalCloud, kvPairName string) error {
+
+ //Construct the composite key to select the entry
+ key := KeyValueKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ KeyValueName: kvPairName,
+ }
+ err := v.util.DBRemove(v.storeName, key)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Delete Key Value")
+ }
+ return nil
+}
+
+// Update an entry for the Key Value in the database
+func (v *KeyValueClient) UpdateKVPair(project, logicalCloud, kvPairName string, c KeyValue) (KeyValue, error) {
+
+ key := KeyValueKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ KeyValueName: kvPairName,
+ }
+ //Check if KV pair URl name is the same name in json
+ if c.MetaData.KeyValueName != kvPairName {
+ return KeyValue{}, pkgerrors.New("Update Error - KV pair name mismatch")
+ }
+ //Check if this Key Value exists
+ _, err := v.GetKVPair(project, logicalCloud, kvPairName)
+ if err != nil {
+ return KeyValue{}, pkgerrors.New("Update Error - Key Value Pair doesn't exist")
+ }
+ err = v.util.DBInsert(v.storeName, key, nil, v.tagMeta, c)
+ if err != nil {
+ return KeyValue{}, pkgerrors.Wrap(err, "Updating DB Entry")
+ }
+ return c, nil
+}
diff --git a/src/dcm/pkg/module/keyvalue_test.go b/src/dcm/pkg/module/keyvalue_test.go
new file mode 100644
index 00000000..9faceda4
--- /dev/null
+++ b/src/dcm/pkg/module/keyvalue_test.go
@@ -0,0 +1,115 @@
+package module
+
+import (
+ "testing"
+
+ "github.com/pkg/errors"
+
+)
+
+
+func TestCreateKVPair(t *testing.T) {
+
+ mData := KVMetaDataList{
+ KeyValueName: "test_kv_pair",
+ }
+
+ kv := KeyValue {
+ MetaData: mData,
+ }
+ data1 := [][]byte{}
+
+
+ key := KeyValueKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ KeyValueName: "test_kv_pair",
+ }
+ myMocks := new(mockValues)
+ // just to get an error value
+ err1 := errors.New("math: square root of negative number")
+
+ myMocks.On("CheckProject", "test_project").Return(nil)
+ myMocks.On("CheckLogicalCloud", "test_project", "test_asdf").Return(nil)
+ myMocks.On("DBInsert", "test_dcm", key, nil, "test_meta", kv).Return(nil)
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, err1)
+
+ kvClient := KeyValueClient{"test_dcm", "test_meta", myMocks}
+ _, err := kvClient.CreateKVPair("test_project", "test_asdf", kv)
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
+
+func TestGetKVPair(t *testing.T) {
+ key := KeyValueKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ KeyValueName: "test_kv_pair",
+ }
+
+ data1 := [][]byte{
+ []byte("abc"),
+ }
+
+ data2 := []byte("abc")
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, nil)
+ myMocks.On("DBUnmarshal", data2).Return(nil)
+ kvClient := KeyValueClient{"test_dcm", "test_meta", myMocks}
+ _, err := kvClient.GetKVPair("test_project", "test_asdf", "test_kv_pair")
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
+
+func TestDeleteKVPair(t *testing.T) {
+
+ key := KeyValueKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ KeyValueName: "test_kv_pair",
+ }
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBRemove", "test_dcm", key).Return(nil)
+
+ kvClient := KeyValueClient{"test_dcm", "test_meta", myMocks}
+ err := kvClient.DeleteKVPair("test_project", "test_asdf", "test_kv_pair")
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+
+}
+
+func TestUpdateKVPair(t *testing.T) {
+ key := KeyValueKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ KeyValueName: "test_kv_pair",
+ }
+ mData := KVMetaDataList{
+ KeyValueName: "test_kv_pair",
+ }
+ kv := KeyValue{
+ MetaData: mData,
+ }
+ data1 := [][]byte{
+ []byte("abc"),
+ }
+ data2 := []byte("abc")
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBInsert", "test_dcm", key, nil, "test_meta", kv).Return(nil)
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, nil)
+ myMocks.On("DBUnmarshal", data2).Return(nil)
+ kvClient := KeyValueClient{"test_dcm", "test_meta", myMocks}
+ _, err := kvClient.UpdateKVPair("test_project", "test_asdf", "test_kv_pair", kv)
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
diff --git a/src/dcm/pkg/module/logicalcloud.go b/src/dcm/pkg/module/logicalcloud.go
new file mode 100644
index 00000000..9fb1b6fb
--- /dev/null
+++ b/src/dcm/pkg/module/logicalcloud.go
@@ -0,0 +1,291 @@
+/*
+* 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"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
+
+ pkgerrors "github.com/pkg/errors"
+)
+
+// LogicalCloud contains the parameters needed for a Logical Cloud
+type LogicalCloud struct {
+ MetaData MetaDataList `json:"metadata"`
+ Specification Spec `json:"spec"`
+}
+
+
+// MetaData contains the parameters needed for metadata
+type MetaDataList struct {
+ LogicalCloudName string `json:"name"`
+ Description string `json:"description"`
+ UserData1 string `json:"userData1"`
+ UserData2 string `json:"userData2"`
+}
+
+// Spec contains the parameters needed for spec
+type Spec struct {
+ NameSpace string `json:"namespace"`
+ User UserData `json:"user"`
+
+}
+
+// UserData contains the parameters needed for user
+type UserData struct {
+ UserName string `json:"user-name"`
+ Type string `json:"type"`
+ UserPermissions []UserPerm `json:"user-permissions"`
+}
+
+// UserPerm contains the parameters needed for user permissions
+type UserPerm struct {
+ PermName string `json:"permission-name"`
+ APIGroups []string `json:"apiGroups"`
+ Resources []string `json:"resources"`
+ Verbs []string `json:"verbs"`
+}
+
+// LogicalCloudKey is the key structure that is used in the database
+type LogicalCloudKey struct {
+ Project string `json:"project"`
+ LogicalCloudName string `json:"logical-cloud-name"`
+}
+
+// LogicalCloudManager is an interface that exposes the connection
+// functionality
+type LogicalCloudManager interface {
+ Create(project string, c LogicalCloud) (LogicalCloud, error)
+ Get(project, name string) (LogicalCloud, error)
+ GetAll(project string) ([]LogicalCloud, error)
+ Delete(project, name string) error
+ Update(project, name string, c LogicalCloud) (LogicalCloud, error)
+
+}
+
+// Interface facilitates unit testing by mocking functions
+type Utility interface {
+ DBInsert(storeName string, key db.Key, query interface{}, meta string, c interface{}) error
+ DBFind(storeName string, key db.Key, meta string) ([][]byte, error)
+ DBUnmarshal(value []byte, out interface{}) error
+ DBRemove(storeName string, key db.Key) error
+ CheckProject(project string) error
+ CheckLogicalCloud(project, logicalCloud string) error
+}
+
+// LogicalCloudClient implements the LogicalCloudManager
+// It will also be used to maintain some localized state
+type LogicalCloudClient struct {
+ storeName string
+ tagMeta string
+ util Utility
+}
+
+// Added for unit testing; implements Utility interface
+type DBService struct {}
+
+// LogicalCloudClient returns an instance of the LogicalCloudClient
+// which implements the LogicalCloudManager
+func NewLogicalCloudClient() *LogicalCloudClient {
+ service := DBService{}
+ return &LogicalCloudClient{
+ storeName: "orchestrator",
+ tagMeta: "logicalcloud",
+ util: service,
+ }
+}
+
+// Create entry for the logical cloud resource in the database
+func (v *LogicalCloudClient) Create(project string, c LogicalCloud) (LogicalCloud, error) {
+
+ //Construct key consisting of name
+ key := LogicalCloudKey{
+ Project: project,
+ LogicalCloudName: c.MetaData.LogicalCloudName,
+ }
+
+ //Check if project exists
+ err := v.util.CheckProject(project)
+ if err != nil {
+ return LogicalCloud{}, pkgerrors.New("Unable to find the project")
+ }
+
+ //Check if this Logical Cloud already exists
+ _, err = v.Get(project, c.MetaData.LogicalCloudName)
+ if err == nil {
+ return LogicalCloud{}, pkgerrors.New("Logical Cloud already exists")
+ }
+
+ err = v.util.DBInsert(v.storeName, key, nil, v.tagMeta, c)
+ if err != nil {
+ return LogicalCloud{}, pkgerrors.Wrap(err, "Creating DB Entry")
+ }
+
+ return c, nil
+}
+
+// Get returns Logical Cloud corresponding to logical cloud name
+func (v *LogicalCloudClient) Get(project, logicalCloudName string) (LogicalCloud, error) {
+
+ //Construct the composite key to select the entry
+ key := LogicalCloudKey{
+ Project: project,
+ LogicalCloudName: logicalCloudName,
+ }
+ value, err := v.util.DBFind(v.storeName, key, v.tagMeta)
+ if err != nil {
+ return LogicalCloud{}, pkgerrors.Wrap(err, "Get Logical Cloud")
+ }
+
+ //value is a byte array
+ if value != nil {
+ lc := LogicalCloud{}
+ err = v.util.DBUnmarshal(value[0], &lc)
+ if err != nil {
+ return LogicalCloud{}, pkgerrors.Wrap(err, "Unmarshaling value")
+ }
+ return lc, nil
+ }
+
+ return LogicalCloud{}, pkgerrors.New("Error getting Logical Cloud")
+}
+
+// GetAll returns Logical Clouds in the project
+func (v *LogicalCloudClient) GetAll(project string) ([]LogicalCloud, error) {
+
+ //Construct the composite key to select the entry
+ key := LogicalCloudKey{
+ Project: project,
+ LogicalCloudName: "",
+ }
+
+ var resp []LogicalCloud
+ values, err := v.util.DBFind(v.storeName, key, v.tagMeta)
+ if err != nil {
+ return []LogicalCloud{}, pkgerrors.Wrap(err, "Get Logical Clouds")
+ }
+
+ for _, value := range values {
+ lc := LogicalCloud{}
+ err = v.util.DBUnmarshal(value, &lc)
+ if err != nil {
+ return []LogicalCloud{}, pkgerrors.Wrap(err, "Unmarshaling values")
+ }
+ resp = append(resp, lc)
+ }
+
+ return resp, nil
+}
+
+// Delete the Logical Cloud entry from database
+func (v *LogicalCloudClient) Delete(project, logicalCloudName string) error {
+
+ //Construct the composite key to select the entry
+ key := LogicalCloudKey{
+ Project: project,
+ LogicalCloudName: logicalCloudName,
+ }
+ err := v.util.DBRemove(v.storeName, key)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Delete Logical Cloud")
+ }
+
+ return nil
+}
+
+// Update an entry for the Logical Cloud in the database
+func (v *LogicalCloudClient) Update(project, logicalCloudName string, c LogicalCloud) (LogicalCloud, error) {
+
+ key := LogicalCloudKey{
+ Project: project,
+ LogicalCloudName: logicalCloudName,
+ }
+ // Check for mismatch, logicalCloudName and payload logical cloud name
+ if c.MetaData.LogicalCloudName != logicalCloudName {
+ return LogicalCloud{}, pkgerrors.New("Update Error - Logical Cloud name mismatch")
+ }
+ //Check if this Logical Cloud exists
+ _, err := v.Get(project, logicalCloudName)
+ if err != nil {
+ return LogicalCloud{}, pkgerrors.New("Update Error - Logical Cloud doesn't exist")
+ }
+ err = v.util.DBInsert(v.storeName, key, nil, v.tagMeta, c)
+ if err != nil {
+ return LogicalCloud{}, pkgerrors.Wrap(err, "Updating DB Entry")
+ }
+ return c, nil
+}
+
+func (d DBService) DBInsert(storeName string, key db.Key, query interface{}, meta string, c interface{}) error {
+
+ err := db.DBconn.Insert(storeName, key, nil, meta, c)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Creating DB Entry")
+ }
+
+ return nil
+}
+
+func (d DBService) DBFind(storeName string, key db.Key, meta string) ([][]byte, error) {
+
+ value, err := db.DBconn.Find(storeName, key, meta)
+ if err != nil {
+ return [][]byte{}, pkgerrors.Wrap(err, "Get Resource")
+ }
+
+ return value, nil
+}
+
+func (d DBService) DBUnmarshal(value []byte, out interface{}) error {
+
+ err := db.DBconn.Unmarshal(value, out)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Unmarshaling Value")
+ }
+
+ return nil
+}
+
+func (d DBService) DBRemove(storeName string, key db.Key) error {
+
+ err := db.DBconn.Remove(storeName, key)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Delete Resource")
+ }
+
+ return nil
+}
+
+func (d DBService) CheckProject(project string) error {
+ // Check if project exists
+ _, err := module.NewProjectClient().GetProject(project)
+ if err != nil {
+ return pkgerrors.New("Unable to find the project")
+ }
+
+ return nil
+}
+
+func (d DBService) CheckLogicalCloud(project, logicalCloud string) error {
+ // Check if logical cloud exists
+ _, err := NewLogicalCloudClient().Get(project, logicalCloud)
+ if err != nil {
+ return pkgerrors.New("Unable to find the logical cloud")
+ }
+
+ return nil
+}
diff --git a/src/dcm/pkg/module/logicalcloud_test.go b/src/dcm/pkg/module/logicalcloud_test.go
new file mode 100644
index 00000000..882cc292
--- /dev/null
+++ b/src/dcm/pkg/module/logicalcloud_test.go
@@ -0,0 +1,157 @@
+package module
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+ "github.com/stretchr/testify/mock"
+ "github.com/pkg/errors"
+
+)
+
+type mockValues struct {
+ mock.Mock
+}
+
+func (m *mockValues) DBInsert(name string, key db.Key, query interface {}, meta string, c interface {}) error{
+ fmt.Println("Mocked Insert operation in Mongo")
+ args := m.Called(name, key, nil, meta, c)
+
+ return args.Error(0)
+}
+
+func (m *mockValues) DBFind(name string, key db.Key, meta string) ([][]byte, error) {
+ fmt.Println("Mocked Mongo DB Find Operation")
+ args := m.Called(name, key, meta)
+
+ return args.Get(0).([][]byte), args.Error(1)
+}
+
+func (m *mockValues) DBUnmarshal(value []byte, out interface{}) error {
+ fmt.Println("Mocked Mongo DB Unmarshal Operation")
+ args := m.Called(value)
+
+ return args.Error(0)
+}
+
+func (m *mockValues) DBRemove(name string, key db.Key) error {
+ fmt.Println("Mocked Mongo DB Remove operation")
+ args := m.Called(name, key)
+
+ return args.Error(0)
+}
+
+func (m *mockValues) CheckProject(project string) error {
+ fmt.Println("Mocked Check Project exists")
+ args := m.Called(project)
+
+ return args.Error(0)
+}
+
+func (m *mockValues) CheckLogicalCloud(project, logicalCloud string) error {
+ fmt.Println("Mocked Check Logical Cloud exists")
+ args := m.Called(project, logicalCloud)
+
+ return args.Error(0)
+}
+
+func TestCreateLogicalCloud(t *testing.T) {
+
+ mData := MetaDataList{
+ LogicalCloudName: "test_asdf",
+ }
+
+ lc := LogicalCloud {
+ MetaData: mData,
+ }
+ data1 := [][]byte{}
+
+ key := LogicalCloudKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ }
+ myMocks := new(mockValues)
+ // just to get an error value
+ err1 := errors.New("math: square root of negative number")
+
+ myMocks.On("CheckProject", "test_project").Return(nil)
+ myMocks.On("DBInsert", "test_dcm", key, nil, "test_meta", lc).Return(nil)
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, err1)
+
+ lcClient := LogicalCloudClient{"test_dcm", "test_meta", myMocks}
+ _, err := lcClient.Create("test_project", lc)
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
+
+func TestGetLogicalCloud(t *testing.T) {
+ key := LogicalCloudKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ }
+
+ data1 := [][]byte{
+ []byte("abc"),
+ }
+
+ data2 := []byte("abc")
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, nil)
+ myMocks.On("DBUnmarshal", data2).Return(nil)
+ lcClient := LogicalCloudClient{"test_dcm", "test_meta", myMocks}
+ _, err := lcClient.Get("test_project", "test_asdf")
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
+
+func TestDeleteLogicalCloud(t *testing.T) {
+
+ key := LogicalCloudKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ }
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBRemove", "test_dcm", key).Return(nil)
+
+ lcClient := LogicalCloudClient{"test_dcm", "test_meta", myMocks}
+ err := lcClient.Delete("test_project", "test_asdf")
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+
+}
+
+func TestUpdateLogicalCloud(t *testing.T) {
+ key := LogicalCloudKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ }
+ mData := MetaDataList{
+ LogicalCloudName: "test_asdf",
+ }
+ lc := LogicalCloud{
+ MetaData: mData,
+ }
+ data1 := [][]byte{
+ []byte("abc"),
+ }
+ data2 := []byte("abc")
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBInsert", "test_dcm", key, nil, "test_meta", lc).Return(nil)
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, nil)
+ myMocks.On("DBUnmarshal", data2).Return(nil)
+ lcClient := LogicalCloudClient{"test_dcm", "test_meta", myMocks}
+ _, err := lcClient.Update("test_project", "test_asdf", lc)
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
diff --git a/src/dcm/pkg/module/module.go b/src/dcm/pkg/module/module.go
new file mode 100644
index 00000000..293f6dd5
--- /dev/null
+++ b/src/dcm/pkg/module/module.go
@@ -0,0 +1,39 @@
+/*
+ * 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
+
+// Client for using the services in the orchestrator
+type Client struct {
+ LogicalCloud *LogicalCloudClient
+ Cluster *ClusterClient
+ Quota *QuotaClient
+ UserPermission *UserPermissionClient
+ KeyValue *KeyValueClient
+ // Add Clients for API's here
+}
+
+// NewClient creates a new client for using the services
+func NewClient() *Client {
+ c := &Client{}
+ c.LogicalCloud = NewLogicalCloudClient()
+ c.Cluster = NewClusterClient()
+ c.Quota = NewQuotaClient()
+ c.UserPermission = NewUserPermissionClient()
+ c.KeyValue = NewKeyValueClient()
+ // Add Client API handlers here
+ return c
+}
diff --git a/src/dcm/pkg/module/quota.go b/src/dcm/pkg/module/quota.go
new file mode 100644
index 00000000..1a7012f6
--- /dev/null
+++ b/src/dcm/pkg/module/quota.go
@@ -0,0 +1,222 @@
+/*
+* 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 (
+ pkgerrors "github.com/pkg/errors"
+)
+
+// Quota contains the parameters needed for a Quota
+type Quota struct {
+ MetaData QMetaDataList `json:"metadata"`
+ Specification QSpec `json:"spec"`
+}
+
+
+// MetaData contains the parameters needed for metadata
+type QMetaDataList struct {
+ QuotaName string `json:"name"`
+ Description string `json:"description"`
+}
+
+// Spec contains the parameters needed for spec
+type QSpec struct {
+ LimitsCPU string `json:"limits.cpu"`
+ LimitsMemory string `json:"limits.memory"`
+ RequestsCPU string `json:"requests.cpu"`
+ RequestsMemory string `json:"requests.memory"`
+ RequestsStorage string `json:"requests.storage"`
+ LimitsEphemeralStorage string `json:"limits.ephemeral.storage"`
+ PersistentVolumeClaims string `json:"persistentvolumeclaims"`
+ Pods string `json:"pods"`
+ ConfigMaps string `json:"configmaps"`
+ ReplicationControllers string `json:"replicationcontrollers"`
+ ResourceQuotas string `json:"resourcequotas"`
+ Services string `json:"services"`
+ ServicesLoadBalancers string `json:"services.loadbalancers"`
+ ServicesNodePorts string `json:"services.nodeports"`
+ Secrets string `json:"secrets"`
+ CountReplicationControllers string `json:"count/replicationcontrollers"`
+ CountDeploymentsApps string `json:"count/deployments.apps"`
+ CountReplicasetsApps string `json:"count/replicasets.apps"`
+ CountStatefulSets string `json:"count/statefulsets.apps"`
+ CountJobsBatch string `json:"count/jobs.batch"`
+ CountCronJobsBatch string `json:"count/cronjobs.batch"`
+ CountDeploymentsExtensions string `json:"count/deployments.extensions"`
+}
+
+// QuotaKey is the key structure that is used in the database
+type QuotaKey struct {
+ Project string `json:"project"`
+ LogicalCloudName string `json:"logical-cloud-name"`
+ QuotaName string `json:"qname"`
+}
+
+// QuotaManager is an interface that exposes the connection
+// functionality
+type QuotaManager interface {
+ CreateQuota(project, logicalCloud string, c Quota) (Quota, error)
+ GetQuota(project, logicalCloud, name string) (Quota, error)
+ GetAllQuotas(project, logicalCloud string) ([]Quota, error)
+ DeleteQuota(project, logicalCloud, name string) error
+ UpdateQuota(project, logicalCloud, name string, c Quota) (Quota, error)
+}
+
+// QuotaClient implements the QuotaManager
+// It will also be used to maintain some localized state
+type QuotaClient struct {
+ storeName string
+ tagMeta string
+ util Utility
+}
+
+// QuotaClient returns an instance of the QuotaClient
+// which implements the QuotaManager
+func NewQuotaClient() *QuotaClient {
+ service := DBService{}
+ return &QuotaClient{
+ storeName: "orchestrator",
+ tagMeta: "quota",
+ util: service,
+ }
+}
+
+// Create entry for the quota resource in the database
+func (v *QuotaClient) CreateQuota(project, logicalCloud string, c Quota) (Quota, error) {
+
+ //Construct key consisting of name
+ key := QuotaKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ QuotaName: c.MetaData.QuotaName,
+ }
+
+ //Check if project exists
+ err := v.util.CheckProject(project)
+ if err != nil {
+ return Quota{}, pkgerrors.New("Unable to find the project")
+ }
+ //check if logical cloud exists
+ err = v.util.CheckLogicalCloud(project, logicalCloud)
+ if err != nil {
+ return Quota{}, pkgerrors.New("Unable to find the logical cloud")
+ }
+ //Check if this Quota already exists
+ _, err = v.GetQuota(project, logicalCloud, c.MetaData.QuotaName)
+ if err == nil {
+ return Quota{}, pkgerrors.New("Quota already exists")
+ }
+
+ err = v.util.DBInsert(v.storeName, key, nil, v.tagMeta, c)
+ if err != nil {
+ return Quota{}, pkgerrors.Wrap(err, "Creating DB Entry")
+ }
+
+ return c, nil
+}
+
+// Get returns Quota for corresponding quota name
+func (v *QuotaClient) GetQuota(project, logicalCloud, quotaName string) (Quota, error) {
+
+ //Construct the composite key to select the entry
+ key := QuotaKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ QuotaName: quotaName,
+ }
+ value, err := v.util.DBFind(v.storeName, key, v.tagMeta)
+ if err != nil {
+ return Quota{}, pkgerrors.Wrap(err, "Quota")
+ }
+
+ //value is a byte array
+ if value != nil {
+ q := Quota{}
+ err = v.util.DBUnmarshal(value[0], &q)
+ if err != nil {
+ return Quota{}, pkgerrors.Wrap(err, "Unmarshaling value")
+ }
+ return q, nil
+ }
+
+ return Quota{}, pkgerrors.New("Error getting Quota")
+}
+
+// GetAll returns all cluster quotas in the logical cloud
+func (v *QuotaClient) GetAllQuotas(project, logicalCloud string) ([]Quota, error) {
+ //Construct the composite key to select the entry
+ key := QuotaKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ QuotaName: "",
+ }
+ var resp []Quota
+ values, err := v.util.DBFind(v.storeName, key, v.tagMeta)
+ if err != nil {
+ return []Quota{}, pkgerrors.Wrap(err, "Get All Quotas")
+ }
+
+ for _, value := range values {
+ q := Quota{}
+ err = v.util.DBUnmarshal(value, &q)
+ if err != nil {
+ return []Quota{}, pkgerrors.Wrap(err, "Unmarshaling value")
+ }
+ resp = append(resp, q)
+ }
+
+ return resp, nil
+}
+
+// Delete the Quota entry from database
+func (v *QuotaClient) DeleteQuota(project, logicalCloud, quotaName string) error {
+ //Construct the composite key to select the entry
+ key := QuotaKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ QuotaName: quotaName,
+ }
+ err := v.util.DBRemove(v.storeName, key)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Delete Quota")
+ }
+ return nil
+}
+
+// Update an entry for the Quota in the database
+func (v *QuotaClient) UpdateQuota(project, logicalCloud, quotaName string, c Quota) (Quota, error) {
+
+ key := QuotaKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ QuotaName: quotaName,
+ }
+ //Check quota URL name against the quota json name
+ if c.MetaData.QuotaName != quotaName {
+ return Quota{}, pkgerrors.New("Update Error - Quota name mismatch")
+ }
+ //Check if this Quota exists
+ _, err := v.GetQuota(project, logicalCloud, quotaName)
+ if err != nil {
+ return Quota{}, pkgerrors.New("Update Error - Quota doesn't exist")
+ }
+ err = v.util.DBInsert(v.storeName, key, nil, v.tagMeta, c)
+ if err != nil {
+ return Quota{}, pkgerrors.Wrap(err, "Updating DB Entry")
+ }
+ return c, nil
+}
diff --git a/src/dcm/pkg/module/quota_test.go b/src/dcm/pkg/module/quota_test.go
new file mode 100644
index 00000000..87a60d71
--- /dev/null
+++ b/src/dcm/pkg/module/quota_test.go
@@ -0,0 +1,115 @@
+package module
+
+import (
+ "testing"
+
+ "github.com/pkg/errors"
+
+)
+
+
+func TestCreateQuota(t *testing.T) {
+
+ mData := QMetaDataList{
+ QuotaName: "test_quota",
+ }
+
+ q := Quota {
+ MetaData: mData,
+ }
+ data1 := [][]byte{}
+
+
+ key := QuotaKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ QuotaName: "test_quota",
+ }
+ myMocks := new(mockValues)
+ // just to get an error value
+ err1 := errors.New("math: square root of negative number")
+
+ myMocks.On("CheckProject", "test_project").Return(nil)
+ myMocks.On("CheckLogicalCloud", "test_project", "test_asdf").Return(nil)
+ myMocks.On("DBInsert", "test_dcm", key, nil, "test_meta", q).Return(nil)
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, err1)
+
+ qClient := QuotaClient{"test_dcm", "test_meta", myMocks}
+ _, err := qClient.CreateQuota("test_project", "test_asdf", q)
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
+
+func TestGetQuota(t *testing.T) {
+ key := QuotaKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ QuotaName: "test_quota",
+ }
+
+ data1 := [][]byte{
+ []byte("abc"),
+ }
+
+ data2 := []byte("abc")
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, nil)
+ myMocks.On("DBUnmarshal", data2).Return(nil)
+ qClient := QuotaClient{"test_dcm", "test_meta", myMocks}
+ _, err := qClient.GetQuota("test_project", "test_asdf", "test_quota")
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
+
+func TestDeleteQuota(t *testing.T) {
+
+ key := QuotaKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ QuotaName: "test_quota",
+ }
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBRemove", "test_dcm", key).Return(nil)
+
+ qClient := QuotaClient{"test_dcm", "test_meta", myMocks}
+ err := qClient.DeleteQuota("test_project", "test_asdf", "test_quota")
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+
+}
+
+func TestUpdateQuota(t *testing.T) {
+ key := QuotaKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ QuotaName: "test_quota",
+ }
+ mData := QMetaDataList{
+ QuotaName: "test_quota",
+ }
+ q := Quota{
+ MetaData: mData,
+ }
+ data1 := [][]byte{
+ []byte("abc"),
+ }
+ data2 := []byte("abc")
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBInsert", "test_dcm", key, nil, "test_meta", q).Return(nil)
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, nil)
+ myMocks.On("DBUnmarshal", data2).Return(nil)
+ qClient := QuotaClient{"test_dcm", "test_meta", myMocks}
+ _, err := qClient.UpdateQuota("test_project", "test_asdf", "test_quota", q)
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
diff --git a/src/dcm/pkg/module/userpermissions.go b/src/dcm/pkg/module/userpermissions.go
new file mode 100644
index 00000000..cf961a65
--- /dev/null
+++ b/src/dcm/pkg/module/userpermissions.go
@@ -0,0 +1,193 @@
+/*
+* 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 (
+ pkgerrors "github.com/pkg/errors"
+)
+
+// UserPermission contains the parameters needed for a user permission
+type UserPermission struct {
+ UserPermissionName string `json:"name"`
+ APIGroups []string `json:"apiGroups"`
+ Resources []string `json:"resources"`
+ Verbs []string `json:"verbs"`
+}
+
+// UserPermissionKey is the key structure that is used in the database
+type UserPermissionKey struct {
+ Project string `json:"project"`
+ LogicalCloudName string `json:"logical-cloud-name"`
+ UserPermissionName string `json:"upname"`
+}
+
+// UserPermissionManager is an interface that exposes the connection
+// functionality
+type UserPermissionManager interface {
+ CreateUserPerm(project, logicalCloud string, c UserPermission) (UserPermission, error)
+ GetUserPerm(project, logicalCloud, name string) (UserPermission, error)
+ GetAllUserPerms(project, logicalCloud string) ([]UserPermission, error)
+ DeleteUserPerm(project, logicalCloud, name string) error
+ UpdateUserPerm(project, logicalCloud, name string, c UserPermission) (UserPermission, error)
+}
+
+// UserPermissionClient implements the UserPermissionManager
+// It will also be used to maintain some localized state
+type UserPermissionClient struct {
+ storeName string
+ tagMeta string
+ util Utility
+}
+
+// UserPermissionClient returns an instance of the UserPermissionClient
+// which implements the UserPermissionManager
+func NewUserPermissionClient() *UserPermissionClient {
+ service := DBService{}
+ return &UserPermissionClient{
+ storeName: "orchestrator",
+ tagMeta: "userpermission",
+ util: service,
+ }
+}
+
+// Create entry for the User Permission resource in the database
+func (v *UserPermissionClient) CreateUserPerm(project, logicalCloud string, c UserPermission) (UserPermission, error) {
+
+ //Construct key consisting of name
+ key := UserPermissionKey {
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ UserPermissionName: c.UserPermissionName,
+ }
+
+ //Check if project exists
+ err := v.util.CheckProject(project)
+ if err != nil {
+ return UserPermission{}, pkgerrors.New("Unable to find the project")
+ }
+ //check if logical cloud exists
+ err = v.util.CheckLogicalCloud(project, logicalCloud)
+ if err != nil {
+ return UserPermission{}, pkgerrors.New("Unable to find the logical cloud")
+ }
+
+ //Check if this User Permission already exists
+ _, err = v.GetUserPerm(project, logicalCloud, c.UserPermissionName)
+ if err == nil {
+ return UserPermission{}, pkgerrors.New("User Permission already exists")
+ }
+
+ err = v.util.DBInsert(v.storeName, key, nil, v.tagMeta, c)
+ if err != nil {
+ return UserPermission{}, pkgerrors.Wrap(err, "Creating DB Entry")
+ }
+
+ return c, nil
+}
+
+// Get returns User Permission for corresponding name
+func (v *UserPermissionClient) GetUserPerm(project, logicalCloud, userPermName string) (UserPermission, error) {
+
+ //Construct the composite key to select the entry
+ key := UserPermissionKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ UserPermissionName: userPermName,
+ }
+
+ value, err := v.util.DBFind(v.storeName, key, v.tagMeta)
+ if err != nil {
+ return UserPermission{}, pkgerrors.Wrap(err, "Get User Permission")
+ }
+
+ //value is a byte array
+ if value != nil {
+ up := UserPermission{}
+ err = v.util.DBUnmarshal(value[0], &up)
+ if err != nil {
+ return UserPermission{}, pkgerrors.Wrap(err, "Unmarshaling value")
+ }
+ return up, nil
+ }
+
+ return UserPermission{}, pkgerrors.New("Error getting User Permission")
+}
+
+// GetAll lists all user permissions
+func (v *UserPermissionClient) GetAllUserPerms(project, logicalCloud string) ([]UserPermission, error) {
+ //Construct the composite key to select the entry
+ key := UserPermissionKey {
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ UserPermissionName: "",
+ }
+ var resp []UserPermission
+ values, err := v.util.DBFind(v.storeName, key, v.tagMeta)
+ if err != nil {
+ return []UserPermission{}, pkgerrors.Wrap(err, "Get All User Permissions")
+ }
+
+ for _, value := range values {
+ up := UserPermission{}
+ err = v.util.DBUnmarshal(value, &up)
+ if err != nil {
+ return []UserPermission{}, pkgerrors.Wrap(err, "Unmarshaling value")
+ }
+ resp = append(resp, up)
+ }
+ return resp, nil
+}
+// Delete the User Permission entry from database
+func (v *UserPermissionClient) DeleteUserPerm(project, logicalCloud, userPermName string) error {
+ //Construct the composite key to select the entry
+ key := UserPermissionKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ UserPermissionName: userPermName,
+ }
+ err := v.util.DBRemove(v.storeName, key)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Delete User Permission")
+ }
+ return nil
+}
+
+// Update an entry for the User Permission in the database
+func (v *UserPermissionClient) UpdateUserPerm(project, logicalCloud, userPermName string, c UserPermission) (
+ UserPermission, error) {
+
+ key := UserPermissionKey{
+ Project: project,
+ LogicalCloudName: logicalCloud,
+ UserPermissionName: userPermName,
+ }
+ //Check for URL name and json permission name mismatch
+ if c.UserPermissionName != userPermName {
+ return UserPermission{}, pkgerrors.New("Update Error - Permission name mismatch")
+ }
+ //Check if this User Permission exists
+ _, err := v.GetUserPerm(project, logicalCloud, userPermName)
+ if err != nil {
+ return UserPermission{}, pkgerrors.New(
+ "Update Error - User Permission doesn't exist")
+ }
+ err = v.util.DBInsert(v.storeName, key, nil, v.tagMeta, c)
+ if err != nil {
+ return UserPermission{}, pkgerrors.Wrap(err, "Updating DB Entry")
+ }
+ return c, nil
+}
diff --git a/src/dcm/pkg/module/userpermissions_test.go b/src/dcm/pkg/module/userpermissions_test.go
new file mode 100644
index 00000000..f134aa0f
--- /dev/null
+++ b/src/dcm/pkg/module/userpermissions_test.go
@@ -0,0 +1,110 @@
+package module
+
+import (
+ "testing"
+
+ "github.com/pkg/errors"
+
+)
+
+
+func TestCreateUserPerm(t *testing.T) {
+
+ up := UserPermission {
+ UserPermissionName: "test_user_perm",
+ }
+ data1 := [][]byte{}
+
+ // data2 := []byte("abc")
+
+ key := UserPermissionKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ UserPermissionName: "test_user_perm",
+ }
+ myMocks := new(mockValues)
+ // just to get an error value
+ err1 := errors.New("math: square root of negative number")
+
+ myMocks.On("CheckProject", "test_project").Return(nil)
+ myMocks.On("CheckLogicalCloud", "test_project", "test_asdf").Return(nil)
+ myMocks.On("DBInsert", "test_dcm", key, nil, "test_meta", up).Return(nil)
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, err1)
+ // myMocks.On("DBUnmarshal", data2).Return(nil)
+
+ upClient := UserPermissionClient{"test_dcm", "test_meta", myMocks}
+ _, err := upClient.CreateUserPerm("test_project", "test_asdf", up)
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
+
+func TestGetUserPerm(t *testing.T) {
+ key := UserPermissionKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ UserPermissionName: "test_user_perm",
+ }
+
+ data1 := [][]byte{
+ []byte("abc"),
+ }
+
+ data2 := []byte("abc")
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, nil)
+ myMocks.On("DBUnmarshal", data2).Return(nil)
+ upClient := UserPermissionClient{"test_dcm", "test_meta", myMocks}
+ _, err := upClient.GetUserPerm("test_project", "test_asdf", "test_user_perm")
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}
+
+func TestDeleteUserPerm(t *testing.T) {
+
+ key := UserPermissionKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ UserPermissionName: "test_user_perm",
+ }
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBRemove", "test_dcm", key).Return(nil)
+
+ upClient := UserPermissionClient{"test_dcm", "test_meta", myMocks}
+ err := upClient.DeleteUserPerm("test_project", "test_asdf", "test_user_perm")
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+
+}
+
+func TestUpdateUserPerm(t *testing.T) {
+ key := UserPermissionKey{
+ Project: "test_project",
+ LogicalCloudName: "test_asdf",
+ UserPermissionName: "test_user_perm",
+ }
+ up := UserPermission{
+ UserPermissionName: "test_user_perm",
+ }
+ data1 := [][]byte{
+ []byte("abc"),
+ }
+ data2 := []byte("abc")
+
+ myMocks := new(mockValues)
+
+ myMocks.On("DBInsert", "test_dcm", key, nil, "test_meta", up).Return(nil)
+ myMocks.On("DBFind", "test_dcm", key, "test_meta").Return(data1, nil)
+ myMocks.On("DBUnmarshal", data2).Return(nil)
+ upClient := UserPermissionClient{"test_dcm", "test_meta", myMocks}
+ _, err := upClient.UpdateUserPerm("test_project", "test_asdf", "test_user_perm", up)
+ if err != nil {
+ t.Errorf("Some error occured!")
+ }
+}