Adding meta data for app in appContext 05/107505/12
authorRajamohan Raj <rajamohan.raj@intel.com>
Mon, 11 May 2020 22:09:18 +0000 (22:09 +0000)
committerRajamohan Raj <rajamohan.raj@intel.com>
Fri, 15 May 2020 23:01:17 +0000 (23:01 +0000)
In this patch, modified the appContext and rtc lib
by adding functions for setting and getting the meta
data associated with the apps.

Issue-ID: MULTICLOUD-1064
Signed-off-by: Rajamohan Raj <rajamohan.raj@intel.com>
Change-Id: I08f91ddda3044f172caf7b2673c069fed16c32c4

src/ncm/go.mod
src/orchestrator/go.mod
src/orchestrator/pkg/appcontext/appcontext.go
src/orchestrator/pkg/appcontext/appcontext_test.go
src/orchestrator/pkg/module/instantiation.go
src/orchestrator/pkg/rtcontext/rtcontext.go
src/orchestrator/pkg/rtcontext/rtcontext_test.go

index 19f83bd..da62530 100644 (file)
@@ -8,11 +8,9 @@ require (
        github.com/gorilla/mux v1.6.2
        github.com/json-iterator/go v1.1.9 // indirect
        github.com/k8snetworkplumbingwg/network-attachment-definition-client v0.0.0-20200127152046-0ee521d56061
+       github.com/onap/multicloud-k8s/src/orchestrator v0.0.0-20200515060444-c77850a75eee
+       github.com/opencontainers/go-digest v1.0.0 // indirect
        github.com/pkg/errors v0.8.1
-       github.com/sirupsen/logrus v1.4.2
-       go.etcd.io/etcd v3.3.12+incompatible
-       go.mongodb.org/mongo-driver v1.0.0
-       golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3
        google.golang.org/grpc v1.27.1
        gopkg.in/yaml.v2 v2.2.8
        k8s.io/api v0.0.0-20190831074750-7364b6bdad65
@@ -32,6 +30,7 @@ replace (
        k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20190409023024-d644b00f3b79
        k8s.io/client-go => k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible
        k8s.io/cloud-provider => k8s.io/cloud-provider v0.0.0-20190409023720-1bc0c81fa51d
+
 )
 
 go 1.13
index 4779662..2961472 100644 (file)
@@ -8,20 +8,19 @@ require (
        github.com/golang/snappy v0.0.1 // indirect
        github.com/gorilla/handlers v1.3.0
        github.com/gorilla/mux v1.6.2
-       github.com/json-iterator/go v1.1.8 // indirect
        github.com/onap/multicloud-k8s/src/k8splugin v0.0.0-20191115005109-f168ebb73d8d // indirect
+       github.com/onap/multicloud-k8s/src/ncm v0.0.0-20200515060444-c77850a75eee
        github.com/pkg/errors v0.8.1
        github.com/sirupsen/logrus v1.4.2
        go.etcd.io/etcd v3.3.12+incompatible
        go.mongodb.org/mongo-driver v1.0.0
        golang.org/x/net v0.0.0-20200301022130-244492dfa37a
-       golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
        golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect
        google.golang.org/genproto v0.0.0-20200305110556-506484158171 // indirect
        google.golang.org/grpc v1.27.1
+       gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86
        k8s.io/apimachinery v0.0.0-20190831074630-461753078381
        k8s.io/helm v2.14.3+incompatible
-       k8s.io/klog v1.0.0 // indirect
 )
 
 replace (
index 8f7841a..00e0241 100644 (file)
@@ -22,7 +22,7 @@ import (
 
        "github.com/onap/multicloud-k8s/src/orchestrator/pkg/rtcontext"
        pkgerrors "github.com/pkg/errors"
-       //"log"
+
        log "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/logutils"
 )
 
@@ -32,6 +32,16 @@ type AppContext struct {
        rtc      rtcontext.Rtcontext
 }
 
+// CompositeAppMeta consists of projectName, CompositeAppName,
+// CompositeAppVersion, ReleaseName. This shall be used for
+// instantiation of a compositeApp
+type CompositeAppMeta struct {
+       Project      string `json:"Project"`
+       CompositeApp string `json:"CompositeApp"`
+       Version      string `json:"Version"`
+       Release      string `json:"Release"`
+}
+
 // Init app context
 func (ac *AppContext) InitAppContext() (interface{}, error) {
        ac.rtcObj = rtcontext.RunTimeContext{}
@@ -46,15 +56,25 @@ func (ac *AppContext) LoadAppContext(cid interface{}) (interface{}, error) {
        return ac.rtc.RtcLoad(cid)
 }
 
-// Create a new context and returns the handle
+// CreateCompositeApp method returns composite app handle as interface.
 func (ac *AppContext) CreateCompositeApp() (interface{}, error) {
        h, err := ac.rtc.RtcCreate()
        if err != nil {
                return nil, err
        }
+       log.Info(":: CreateCompositeApp ::", log.Fields{"CompositeAppHandle": h})
        return h, nil
 }
 
+// AddCompositeAppMeta adds the meta data associated with a composite app
+func (ac *AppContext) AddCompositeAppMeta(meta interface{}) error {
+       err := ac.rtc.RtcAddMeta(meta)
+       if err != nil {
+               return err
+       }
+       return nil
+}
+
 // Deletes the entire context
 func (ac *AppContext) DeleteCompositeApp() error {
        h, err := ac.rtc.RtcGet()
@@ -69,7 +89,7 @@ func (ac *AppContext) DeleteCompositeApp() error {
 }
 
 //Returns the handles for a given composite app context
-func (ac *AppContext) GetCompositeApp() (interface{}, error) {
+func (ac *AppContext) GetCompositeAppHandle() (interface{}, error) {
        h, err := ac.rtc.RtcGet()
        if err != nil {
                return nil, err
@@ -83,7 +103,7 @@ func (ac *AppContext) AddApp(handle interface{}, appname string) (interface{}, e
        if err != nil {
                return nil, err
        }
-       log.Info(":: Added app handle ::", log.Fields{"AppHandle":h})
+       log.Info(":: Added app handle ::", log.Fields{"AppHandle": h})
        return h, nil
 }
 
@@ -126,7 +146,7 @@ func (ac *AppContext) AddCluster(handle interface{}, clustername string) (interf
        if err != nil {
                return nil, err
        }
-       log.Info(":: Added cluster handle ::", log.Fields{"ClusterHandler":h})
+       log.Info(":: Added cluster handle ::", log.Fields{"ClusterHandler": h})
        return h, nil
 }
 
@@ -202,7 +222,7 @@ func (ac *AppContext) AddResource(handle interface{}, resname string, value []by
        if err != nil {
                return nil, err
        }
-       log.Info(":: Added resource handle ::", log.Fields{"ResourceHandler":h})
+       log.Info(":: Added resource handle ::", log.Fields{"ResourceHandler": h})
 
        return h, nil
 }
@@ -260,7 +280,7 @@ func (ac *AppContext) AddInstruction(handle interface{}, level string, insttype
        if err != nil {
                return nil, err
        }
-       log.Info(":: Added instruction handle ::", log.Fields{"InstructionHandler":h})
+       log.Info(":: Added instruction handle ::", log.Fields{"InstructionHandler": h})
        return h, nil
 }
 
@@ -332,3 +352,24 @@ func (ac *AppContext) GetValue(handle interface{}) (interface{}, error) {
        }
        return v, nil
 }
+
+// GetCompositeAppMeta returns the meta data associated with the compositeApp
+// Its return type is CompositeAppMeta
+func (ac *AppContext) GetCompositeAppMeta() (CompositeAppMeta, error) {
+       mi, err := ac.rtcObj.RtcGetMeta()
+
+       if err != nil {
+               return CompositeAppMeta{}, pkgerrors.Errorf("Failed to get compositeApp meta")
+       }
+       datamap, ok := mi.(map[string]interface{})
+       if ok == false {
+               return CompositeAppMeta{}, pkgerrors.Errorf("Failed to cast meta interface to compositeApp meta")
+       }
+
+       p := fmt.Sprintf("%v", datamap["Project"])
+       ca := fmt.Sprintf("%v", datamap["CompositeApp"])
+       v := fmt.Sprintf("%v", datamap["Version"])
+       rn := fmt.Sprintf("%v", datamap["Release"])
+
+       return CompositeAppMeta{Project: p, CompositeApp: ca, Version: v, Release: rn}, nil
+}
index e539ed7..07a13d0 100644 (file)
@@ -29,6 +29,13 @@ type MockRunTimeContext struct {
        Err   error
 }
 
+type MockCompositeAppMeta struct {
+       Project      string
+       CompositeApp string
+       Version      string
+       Release      string
+}
+
 func (c *MockRunTimeContext) RtcCreate() (interface{}, error) {
        var key string = "/context/9345674458787728/"
 
@@ -40,6 +47,16 @@ func (c *MockRunTimeContext) RtcCreate() (interface{}, error) {
 
 }
 
+func (c *MockRunTimeContext) RtcAddMeta(meta interface{}) error {
+       var cid string = "/context/9345674458787728/"
+       key := cid + "meta" + "/"
+       if c.Items == nil {
+               c.Items = make(map[string]interface{})
+       }
+       c.Items[key] = meta
+       return nil
+}
+
 func (c *MockRunTimeContext) RtcInit() (interface{}, error) {
        var id string = "9345674458787728"
        return id, c.Err
@@ -55,6 +72,11 @@ func (c *MockRunTimeContext) RtcGet() (interface{}, error) {
        return key, c.Err
 }
 
+func (c *MockRunTimeContext) RtcGetMeta() (interface{}, error) {
+       meta := CompositeAppMeta{Project: "pn", CompositeApp: "ca", Version: "v", Release: "rName"}
+       return meta, nil
+}
+
 func (c *MockRunTimeContext) RtcAddLevel(handle interface{}, level string, value string) (interface{}, error) {
        str := fmt.Sprintf("%v", handle) + level + "/" + value + "/"
        c.Items[str] = value
@@ -122,15 +144,18 @@ func TestCreateCompositeApp(t *testing.T) {
                label         string
                mockRtcontext *MockRunTimeContext
                expectedError string
+               meta          interface{}
        }{
                {
                        label:         "Success case",
                        mockRtcontext: &MockRunTimeContext{},
+                       meta:          interface{}(MockCompositeAppMeta{Project: "Testproject", CompositeApp: "TestCompApp", Version: "CompAppVersion", Release: "TestRelease"}),
                },
                {
                        label:         "Create returns error case",
                        mockRtcontext: &MockRunTimeContext{Err: pkgerrors.Errorf("Error creating run time context:")},
                        expectedError: "Error creating run time context:",
+                       meta:          interface{}(MockCompositeAppMeta{Project: "Testproject", CompositeApp: "TestCompApp", Version: "CompAppVersion", Release: "TestRelease"}),
                },
        }
 
@@ -169,7 +194,7 @@ func TestGetCompositeApp(t *testing.T) {
        for _, testCase := range testCases {
                t.Run(testCase.label, func(t *testing.T) {
                        ac.rtc = testCase.mockRtcontext
-                       _, err := ac.GetCompositeApp()
+                       _, err := ac.GetCompositeAppHandle()
                        if err != nil {
                                if !strings.Contains(string(err.Error()), testCase.expectedError) {
                                        t.Fatalf("Method returned an error (%s)", err)
@@ -219,17 +244,20 @@ func TestAddApp(t *testing.T) {
                mockRtcontext *MockRunTimeContext
                key           interface{}
                expectedError string
+               meta          interface{}
        }{
                {
                        label:         "Success case",
                        mockRtcontext: &MockRunTimeContext{},
                        key:           "/context/9345674458787728/",
+                       meta:          interface{}(MockCompositeAppMeta{Project: "Testproject", CompositeApp: "TestCompApp", Version: "CompAppVersion", Release: "TestRelease"}),
                },
                {
                        label:         "Error case for adding app",
                        mockRtcontext: &MockRunTimeContext{Err: pkgerrors.Errorf("Error adding app to run time context:")},
                        key:           "/context/9345674458787728/",
                        expectedError: "Error adding app to run time context:",
+                       meta:          interface{}(MockCompositeAppMeta{Project: "Testproject", CompositeApp: "TestCompApp", Version: "CompAppVersion", Release: "TestRelease"}),
                },
        }
 
index 58706ef..32e84c3 100644 (file)
@@ -111,7 +111,7 @@ func findGenericPlacementIntent(p, ca, v, di string) (string, error) {
        }
        for _, eachMap := range iList.ListOfIntents {
                if gi, found := eachMap[GenericPlacementIntentName]; found {
-                       log.Info(":: Name of the generic-placement-intent ::", log.Fields{"GenPlmtIntent":gi})
+                       log.Info(":: Name of the generic-placement-intent ::", log.Fields{"GenPlmtIntent": gi})
                        return gi, err
                }
        }
@@ -126,8 +126,7 @@ func findGenericPlacementIntent(p, ca, v, di string) (string, error) {
 //It takes in arguments - appName, project, compositeAppName, releaseName, compositeProfileName, array of override values
 func GetSortedTemplateForApp(appName, p, ca, v, rName, cp string, overrideValues []OverrideValues) ([]helm.KubernetesResourceTemplate, error) {
 
-
-       log.Info(":: Processing App ::", log.Fields{"appName":appName})
+       log.Info(":: Processing App ::", log.Fields{"appName": appName})
 
        var sortedTemplates []helm.KubernetesResourceTemplate
 
@@ -140,7 +139,7 @@ func GetSortedTemplateForApp(appName, p, ca, v, rName, cp string, overrideValues
                return sortedTemplates, pkgerrors.Wrap(err, "Fail to convert to byte array")
        }
 
-       log.Info(":: Got the app content.. ::", log.Fields{"appName":appName})
+       log.Info(":: Got the app content.. ::", log.Fields{"appName": appName})
 
        appPC, err := NewAppProfileClient().GetAppProfileContentByApp(p, ca, v, cp, appName)
        if err != nil {
@@ -151,7 +150,7 @@ func GetSortedTemplateForApp(appName, p, ca, v, rName, cp string, overrideValues
                return sortedTemplates, pkgerrors.Wrap(err, "Fail to convert to byte array")
        }
 
-       log.Info(":: Got the app Profile content .. ::", log.Fields{"appName":appName})
+       log.Info(":: Got the app Profile content .. ::", log.Fields{"appName": appName})
 
        overrideValuesOfApp := getOverrideValuesByAppName(overrideValues, appName)
        //Convert override values from map to array of strings of the following format
@@ -168,7 +167,7 @@ func GetSortedTemplateForApp(appName, p, ca, v, rName, cp string, overrideValues
                appProfileContent, overrideValuesOfAppStr,
                appName)
 
-       log.Info(":: Total no. of sorted templates ::", log.Fields{"len(sortedTemplates):":len(sortedTemplates)})
+       log.Info(":: Total no. of sorted templates ::", log.Fields{"len(sortedTemplates):": len(sortedTemplates)})
 
        return sortedTemplates, err
 }
@@ -193,20 +192,20 @@ func getResources(st []helm.KubernetesResourceTemplate) ([]resource, error) {
 
                resources = append(resources, resource{name: n, filecontent: yamlFile})
 
-               log.Info(":: Added resource into resource-order ::", log.Fields{"ResourceName":n})
+               log.Info(":: Added resource into resource-order ::", log.Fields{"ResourceName": n})
        }
        return resources, nil
 }
 
 func addResourcesToCluster(ct appcontext.AppContext, ch interface{}, resources []resource, resourceOrder []string) error {
-       for _, resource := range resources {
 
+       for _, resource := range resources {
                resourceOrder = append(resourceOrder, resource.name)
                _, err := ct.AddResource(ch, resource.name, resource.filecontent)
                if err != nil {
                        cleanuperr := ct.DeleteCompositeApp()
                        if cleanuperr != nil {
-                               log.Info(":: Error Cleaning up AppContext after add resource failure ::", log.Fields{"Resource":resource.name, "Error":cleanuperr.Error})
+                               log.Info(":: Error Cleaning up AppContext after add resource failure ::", log.Fields{"Resource": resource.name, "Error": cleanuperr.Error})
                        }
                        return pkgerrors.Wrapf(err, "Error adding resource ::%s to AppContext", resource.name)
                }
@@ -214,7 +213,7 @@ func addResourcesToCluster(ct appcontext.AppContext, ch interface{}, resources [
                if err != nil {
                        cleanuperr := ct.DeleteCompositeApp()
                        if cleanuperr != nil {
-                               log.Info(":: Error Cleaning up AppContext after add instruction failure ::", log.Fields{"Resource":resource.name, "Error":cleanuperr.Error})
+                               log.Info(":: Error Cleaning up AppContext after add instruction failure ::", log.Fields{"Resource": resource.name, "Error": cleanuperr.Error})
                        }
                        return pkgerrors.Wrapf(err, "Error adding instruction for resource ::%s to AppContext", resource.name)
                }
@@ -231,7 +230,7 @@ func addClustersToAppContext(l gpic.Clusters, ct appcontext.AppContext, appHandl
                if err != nil {
                        cleanuperr := ct.DeleteCompositeApp()
                        if cleanuperr != nil {
-                               log.Info(":: Error Cleaning up AppContext after add cluster failure ::", log.Fields{"cluster-provider":p, "cluster-name":n, "Error":cleanuperr.Error})
+                               log.Info(":: Error Cleaning up AppContext after add cluster failure ::", log.Fields{"cluster-provider": p, "cluster-name": n, "Error": cleanuperr.Error})
                        }
                        return pkgerrors.Wrapf(err, "Error adding Cluster(provider::%s and name::%s) to AppContext", p, n)
                }
@@ -259,7 +258,7 @@ func verifyResources(l gpic.Clusters, ct appcontext.AppContext, resources []reso
                        if err != nil {
                                return pkgerrors.Wrapf(err, "Error getting resoure handle for resource :: %s, app:: %s, cluster :: %s", appName, res.name, cn)
                        }
-                       log.Info(":: GetResourceHandle ::", log.Fields{"ResourceHandler":rh, "appName":appName, "Cluster": cn, "Resource":res.name})
+                       log.Info(":: GetResourceHandle ::", log.Fields{"ResourceHandler": rh, "appName": appName, "Cluster": cn, "Resource": res.name})
 
                }
 
@@ -288,8 +287,8 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin
                return err
        }
 
-       log.Info(":: The name of the GenPlacIntent ::", log.Fields{"GenPlmtIntent":gIntent})
-       log.Info(":: DeploymentIntentGroup, ReleaseName, CompositeProfile ::", log.Fields{"dIGrp":dIGrp.MetaData.Name, "releaseName":rName, "cp":cp})
+       log.Info(":: The name of the GenPlacIntent ::", log.Fields{"GenPlmtIntent": gIntent})
+       log.Info(":: DeploymentIntentGroup, ReleaseName, CompositeProfile ::", log.Fields{"dIGrp": dIGrp.MetaData.Name, "releaseName": rName, "cp": cp})
 
        allApps, err := NewAppClient().GetApps(p, ca, v)
        if err != nil {
@@ -304,8 +303,16 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin
        }
        compositeHandle, err := context.CreateCompositeApp()
        if err != nil {
-               return pkgerrors.Wrap(err, "Error creating AppContext")
+               return pkgerrors.Wrap(err, "Error creating CompositeApp handle")
        }
+       err = context.AddCompositeAppMeta(appcontext.CompositeAppMeta{Project: p, CompositeApp: ca, Version: v, Release: rName})
+       if err != nil {
+               return pkgerrors.Wrap(err, "Error Adding CompositeAppMeta")
+       }
+
+       m, err := context.GetCompositeAppMeta()
+
+       log.Info(":: The meta data stored in the runtime context :: ", log.Fields{"Project": m.Project, "CompositeApp": m.CompositeApp, "Version": m.Version, "Release": m.Release})
 
        var appOrder []string
 
@@ -318,7 +325,7 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin
                        return pkgerrors.Wrap(err, "Unable to get the sorted templates for app")
                }
 
-               log.Info(":: Resolved all the templates ::", log.Fields{"appName":eachApp.Metadata.Name, "SortedTemplate":sortedTemplates})
+               log.Info(":: Resolved all the templates ::", log.Fields{"appName": eachApp.Metadata.Name, "SortedTemplate": sortedTemplates})
 
                resources, err := getResources(sortedTemplates)
                if err != nil {
@@ -334,7 +341,7 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin
                        return pkgerrors.Wrap(err, "Unable to get the intents resolved for app")
                }
 
-               log.Info(":: listOfClusters ::", log.Fields{"listOfClusters":listOfClusters})
+               log.Info(":: listOfClusters ::", log.Fields{"listOfClusters": listOfClusters})
 
                //BEGIN: storing into etcd
                // Add an app to the app context
@@ -342,17 +349,17 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin
                if err != nil {
                        cleanuperr := context.DeleteCompositeApp()
                        if cleanuperr != nil {
-                               log.Info(":: Error Cleaning up AppContext compositeApp failure ::", log.Fields{"Error":cleanuperr.Error(), "AppName":eachApp.Metadata.Name})
+                               log.Info(":: Error Cleaning up AppContext compositeApp failure ::", log.Fields{"Error": cleanuperr.Error(), "AppName": eachApp.Metadata.Name})
                        }
                        return pkgerrors.Wrap(err, "Error adding App to AppContext")
                }
                err = addClustersToAppContext(listOfClusters, context, apphandle, resources)
                if err != nil {
-                       log.Info(":: Error while adding cluster and resources to app ::", log.Fields{"Error":err.Error(), "AppName":eachApp.Metadata.Name})
+                       log.Info(":: Error while adding cluster and resources to app ::", log.Fields{"Error": err.Error(), "AppName": eachApp.Metadata.Name})
                }
                err = verifyResources(listOfClusters, context, resources, eachApp.Metadata.Name)
                if err != nil {
-                       log.Info(":: Error while verifying resources in app ::", log.Fields{"Error":err.Error(), "AppName":eachApp.Metadata.Name})
+                       log.Info(":: Error while verifying resources in app ::", log.Fields{"Error": err.Error(), "AppName": eachApp.Metadata.Name})
                }
 
        }
@@ -373,12 +380,12 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin
                cleanuperr := context.DeleteCompositeApp()
                if cleanuperr != nil {
 
-                       log.Info(":: Error Cleaning up AppContext while saving context in the db for GPIntent ::", log.Fields{"Error":cleanuperr.Error(), "GPIntent":gIntent, "DeploymentIntentGroup":di, "CompositeApp":ca, "CompositeAppVersion":v, "Project":p})
+                       log.Info(":: Error Cleaning up AppContext while saving context in the db for GPIntent ::", log.Fields{"Error": cleanuperr.Error(), "GPIntent": gIntent, "DeploymentIntentGroup": di, "CompositeApp": ca, "CompositeAppVersion": v, "Project": p})
                }
                return pkgerrors.Wrap(err, "Error adding AppContext to DB")
        }
        // END:: save the context in the orchestrator db record
 
-       log.Info(":: Done with instantiation... ::", log.Fields{"CompositeAppName":ca})
+       log.Info(":: Done with instantiation... ::", log.Fields{"CompositeAppName": ca})
        return err
 }
index 1835251..5610ea5 100644 (file)
@@ -29,13 +29,15 @@ const maxrand = 0x7fffffffffffffff
 const prefix string = "/context/"
 
 type RunTimeContext struct {
-       cid interface{}
+       cid  interface{}
+       meta interface{}
 }
 
 type Rtcontext interface {
        RtcInit() (interface{}, error)
        RtcLoad(interface{}) (interface{}, error)
        RtcCreate() (interface{}, error)
+       RtcAddMeta(meta interface{}) error
        RtcGet() (interface{}, error)
        RtcAddLevel(handle interface{}, level string, value string) (interface{}, error)
        RtcAddResource(handle interface{}, resname string, value interface{}) (interface{}, error)
@@ -45,6 +47,7 @@ type Rtcontext interface {
        RtcGetHandles(handle interface{}) ([]interface{}, error)
        RtcGetValue(handle interface{}, value interface{}) error
        RtcUpdateValue(handle interface{}, value interface{}) error
+       RtcGetMeta() (interface{}, error)
 }
 
 //Intialize context by assiging a new id
@@ -76,7 +79,6 @@ func (rtc *RunTimeContext) RtcLoad(id interface{}) (interface{}, error) {
        return handle, nil
 }
 
-//Create context using the id and prefix
 func (rtc *RunTimeContext) RtcCreate() (interface{}, error) {
        cid := fmt.Sprintf("%v", rtc.cid)
        if cid == "" {
@@ -94,6 +96,26 @@ func (rtc *RunTimeContext) RtcCreate() (interface{}, error) {
        return rtc.cid, nil
 }
 
+//RtcAddMeta is used for saving meta data of appContext into ETCD.
+func (rtc *RunTimeContext) RtcAddMeta(meta interface{}) error {
+       cid := fmt.Sprintf("%v", rtc.cid)
+       if cid == "" {
+               return pkgerrors.Errorf("Error, context not intialized")
+       }
+       if !strings.HasPrefix(cid, prefix) {
+               return pkgerrors.Errorf("Not a valid run time context prefix")
+       }
+
+       rtc.meta = meta
+       k := cid + "meta" + "/"
+       err := contextdb.Db.Put(k, rtc.meta)
+       if err != nil {
+               return pkgerrors.Errorf("Error saving metadata in run time context: %s", err.Error())
+       }
+
+       return nil
+}
+
 //Get the root handle
 func (rtc *RunTimeContext) RtcGet() (interface{}, error) {
        str := fmt.Sprintf("%v", rtc.cid)
@@ -113,6 +135,23 @@ func (rtc *RunTimeContext) RtcGet() (interface{}, error) {
        return rtc.cid, nil
 }
 
+// RtcGetMeta method fetches the meta data of the rtc object and returns it.
+func (rtc *RunTimeContext) RtcGetMeta() (interface{}, error) {
+       str := fmt.Sprintf("%v", rtc.cid)
+       if !strings.HasPrefix(str, prefix) {
+               return nil, pkgerrors.Errorf("Not a valid run time context")
+       }
+
+       var value interface{}
+       k := str + "meta" + "/"
+       err := contextdb.Db.Get(k, &value)
+       if err != nil {
+               return nil, pkgerrors.Errorf("Error getting run time context metadata: %s", err.Error())
+       }
+       return value, nil
+
+}
+
 //Add a new level at a given handle and return the new handle
 func (rtc *RunTimeContext) RtcAddLevel(handle interface{}, level string, value string) (interface{}, error) {
        str := fmt.Sprintf("%v", handle)
@@ -177,7 +216,6 @@ func (rtc *RunTimeContext) RtcAddInstruction(handle interface{}, level string, i
        if value == nil {
                return nil, pkgerrors.Errorf("Not a valid run time context instruction value")
        }
-
        k := str + level + "/" + "instruction" + "/" + insttype + "/"
        err := contextdb.Db.Put(k, fmt.Sprintf("%v", value))
        if err != nil {
@@ -194,7 +232,6 @@ func (rtc *RunTimeContext) RtcDeletePair(handle interface{}) error {
        if !strings.HasPrefix(str, sid) {
                return pkgerrors.Errorf("Not a valid run time context handle")
        }
-
        err := contextdb.Db.Delete(str)
        if err != nil {
                return pkgerrors.Errorf("Error deleting run time context pair: %s", err.Error())
index eedbeb8..49e8374 100644 (file)
@@ -112,7 +112,7 @@ func TestRtcInit(t *testing.T) {
 }
 
 func TestRtcLoad(t *testing.T) {
-       var rtc = RunTimeContext{""}
+       var rtc = RunTimeContext{"", ""}
        testCases := []struct {
                label         string
                mockContextDb *MockContextDb
@@ -147,7 +147,7 @@ func TestRtcLoad(t *testing.T) {
 }
 
 func TestRtcCreate(t *testing.T) {
-       var rtc = RunTimeContext{"/context/5345674458787728/"}
+       var rtc = RunTimeContext{"/context/5345674458787728/", ""}
        testCases := []struct {
                label         string
                mockContextDb *MockContextDb
@@ -179,7 +179,7 @@ func TestRtcCreate(t *testing.T) {
 }
 
 func TestRtcGet(t *testing.T) {
-       var rtc = RunTimeContext{"/context/5345674458787728/"}
+       var rtc = RunTimeContext{"/context/5345674458787728/", ""}
        testCases := []struct {
                label         string
                mockContextDb *MockContextDb
@@ -240,7 +240,7 @@ func TestRtcGet(t *testing.T) {
 }
 
 func TestRtcAddLevel(t *testing.T) {
-       var rtc = RunTimeContext{"/context/3528435435454354/"}
+       var rtc = RunTimeContext{"/context/3528435435454354/", ""}
        testCases := []struct {
                label         string
                mockContextDb *MockContextDb
@@ -304,7 +304,7 @@ func TestRtcAddLevel(t *testing.T) {
 }
 
 func TestRtcAddResource(t *testing.T) {
-       var rtc = RunTimeContext{"/context/3528435435454354/"}
+       var rtc = RunTimeContext{"/context/3528435435454354/", ""}
        testCases := []struct {
                label         string
                mockContextDb *MockContextDb
@@ -368,7 +368,7 @@ func TestRtcAddResource(t *testing.T) {
 }
 
 func TestRtcAddInstruction(t *testing.T) {
-       var rtc = RunTimeContext{"/context/3528435435454354/"}
+       var rtc = RunTimeContext{"/context/3528435435454354/", ""}
        testCases := []struct {
                label         string
                mockContextDb *MockContextDb
@@ -447,7 +447,7 @@ func TestRtcAddInstruction(t *testing.T) {
 }
 
 func TestRtcGetHandles(t *testing.T) {
-       var rtc = RunTimeContext{"/context/5345674458787728/"}
+       var rtc = RunTimeContext{"/context/5345674458787728/", ""}
        testCases := []struct {
                label         string
                mockContextDb *MockContextDb
@@ -490,7 +490,7 @@ func TestRtcGetHandles(t *testing.T) {
 }
 
 func TestRtcGetValue(t *testing.T) {
-       var rtc = RunTimeContext{"/context/5345674458787728/"}
+       var rtc = RunTimeContext{"/context/5345674458787728/", ""}
        testCases := []struct {
                label         string
                mockContextDb *MockContextDb
@@ -534,7 +534,7 @@ func TestRtcGetValue(t *testing.T) {
 }
 
 func TestRtcUpdateValue(t *testing.T) {
-       var rtc = RunTimeContext{"/context/5345674458787728/"}
+       var rtc = RunTimeContext{"/context/5345674458787728/", ""}
        testCases := []struct {
                label         string
                mockContextDb *MockContextDb
@@ -581,7 +581,7 @@ func TestRtcUpdateValue(t *testing.T) {
 }
 
 func TestRtcDeletePair(t *testing.T) {
-       var rtc = RunTimeContext{"/context/5345674458787728/"}
+       var rtc = RunTimeContext{"/context/5345674458787728/", ""}
        testCases := []struct {
                label         string
                mockContextDb *MockContextDb
@@ -621,7 +621,7 @@ func TestRtcDeletePair(t *testing.T) {
 }
 
 func TestRtcDeletePrefix(t *testing.T) {
-       var rtc = RunTimeContext{"/context/5345674458787728/"}
+       var rtc = RunTimeContext{"/context/5345674458787728/", ""}
        testCases := []struct {
                label         string
                mockContextDb *MockContextDb