summaryrefslogtreecommitdiffstats
path: root/src/dcm/pkg/module
diff options
context:
space:
mode:
authorenyinna1234 <enyinna.ochulor@intel.com>2020-02-14 08:41:49 -0800
committerenyinna1234 <enyinna.ochulor@intel.com>2020-04-10 08:15:33 -0700
commit10b17da590fc43622c6080815f65fbbb2721b640 (patch)
treeb9a8f456f97fd8ac3883bacf7835a2baaceed9a2 /src/dcm/pkg/module
parent335c7cca38eb804c2977e4dd9af9efa0ea7ef82b (diff)
Add Distributed Cloud Manager
This handles RESTful API CRUD operations for logical clouds, CLuster, User Permissions, Quota, and Key Value pairs. See: https://wiki.onap.org/x/tAiVB Issue-ID: MULTICLOUD-996 Signed-off-by: Enyinna Ochulor <enyinna.ochulor@intel.com> Change-Id: I654a304cd682f762c02cfd92b4483d1edea63fca
Diffstat (limited to 'src/dcm/pkg/module')
-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
11 files changed, 1767 insertions, 0 deletions
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!")
+ }
+}