summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManjunath Ranganathaiah <manjunath.ranganathaiah@intel.com>2020-03-20 15:39:06 +0000
committerManjunath Ranganathaiah <manjunath.ranganathaiah@intel.com>2020-03-25 16:15:07 +0000
commit54ab79c77f0286b95074d2c714292c0b18fb18fb (patch)
treeffe82247230147b014ef44603b8da9cd17b3216d
parent8c6fb0cbc3cea30f10af0db5a69bc6a601197961 (diff)
App context library interface for etcd
Issue-ID: MULTICLOUD-1005 Signed-off-by: Manjunath Ranganathaiah <manjunath.ranganathaiah@intel.com> Change-Id: Id4d3357fe851f6653112d24ac5d48b6dbaa6e888 Signed-off-by: Manjunath Ranganathaiah <manjunath.ranganathaiah@intel.com>
-rw-r--r--src/orchestrator/pkg/appcontext/appcontext.go290
-rw-r--r--src/orchestrator/pkg/appcontext/appcontext_test.go283
2 files changed, 573 insertions, 0 deletions
diff --git a/src/orchestrator/pkg/appcontext/appcontext.go b/src/orchestrator/pkg/appcontext/appcontext.go
new file mode 100644
index 00000000..357402b3
--- /dev/null
+++ b/src/orchestrator/pkg/appcontext/appcontext.go
@@ -0,0 +1,290 @@
+/*
+ * 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 appcontext
+
+import (
+ "fmt"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/rtcontext"
+ pkgerrors "github.com/pkg/errors"
+)
+
+type AppContext struct {
+ initDone bool
+ rtcObj rtcontext.RunTimeContext
+ rtc rtcontext.Rtcontext
+}
+
+// Init app context
+func (ac *AppContext) InitAppContext() {
+ if !ac.initDone {
+ ac.rtcObj = rtcontext.RunTimeContext{}
+ ac.initDone = true
+ }
+ ac.rtc = &ac.rtcObj
+}
+
+// Create a new context and returns the handle
+func (ac *AppContext) CreateCompositeApp() (interface{}, error) {
+ h, err := ac.rtc.RtcCreate()
+ if err != nil {
+ return nil, err
+ }
+ return h, nil
+}
+
+// Deletes the entire context
+func (ac *AppContext) DeleteCompositeApp() (error) {
+ h, err := ac.rtc.RtcGet()
+ if err != nil {
+ return err
+ }
+ err = ac.rtc.RtcDeletePrefix(h)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+//Returns the handles for a given composite app context
+func (ac *AppContext) GetCompositeApp() (interface{}, error) {
+ h, err := ac.rtc.RtcGet()
+ if err != nil {
+ return nil, err
+ }
+ return h, nil
+}
+
+//Add app to the context under composite app
+func (ac *AppContext) AddApp(handle interface{}, appname string) (interface{}, error) {
+ h, err := ac.rtc.RtcAddLevel(handle, "app", appname)
+ if err != nil {
+ return nil, err
+ }
+ return h, nil
+}
+
+//Delete app from the context and everything underneth
+func (ac *AppContext) DeleteApp(handle interface{}) (error) {
+ err := ac.rtc.RtcDeletePrefix(handle)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+//Returns the hanlde for a given app
+func (ac *AppContext) GetAppHandle(appname string) (interface{}, error) {
+ if appname == "" {
+ return nil, pkgerrors.Errorf("Not a valid run time context app name")
+ }
+
+ rh, err := ac.rtc.RtcGet()
+ if err != nil {
+ return nil, err
+ }
+
+ apph := fmt.Sprintf("%v", rh) + "app/" + appname + "/"
+ hs, err := ac.rtc.RtcGetHandles(apph)
+ if err != nil {
+ return nil, err
+ }
+ for _, v := range hs {
+ if v == apph {
+ return v, nil
+ }
+ }
+ return nil, pkgerrors.Errorf("No handle was found for the given app")
+}
+
+//Add cluster to the context under app
+func (ac *AppContext) AddCluster(handle interface{}, clustername string) (interface{}, error) {
+ h, err := ac.rtc.RtcAddLevel(handle, "cluster", clustername)
+ if err != nil {
+ return nil, err
+ }
+ return h, nil
+}
+
+//Delete cluster from the context and everything underneth
+func (ac *AppContext) DeleteCluster(handle interface{}) (error) {
+ err := ac.rtc.RtcDeletePrefix(handle)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+//Returns the handle for a given app and cluster
+func (ac *AppContext) GetClusterHandle(appname string, clustername string) (interface{}, error) {
+ if appname == "" {
+ return nil, pkgerrors.Errorf("Not a valid run time context app name")
+ }
+ if clustername == "" {
+ return nil, pkgerrors.Errorf("Not a valid run time context cluster name")
+ }
+
+ rh, err := ac.rtc.RtcGet()
+ if err != nil {
+ return nil, err
+ }
+
+ ach := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/" + clustername + "/"
+ hs, err := ac.rtc.RtcGetHandles(ach)
+ if err != nil {
+ return nil, err
+ }
+ for _, v := range hs {
+ if v == ach {
+ return v, nil
+ }
+ }
+ return nil, pkgerrors.Errorf("No handle was found for the given cluster")
+}
+
+//Add resource under app and cluster
+func (ac *AppContext) AddResource(handle interface{},resname string, value interface{}) (interface{}, error) {
+ h, err := ac.rtc.RtcAddResource(handle, resname, value)
+ if err != nil {
+ return nil, err
+ }
+ return h, nil
+}
+
+//Delete resource given the handle
+func (ac *AppContext) DeleteResource(handle interface{}) (error) {
+ err := ac.rtc.RtcDeletePair(handle)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+//Return the hanlde for given app, cluster and resource name
+func (ac *AppContext) GetResourceHandle(appname string, clustername string, resname string) (interface{}, error) {
+ if appname == "" {
+ return nil, pkgerrors.Errorf("Not a valid run time context app name")
+ }
+ if clustername == "" {
+ return nil, pkgerrors.Errorf("Not a valid run time context cluster name")
+ }
+
+ rh, err := ac.rtc.RtcGet()
+ if err != nil {
+ return nil, err
+ }
+
+ acrh := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/" + clustername + "/resource/" + resname + "/"
+ hs, err := ac.rtc.RtcGetHandles(acrh)
+ if err != nil {
+ return nil, err
+ }
+ for _, v := range hs {
+ if v == acrh {
+ return v, nil
+ }
+ }
+ return nil, pkgerrors.Errorf("No handle was found for the given resource")
+}
+
+//Update the resource value usign the given handle
+func (ac *AppContext) UpdateResourceValue(handle interface{}, value interface{}) (error) {
+ return ac.rtc.RtcUpdateValue(handle, value)
+}
+
+//Add instruction under given handle and type
+func (ac *AppContext) AddInstruction(handle interface{}, level string, insttype string, value interface{}) (interface{}, error) {
+ if !(insttype == "order" || insttype == "dependency") {
+ return nil, pkgerrors.Errorf("Not a valid app context instruction type")
+ }
+ if !(level == "app" || level == "resource") {
+ return nil, pkgerrors.Errorf("Not a valid app context instruction level")
+ }
+ h, err := ac.rtc.RtcAddInstruction(handle, level, insttype, value)
+ if err != nil {
+ return nil, err
+ }
+ return h,nil
+}
+
+//Delete instruction under gievn handle
+func (ac *AppContext) DeleteInstruction(handle interface{}) (error) {
+ err := ac.rtc.RtcDeletePair(handle)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+//Returns the app instruction for a given instruction type
+func (ac *AppContext) GetAppInstruction(insttype string) (interface{}, error) {
+ if !(insttype == "order" || insttype == "dependency") {
+ return nil, pkgerrors.Errorf("Not a valid app context instruction type")
+ }
+ rh, err := ac.rtc.RtcGet()
+ if err != nil {
+ return nil, err
+ }
+ s := fmt.Sprintf("%v", rh) + "app/" + "instruction/" + insttype + "/"
+ var v string
+ err = ac.rtc.RtcGetValue(s, &v)
+ if err != nil {
+ return nil, err
+ }
+ return v,nil
+}
+
+//Update the instruction usign the given handle
+func (ac *AppContext) UpdateInstructionValue(handle interface{}, value interface{}) (error) {
+ return ac.rtc.RtcUpdateValue(handle, value)
+}
+
+//Returns the resource instruction for a given instruction type
+func (ac *AppContext) GetResourceInstruction(appname string, clustername string, insttype string) (interface{}, error) {
+ if !(insttype == "order" || insttype == "dependency") {
+ return nil, pkgerrors.Errorf("Not a valid app context instruction type")
+ }
+ rh, err := ac.rtc.RtcGet()
+ if err != nil {
+ return nil, err
+ }
+ s := fmt.Sprintf("%v", rh) + "app/" + appname + "/cluster/" + clustername + "/resource/instruction/" + insttype
+ var v string
+ err = ac.rtc.RtcGetValue(s, &v)
+ if err != nil {
+ return nil, err
+ }
+ return v,nil
+}
+
+//Return all the handles under the composite app
+func (ac *AppContext) GetAllHandles(handle interface{}) ([]interface{}, error) {
+ hs, err := ac.rtc.RtcGetHandles(handle)
+ if err != nil {
+ return nil, err
+ }
+ return hs,nil
+}
+
+//Returns the value for a given handle
+func (ac *AppContext) GetValue(handle interface{}) (interface{}, error) {
+ var v string
+ err := ac.rtc.RtcGetValue(handle, &v)
+ if err != nil {
+ return nil, err
+ }
+ return v,nil
+}
diff --git a/src/orchestrator/pkg/appcontext/appcontext_test.go b/src/orchestrator/pkg/appcontext/appcontext_test.go
new file mode 100644
index 00000000..a6f3e94e
--- /dev/null
+++ b/src/orchestrator/pkg/appcontext/appcontext_test.go
@@ -0,0 +1,283 @@
+/*
+ * 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 appcontext
+
+import (
+ "fmt"
+ "testing"
+ "strings"
+ pkgerrors "github.com/pkg/errors"
+)
+
+// Mock run time context
+type MockRunTimeContext struct {
+ Items map[string]interface{}
+ Err error
+}
+
+func (c *MockRunTimeContext) RtcCreate() (interface{}, error) {
+ var key string = "/context/9345674458787728/"
+
+ if c.Items == nil {
+ c.Items = make(map[string]interface{})
+ }
+ c.Items[key] = "9345674458787728"
+ return interface{}(key), c.Err
+
+}
+
+func (c *MockRunTimeContext) RtcGet() (interface{}, error) {
+ var key string = "/context/9345674458787728/"
+ return key, c.Err
+}
+
+func (c *MockRunTimeContext) RtcAddLevel(handle interface{}, level string, value string) (interface{}, error) {
+ str := fmt.Sprintf("%v", handle) + level + "/" + value + "/"
+ c.Items[str] = value
+ return nil, c.Err
+
+}
+
+func (c *MockRunTimeContext) RtcAddResource(handle interface{}, resname string, value interface{}) (interface{}, error) {
+ str := fmt.Sprintf("%v", handle) + "resource" + "/" + resname + "/"
+ c.Items[str] = value
+ return nil, c.Err
+
+}
+
+func (c *MockRunTimeContext) RtcAddInstruction(handle interface{}, level string, insttype string, value interface{}) (interface{}, error) {
+ str := fmt.Sprintf("%v", handle) + level + "/" + insttype + "/"
+ c.Items[str] = value
+ return nil, c.Err
+}
+
+func (c *MockRunTimeContext) RtcDeletePair(handle interface{}) (error) {
+ str := fmt.Sprintf("%v", handle)
+ delete(c.Items, str)
+ return c.Err
+}
+
+func (c *MockRunTimeContext) RtcDeletePrefix(handle interface{}) (error) {
+ for k, _ := range c.Items {
+ delete(c.Items, k)
+ }
+ return c.Err
+}
+
+func (c *MockRunTimeContext) RtcGetHandles(handle interface{}) ([]interface{}, error) {
+ var keys []interface{}
+
+ for k, _ := range c.Items {
+ keys = append(keys, string(k))
+ }
+ return keys, c.Err
+}
+
+func (c *MockRunTimeContext) RtcGetValue(handle interface{}, value interface{}) (error) {
+ key := fmt.Sprintf("%v", handle)
+ var s *string
+ s = value.(*string)
+ for kvKey, kvValue := range c.Items {
+ if kvKey == key {
+ *s = kvValue.(string)
+ return c.Err
+ }
+ }
+ return c.Err
+}
+
+func (c *MockRunTimeContext) RtcUpdateValue(handle interface{}, value interface{}) (error) {
+ key := fmt.Sprintf("%v", handle)
+ c.Items[key] = value
+ return c.Err
+}
+
+func TestCreateCompositeApp(t *testing.T) {
+ var ac = AppContext{}
+ testCases := []struct {
+ label string
+ mockRtcontext *MockRunTimeContext
+ expectedError string
+ }{
+ {
+ label: "Success case",
+ mockRtcontext: &MockRunTimeContext{},
+ },
+ {
+ label: "Create returns error case",
+ mockRtcontext: &MockRunTimeContext{Err: pkgerrors.Errorf("Error creating run time context:")},
+ expectedError: "Error creating run time context:",
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ ac.rtc = testCase.mockRtcontext
+ _, err := ac.CreateCompositeApp()
+ if err != nil {
+ if !strings.Contains(string(err.Error()), testCase.expectedError) {
+ t.Fatalf("Method returned an error (%s)", err)
+ }
+ }
+
+ })
+ }
+}
+
+func TestGetCompositeApp(t *testing.T) {
+ var ac = AppContext{}
+ testCases := []struct {
+ label string
+ mockRtcontext *MockRunTimeContext
+ expectedError string
+ }{
+ {
+ label: "Success case",
+ mockRtcontext: &MockRunTimeContext{},
+ },
+ {
+ label: "Get returns error case",
+ mockRtcontext: &MockRunTimeContext{Err: pkgerrors.Errorf("Error getting run time context:")},
+ expectedError: "Error getting run time context:",
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ ac.rtc = testCase.mockRtcontext
+ _, err := ac.GetCompositeApp()
+ if err != nil {
+ if !strings.Contains(string(err.Error()), testCase.expectedError) {
+ t.Fatalf("Method returned an error (%s)", err)
+ }
+ }
+
+ })
+ }
+}
+
+func TestDeleteCompositeApp(t *testing.T) {
+ var ac = AppContext{}
+ testCases := []struct {
+ label string
+ mockRtcontext *MockRunTimeContext
+ expectedError string
+ }{
+ {
+ label: "Success case",
+ mockRtcontext: &MockRunTimeContext{},
+ },
+ {
+ label: "Delete returns error case",
+ mockRtcontext: &MockRunTimeContext{Err: pkgerrors.Errorf("Error deleting run time context:")},
+ expectedError: "Error deleting run time context:",
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ ac.rtc = testCase.mockRtcontext
+ err := ac.DeleteCompositeApp()
+ if err != nil {
+ if !strings.Contains(string(err.Error()), testCase.expectedError) {
+ t.Fatalf("Method returned an error (%s)", err)
+ }
+ }
+
+ })
+ }
+}
+
+func TestAddApp(t *testing.T) {
+ var ac = AppContext{}
+ testCases := []struct {
+ label string
+ mockRtcontext *MockRunTimeContext
+ key interface{}
+ expectedError string
+ }{
+ {
+ label: "Success case",
+ mockRtcontext: &MockRunTimeContext{},
+ key: "/context/9345674458787728/",
+ },
+ {
+ label: "Delete returns error case",
+ mockRtcontext: &MockRunTimeContext{Err: pkgerrors.Errorf("Error adding app to run time context:")},
+ key: "/context/9345674458787728/",
+ expectedError: "Error adding app to run time context:",
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ ac.rtc = testCase.mockRtcontext
+ _, err := ac.CreateCompositeApp()
+ _, err = ac.AddApp(testCase.key, "testapp1")
+ if err != nil {
+ if !strings.Contains(string(err.Error()), testCase.expectedError) {
+ t.Fatalf("Method returned an error (%s)", err)
+ }
+ }
+
+ })
+ }
+}
+
+func TestGetAppHandle(t *testing.T) {
+ var ac = AppContext{}
+ testCases := []struct {
+ label string
+ mockRtcontext *MockRunTimeContext
+ key interface{}
+ appname string
+ expectedError string
+ }{
+ {
+ label: "Success case",
+ mockRtcontext: &MockRunTimeContext{},
+ key: "/context/9345674458787728/",
+ appname: "testapp1",
+ },
+ {
+ label: "Invalid app name case",
+ mockRtcontext: &MockRunTimeContext{},
+ key: "/context/9345674458787728/",
+ appname: "",
+ },
+ {
+ label: "Delete returns error case",
+ mockRtcontext: &MockRunTimeContext{Err: pkgerrors.Errorf("Error getting app handle from run time context:")},
+ key: "/context/9345674458787728/",
+ appname: "testapp1",
+ expectedError: "Error getting app handle from run time context:",
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ ac.rtc = testCase.mockRtcontext
+ _, err := ac.GetAppHandle(testCase.appname)
+ if err != nil {
+ if !strings.Contains(string(err.Error()), testCase.expectedError) {
+ t.Fatalf("Method returned an error (%s)", err)
+ }
+ }
+
+ })
+ }
+}