Update broker responses to match spec and SO 26/88426/3
authorKiran Kamineni <kiran.k.kamineni@intel.com>
Thu, 23 May 2019 20:50:50 +0000 (13:50 -0700)
committerKiran Kamineni <kiran.k.kamineni@intel.com>
Fri, 24 May 2019 02:28:22 +0000 (19:28 -0700)
The broker responses need to match the spec and
what SO expects as responses.
CREATE_COMPLETE instead of CREATED in both POST and GET
DELETE now returns a response body
GET by name is now supported
Name is an alias for vf_module_id which is expected to be provided
as an attribute in sdnc_directives in the original POST request

Issue-ID: MULTICLOUD-645
Change-Id: Ifeca755a07298d0a858cbe9e80f9ce654d6d21b8
Signed-off-by: Kiran Kamineni <kiran.k.kamineni@intel.com>
src/k8splugin/api/api.go
src/k8splugin/api/brokerhandler.go
src/k8splugin/api/brokerhandler_test.go
src/k8splugin/api/instancehandler_test.go
src/k8splugin/internal/app/config_backend.go
src/k8splugin/internal/app/instance.go
src/k8splugin/internal/app/instance_test.go

index 58e50a1..808d6f5 100644 (file)
@@ -47,6 +47,7 @@ func NewRouter(defClient rb.DefinitionManager,
        brokerHandler := brokerInstanceHandler{client: instClient}
        router.HandleFunc("/{cloud-owner}/{cloud-region}/infra_workload", brokerHandler.createHandler).Methods("POST")
        router.HandleFunc("/{cloud-owner}/{cloud-region}/infra_workload/{instID}", brokerHandler.getHandler).Methods("GET")
+       router.HandleFunc("/{cloud-owner}/{cloud-region}/infra_workload", brokerHandler.findHandler).Queries("name", "{name}").Methods("GET")
        router.HandleFunc("/{cloud-owner}/{cloud-region}/infra_workload/{instID}", brokerHandler.deleteHandler).Methods("DELETE")
 
        //Setup the connectivity api handler here
index dca6478..c0564ee 100644 (file)
@@ -39,22 +39,32 @@ type brokerRequest struct {
        VFModuleModelVersionID       string                 `json:"vf-module-model-version-id"`
        VFModuleModelCustomizationID string                 `json:"vf-module-model-customization-id"`
        OOFDirectives                map[string]interface{} `json:"oof_directives"`
-       SDNCDirections               map[string]interface{} `json:"sdnc_directives"`
+       SDNCDirectives               map[string]interface{} `json:"sdnc_directives"`
        UserDirectives               map[string]interface{} `json:"user_directives"`
        TemplateType                 string                 `json:"template_type"`
        TemplateData                 map[string]interface{} `json:"template_data"`
 }
 
 type brokerPOSTResponse struct {
-       TemplateType     string                    `json:"template_type"`
-       WorkloadID       string                    `json:"workload_id"`
-       TemplateResponse []helm.KubernetesResource `json:"template_response"`
+       TemplateType         string                    `json:"template_type"`
+       WorkloadID           string                    `json:"workload_id"`
+       TemplateResponse     []helm.KubernetesResource `json:"template_response"`
+       WorkloadStatus       string                    `json:"workload_status"`
+       WorkloadStatusReason map[string]interface{}    `json:"workload_status_reason"`
 }
 
 type brokerGETResponse struct {
-       TemplateType   string `json:"template_type"`
-       WorkloadID     string `json:"workload_id"`
-       WorkloadStatus string `json:"workload_status"`
+       TemplateType         string                 `json:"template_type"`
+       WorkloadID           string                 `json:"workload_id"`
+       WorkloadStatus       string                 `json:"workload_status"`
+       WorkloadStatusReason map[string]interface{} `json:"workload_status_reason"`
+}
+
+type brokerDELETEResponse struct {
+       TemplateType         string                 `json:"template_type"`
+       WorkloadID           string                 `json:"workload_id"`
+       WorkloadStatus       string                 `json:"workload_status"`
+       WorkloadStatusReason map[string]interface{} `json:"workload_status_reason"`
 }
 
 // getUserDirectiveValue parses the following kind of json
@@ -70,8 +80,8 @@ type brokerGETResponse struct {
 //             }
 //             ]
 // }
-func (b brokerRequest) getUserDirectiveValue(inp string) string {
-       attributes, ok := b.UserDirectives["attributes"].([]interface{})
+func (b brokerRequest) getAttributeValue(directives map[string]interface{}, inp string) string {
+       attributes, ok := directives["attributes"].([]interface{})
        if !ok {
                log.Println("Unable to cast attributes to []interface{}")
                return ""
@@ -85,12 +95,12 @@ func (b brokerRequest) getUserDirectiveValue(inp string) string {
                        return ""
                }
 
-               attributename, ok := attribute["attribute_name"].(string)
+               attributeName, ok := attribute["attribute_name"].(string)
                if !ok {
                        log.Println("Unable to cast attribute_name to string")
                        return ""
                }
-               if attributename == inp {
+               if attributeName == inp {
                        attributevalue, ok := attribute["attribute_value"].(string)
                        if !ok {
                                log.Println("Unable to cast attribute_value to string")
@@ -124,30 +134,39 @@ func (b brokerInstanceHandler) createHandler(w http.ResponseWriter, r *http.Requ
                return
        }
 
-       rbName := req.getUserDirectiveValue("definition-name")
+       rbName := req.getAttributeValue(req.UserDirectives, "definition-name")
        if rbName == "" {
                http.Error(w, "definition-name is missing from user-directives", http.StatusBadRequest)
                return
        }
 
-       rbVersion := req.getUserDirectiveValue("definition-version")
+       rbVersion := req.getAttributeValue(req.UserDirectives, "definition-version")
        if rbVersion == "" {
                http.Error(w, "definition-version is missing from user-directives", http.StatusBadRequest)
                return
        }
 
-       profileName := req.getUserDirectiveValue("profile-name")
+       profileName := req.getAttributeValue(req.UserDirectives, "profile-name")
        if profileName == "" {
                http.Error(w, "profile-name is missing from user-directives", http.StatusBadRequest)
                return
        }
 
+       vfModuleName := req.getAttributeValue(req.SDNCDirectives, "vf_module_name")
+       if vfModuleName == "" {
+               http.Error(w, "vf_module_name is missing from sdnc-directives", http.StatusBadRequest)
+               return
+       }
+
        // Setup the resource parameters for making the request
        var instReq app.InstanceRequest
        instReq.RBName = rbName
        instReq.RBVersion = rbVersion
        instReq.ProfileName = profileName
        instReq.CloudRegion = cloudRegion
+       instReq.Labels = map[string]string{
+               "vf_module_name": vfModuleName,
+       }
 
        resp, err := b.client.Create(instReq)
        if err != nil {
@@ -159,6 +178,7 @@ func (b brokerInstanceHandler) createHandler(w http.ResponseWriter, r *http.Requ
                TemplateType:     "heat",
                WorkloadID:       resp.ID,
                TemplateResponse: resp.Resources,
+               WorkloadStatus:   "CREATE_COMPLETE",
        }
 
        w.Header().Set("Content-Type", "application/json")
@@ -184,7 +204,7 @@ func (b brokerInstanceHandler) getHandler(w http.ResponseWriter, r *http.Request
        brokerResp := brokerGETResponse{
                TemplateType:   "heat",
                WorkloadID:     resp.ID,
-               WorkloadStatus: "CREATED",
+               WorkloadStatus: "CREATE_COMPLETE",
        }
 
        w.Header().Set("Content-Type", "application/json")
@@ -196,6 +216,45 @@ func (b brokerInstanceHandler) getHandler(w http.ResponseWriter, r *http.Request
        }
 }
 
+// getHandler retrieves information about an instance via the ID
+func (b brokerInstanceHandler) findHandler(w http.ResponseWriter, r *http.Request) {
+       vars := mux.Vars(r)
+       //name is an alias for vf_module_name from the so adapter
+       name := vars["name"]
+       responses, _ := b.client.Find("", "", "", map[string]string{"vf_module_name": name})
+
+       brokerResp := brokerGETResponse{
+               TemplateType:   "heat",
+               WorkloadID:     "",
+               WorkloadStatus: "GET_COMPLETE",
+               WorkloadStatusReason: map[string]interface{}{
+                       //treating stacks as an array of map[string]interface{} types
+                       "stacks": []map[string]interface{}{},
+               },
+       }
+
+       if len(responses) != 0 {
+               //Return the first object that matches.
+               resp := responses[0]
+               brokerResp.WorkloadID = resp.ID
+               brokerResp.WorkloadStatus = "CREATE_COMPLETE"
+               brokerResp.WorkloadStatusReason["stacks"] = []map[string]interface{}{
+                       {
+                               "stack_status": "CREATE_COMPLETE",
+                               "id":           resp.ID,
+                       },
+               }
+       }
+
+       w.Header().Set("Content-Type", "application/json")
+       w.WriteHeader(http.StatusOK)
+       err := json.NewEncoder(w).Encode(brokerResp)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+}
+
 // deleteHandler method terminates an instance via the ID
 func (b brokerInstanceHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
        vars := mux.Vars(r)
@@ -207,6 +266,17 @@ func (b brokerInstanceHandler) deleteHandler(w http.ResponseWriter, r *http.Requ
                return
        }
 
+       brokerResp := brokerDELETEResponse{
+               TemplateType:   "heat",
+               WorkloadID:     instanceID,
+               WorkloadStatus: "DELETE_COMPLETE",
+       }
+
        w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(http.StatusAccepted)
+       err = json.NewEncoder(w).Encode(brokerResp)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
 }
index 8289441..15b7bd7 100644 (file)
@@ -70,6 +70,14 @@ func TestBrokerCreateHandler(t *testing.T) {
                        label: "Succesfully create an Instance",
                        input: bytes.NewBuffer([]byte(`{
                                "vf-module-model-customization-id": "84sdfkio938",
+                               "sdnc_directives": {
+                                       "attributes": [
+                                               {
+                                                       "attribute_name": "vf_module_name",
+                                                       "attribute_value": "test-vf-module-name"
+                                               }
+                                       ]
+                               },
                                "user_directives": {
                                        "attributes": [
                                                {
@@ -88,8 +96,9 @@ func TestBrokerCreateHandler(t *testing.T) {
                                }
                        }`)),
                        expected: brokerPOSTResponse{
-                               WorkloadID:   "HaKpys8e",
-                               TemplateType: "heat",
+                               WorkloadID:     "HaKpys8e",
+                               TemplateType:   "heat",
+                               WorkloadStatus: "CREATE_COMPLETE",
                                TemplateResponse: []helm.KubernetesResource{
                                        {
                                                GVK: schema.GroupVersionKind{
@@ -111,14 +120,14 @@ func TestBrokerCreateHandler(t *testing.T) {
                        instClient: &mockInstanceClient{
                                items: []app.InstanceResponse{
                                        {
-                                               ID:          "HaKpys8e",
+                                               ID: "HaKpys8e",
                                                Request: app.InstanceRequest{
                                                        RBName:      "test-rbdef",
                                                        RBVersion:   "v1",
                                                        ProfileName: "profile1",
                                                        CloudRegion: "region1",
                                                },
-                                               Namespace:   "testnamespace",
+                                               Namespace: "testnamespace",
                                                Resources: []helm.KubernetesResource{
                                                        {
                                                                GVK: schema.GroupVersionKind{
@@ -191,19 +200,19 @@ func TestBrokerGetHandler(t *testing.T) {
                        expectedResponse: brokerGETResponse{
                                TemplateType:   "heat",
                                WorkloadID:     "HaKpys8e",
-                               WorkloadStatus: "CREATED",
+                               WorkloadStatus: "CREATE_COMPLETE",
                        },
                        instClient: &mockInstanceClient{
                                items: []app.InstanceResponse{
                                        {
-                                               ID:          "HaKpys8e",
+                                               ID: "HaKpys8e",
                                                Request: app.InstanceRequest{
                                                        RBName:      "test-rbdef",
                                                        RBVersion:   "v1",
                                                        ProfileName: "profile1",
                                                        CloudRegion: "region1",
                                                },
-                                               Namespace:   "testnamespace",
+                                               Namespace: "testnamespace",
                                                Resources: []helm.KubernetesResource{
                                                        {
                                                                GVK: schema.GroupVersionKind{
@@ -250,12 +259,118 @@ func TestBrokerGetHandler(t *testing.T) {
        }
 }
 
+func TestBrokerFindHandler(t *testing.T) {
+       testCases := []struct {
+               label            string
+               input            string
+               expectedCode     int
+               expectedResponse brokerGETResponse
+               instClient       *mockInstanceClient
+       }{
+               {
+                       label:        "Successful find an Instance",
+                       input:        "test-vf-module-name",
+                       expectedCode: http.StatusOK,
+                       expectedResponse: brokerGETResponse{
+                               TemplateType:   "heat",
+                               WorkloadID:     "HaKpys8e",
+                               WorkloadStatus: "CREATE_COMPLETE",
+                               WorkloadStatusReason: map[string]interface{}{
+                                       "stacks": []map[string]interface{}{
+                                               {
+                                                       "stack_status": "CREATE_COMPLETE",
+                                                       "id":           "HaKpys8e",
+                                               },
+                                       },
+                               },
+                       },
+                       instClient: &mockInstanceClient{
+                               items: []app.InstanceResponse{
+                                       {
+                                               ID: "HaKpys8e",
+                                               Request: app.InstanceRequest{
+                                                       RBName:      "test-rbdef",
+                                                       RBVersion:   "v1",
+                                                       ProfileName: "profile1",
+                                                       CloudRegion: "region1",
+                                               },
+                                               Namespace: "testnamespace",
+                                               Resources: []helm.KubernetesResource{
+                                                       {
+                                                               GVK: schema.GroupVersionKind{
+                                                                       Group:   "apps",
+                                                                       Version: "v1",
+                                                                       Kind:    "Deployment"},
+                                                               Name: "test-deployment",
+                                                       },
+                                                       {
+                                                               GVK: schema.GroupVersionKind{
+                                                                       Group:   "",
+                                                                       Version: "v1",
+                                                                       Kind:    "Service"},
+                                                               Name: "test-service",
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+               },
+               {
+                       label:        "Fail to find an Instance",
+                       input:        "test-vf-module-name-1",
+                       expectedCode: http.StatusOK,
+                       expectedResponse: brokerGETResponse{
+                               TemplateType:   "heat",
+                               WorkloadID:     "",
+                               WorkloadStatus: "GET_COMPLETE",
+                               WorkloadStatusReason: map[string]interface{}{
+                                       "stacks": []map[string]interface{}{},
+                               },
+                       },
+                       instClient: &mockInstanceClient{},
+               },
+       }
+
+       for _, testCase := range testCases {
+               t.Run(testCase.label, func(t *testing.T) {
+                       request := httptest.NewRequest("GET", "/cloudowner/cloudregion/infra_workload?name="+testCase.input, nil)
+                       resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil))
+
+                       if testCase.expectedCode != resp.StatusCode {
+                               t.Fatalf("Request method returned: %v and it was expected: %v",
+                                       resp.StatusCode, testCase.expectedCode)
+                       }
+                       if resp.StatusCode == http.StatusOK {
+                               var response brokerGETResponse
+                               err := json.NewDecoder(resp.Body).Decode(&response)
+                               if err != nil {
+                                       t.Fatalf("Parsing the returned response got an error (%s)", err)
+                               }
+                               if testCase.expectedResponse.WorkloadID != response.WorkloadID {
+                                       t.Fatalf("TestGetHandler returned:\n result=%v\n expected=%v",
+                                               response.WorkloadID, testCase.expectedResponse.WorkloadID)
+                               }
+                               tcStacks := testCase.expectedResponse.WorkloadStatusReason["stacks"].([]map[string]interface{})
+                               if len(tcStacks) != 0 {
+                                       //We expect only one response in this testcase.
+                                       resStacks := response.WorkloadStatusReason["stacks"].([]interface{})[0].(map[string]interface{})
+                                       if !reflect.DeepEqual(tcStacks[0], resStacks) {
+                                               t.Fatalf("TestGetHandler returned:\n result=%v\n expected=%v",
+                                                       resStacks, tcStacks)
+                                       }
+                               }
+                       }
+               })
+       }
+}
+
 func TestBrokerDeleteHandler(t *testing.T) {
        testCases := []struct {
-               label        string
-               input        string
-               expectedCode int
-               instClient   *mockInstanceClient
+               label            string
+               input            string
+               expectedCode     int
+               expectedResponse brokerDELETEResponse
+               instClient       *mockInstanceClient
        }{
                {
                        label:        "Fail to destroy VNF",
@@ -269,7 +384,12 @@ func TestBrokerDeleteHandler(t *testing.T) {
                        label:        "Succesful delete a VNF",
                        input:        "HaKpys8e",
                        expectedCode: http.StatusAccepted,
-                       instClient:   &mockInstanceClient{},
+                       expectedResponse: brokerDELETEResponse{
+                               TemplateType:   "heat",
+                               WorkloadID:     "HaKpys8e",
+                               WorkloadStatus: "DELETE_COMPLETE",
+                       },
+                       instClient: &mockInstanceClient{},
                },
        }
 
@@ -281,6 +401,17 @@ func TestBrokerDeleteHandler(t *testing.T) {
                        if testCase.expectedCode != resp.StatusCode {
                                t.Fatalf("Request method returned: %v and it was expected: %v", resp.StatusCode, testCase.expectedCode)
                        }
+                       if resp.StatusCode == http.StatusOK {
+                               var response brokerGETResponse
+                               err := json.NewDecoder(resp.Body).Decode(&response)
+                               if err != nil {
+                                       t.Fatalf("Parsing the returned response got an error (%s)", err)
+                               }
+                               if !reflect.DeepEqual(testCase.expectedResponse, response) {
+                                       t.Fatalf("TestGetHandler returned:\n result=%v\n expected=%v",
+                                               response, testCase.expectedResponse)
+                               }
+                       }
                })
        }
 }
index 2e2450e..dac7db0 100644 (file)
@@ -58,6 +58,14 @@ func (m *mockInstanceClient) Get(id string) (app.InstanceResponse, error) {
        return m.items[0], nil
 }
 
+func (m *mockInstanceClient) Find(rbName string, ver string, profile string, labelKeys map[string]string) ([]app.InstanceResponse, error) {
+       if m.err != nil {
+               return nil, m.err
+       }
+
+       return m.items, nil
+}
+
 func (m *mockInstanceClient) Delete(id string) error {
        return m.err
 }
@@ -104,14 +112,14 @@ func TestInstanceCreateHandler(t *testing.T) {
                                "profile-name": "profile1"
                        }`)),
                        expected: app.InstanceResponse{
-                               ID:          "HaKpys8e",
+                               ID: "HaKpys8e",
                                Request: app.InstanceRequest{
                                        RBName:      "test-rbdef",
                                        RBVersion:   "v1",
                                        ProfileName: "profile1",
                                        CloudRegion: "region1",
                                },
-                               Namespace:   "testnamespace",
+                               Namespace: "testnamespace",
                                Resources: []helm.KubernetesResource{
                                        {
                                                GVK: schema.GroupVersionKind{
@@ -133,14 +141,14 @@ func TestInstanceCreateHandler(t *testing.T) {
                        instClient: &mockInstanceClient{
                                items: []app.InstanceResponse{
                                        {
-                                               ID:          "HaKpys8e",
+                                               ID: "HaKpys8e",
                                                Request: app.InstanceRequest{
                                                        RBName:      "test-rbdef",
                                                        RBVersion:   "v1",
                                                        ProfileName: "profile1",
                                                        CloudRegion: "region1",
                                                },
-                                               Namespace:   "testnamespace",
+                                               Namespace: "testnamespace",
                                                Resources: []helm.KubernetesResource{
                                                        {
                                                                GVK: schema.GroupVersionKind{
@@ -207,14 +215,14 @@ func TestInstanceGetHandler(t *testing.T) {
                        input:        "HaKpys8e",
                        expectedCode: http.StatusOK,
                        expectedResponse: &app.InstanceResponse{
-                               ID:          "HaKpys8e",
+                               ID: "HaKpys8e",
                                Request: app.InstanceRequest{
                                        RBName:      "test-rbdef",
                                        RBVersion:   "v1",
                                        ProfileName: "profile1",
                                        CloudRegion: "region1",
                                },
-                               Namespace:   "testnamespace",
+                               Namespace: "testnamespace",
                                Resources: []helm.KubernetesResource{
                                        {
                                                GVK: schema.GroupVersionKind{
@@ -235,14 +243,14 @@ func TestInstanceGetHandler(t *testing.T) {
                        instClient: &mockInstanceClient{
                                items: []app.InstanceResponse{
                                        {
-                                               ID:          "HaKpys8e",
+                                               ID: "HaKpys8e",
                                                Request: app.InstanceRequest{
                                                        RBName:      "test-rbdef",
                                                        RBVersion:   "v1",
                                                        ProfileName: "profile1",
                                                        CloudRegion: "region1",
                                                },
-                                               Namespace:   "testnamespace",
+                                               Namespace: "testnamespace",
                                                Resources: []helm.KubernetesResource{
                                                        {
                                                                GVK: schema.GroupVersionKind{
index 81696b3..9894b6a 100644 (file)
@@ -343,7 +343,7 @@ func scheduleResources(c chan configResourceList) {
                data := <-c
                //TODO: ADD Check to see if Application running
                ic := NewInstanceClient()
-               resp, err := ic.Find(data.profile.RBName, data.profile.RBVersion, data.profile.ProfileName)
+               resp, err := ic.Find(data.profile.RBName, data.profile.RBVersion, data.profile.ProfileName, nil)
                if err != nil || len(resp) == 0 {
                        log.Println("Error finding a running instance. Retrying later...")
                        time.Sleep(time.Second * 10)
index fe9f385..19841c0 100644 (file)
@@ -50,7 +50,7 @@ type InstanceResponse struct {
 type InstanceManager interface {
        Create(i InstanceRequest) (InstanceResponse, error)
        Get(id string) (InstanceResponse, error)
-       Find(rbName string, ver string, profile string) ([]InstanceResponse, error)
+       Find(rbName string, ver string, profile string, labelKeys map[string]string) ([]InstanceResponse, error)
        Delete(id string) error
 }
 
@@ -131,13 +131,8 @@ func (v *InstanceClient) Create(i InstanceRequest) (InstanceResponse, error) {
 
        //Compose the return response
        resp := InstanceResponse{
-               ID: id,
-               Request: InstanceRequest{
-                       RBName:      i.RBName,
-                       RBVersion:   i.RBVersion,
-                       ProfileName: i.ProfileName,
-                       CloudRegion: i.CloudRegion,
-               },
+               ID:        id,
+               Request:   i,
                Namespace: profile.Namespace,
                Resources: createdResources,
        }
@@ -179,9 +174,11 @@ func (v *InstanceClient) Get(id string) (InstanceResponse, error) {
 // Find returns the instances that match the given criteria
 // If version is empty, it will return all instances for a given rbName
 // If profile is empty, it will return all instances for a given rbName+version
-func (v *InstanceClient) Find(rbName string, version string, profile string) ([]InstanceResponse, error) {
-       if rbName == "" {
-               return []InstanceResponse{}, pkgerrors.New("rbName is required and cannot be empty")
+// If labelKeys are provided, the results are filtered based on that.
+// It is an AND operation for labelkeys.
+func (v *InstanceClient) Find(rbName string, version string, profile string, labelKeys map[string]string) ([]InstanceResponse, error) {
+       if rbName == "" && len(labelKeys) == 0 {
+               return []InstanceResponse{}, pkgerrors.New("rbName or labelkeys is required and cannot be empty")
        }
 
        values, err := db.DBconn.ReadAll(v.storeName, v.tagInst)
@@ -191,6 +188,7 @@ func (v *InstanceClient) Find(rbName string, version string, profile string) ([]
 
        response := []InstanceResponse{}
        //values is a map[string][]byte
+InstanceResponseLoop:
        for _, value := range values {
                resp := InstanceResponse{}
                db.DBconn.Unmarshal(value, &resp)
@@ -198,19 +196,45 @@ func (v *InstanceClient) Find(rbName string, version string, profile string) ([]
                        return []InstanceResponse{}, pkgerrors.Wrap(err, "Unmarshaling Instance Value")
                }
 
-               if resp.Request.RBName == rbName {
+               // Filter by labels provided
+               if len(labelKeys) != 0 {
+                       for lkey, lvalue := range labelKeys {
+                               //Check if label key exists and get its value
+                               if val, ok := resp.Request.Labels[lkey]; ok {
+                                       if lvalue != val {
+                                               continue InstanceResponseLoop
+                                       }
+                               } else {
+                                       continue InstanceResponseLoop
+                               }
+                       }
+               }
+
+               if rbName != "" {
+                       if resp.Request.RBName == rbName {
 
-                       //Check if a version is provided and if it matches
-                       if version != "" {
-                               if resp.Request.RBVersion == version {
-                                       //Check if a profilename matches or if it is not provided
-                                       if profile == "" || resp.Request.ProfileName == profile {
-                                               response = append(response, resp)
+                               //Check if a version is provided and if it matches
+                               if version != "" {
+                                       if resp.Request.RBVersion == version {
+                                               //Check if a profilename matches or if it is not provided
+                                               if profile == "" || resp.Request.ProfileName == profile {
+                                                       response = append(response, resp)
+                                               }
                                        }
+                               } else {
+                                       //Append all versions as version is not provided
+                                       response = append(response, resp)
                                }
-                       } else {
-                               //Append all versions as version is not provided
-                               response = append(response, resp)
+                       }
+               } else {
+                       response = append(response, resp)
+               }
+       }
+
+       //filter the list by labelKeys now
+       for _, value := range response {
+               for _, label := range labelKeys {
+                       if _, ok := value.Request.Labels[label]; ok {
                        }
                }
        }
index 87824d7..ea37748 100644 (file)
@@ -339,7 +339,10 @@ func TestInstanceFind(t *testing.T) {
                                                "profile-name":"profile1",
                                                "rb-name":"test-rbdef",
                                                "rb-version":"v1",
-                                               "cloud-region":"region1"
+                                               "cloud-region":"region1",
+                                               "labels":{
+                                                       "vf_module_id": "test-vf-module-id"
+                                               }
                                        },
                                        "namespace":"testnamespace",
                                        "resources": [
@@ -439,6 +442,9 @@ func TestInstanceFind(t *testing.T) {
                                        RBVersion:   "v1",
                                        ProfileName: "profile1",
                                        CloudRegion: "region1",
+                                       Labels: map[string]string{
+                                               "vf_module_id": "test-vf-module-id",
+                                       },
                                },
                                Namespace: "testnamespace",
                                Resources: []helm.KubernetesResource{
@@ -513,7 +519,7 @@ func TestInstanceFind(t *testing.T) {
                }
                ic := NewInstanceClient()
                name := "test-rbdef"
-               data, err := ic.Find(name, "", "")
+               data, err := ic.Find(name, "", "", nil)
                if err != nil {
                        t.Fatalf("TestInstanceFind returned an error (%s)", err)
                }
@@ -548,6 +554,9 @@ func TestInstanceFind(t *testing.T) {
                                        RBVersion:   "v1",
                                        ProfileName: "profile1",
                                        CloudRegion: "region1",
+                                       Labels: map[string]string{
+                                               "vf_module_id": "test-vf-module-id",
+                                       },
                                },
                                Namespace: "testnamespace",
 
@@ -598,7 +607,7 @@ func TestInstanceFind(t *testing.T) {
                }
                ic := NewInstanceClient()
                name := "test-rbdef"
-               data, err := ic.Find(name, "v1", "")
+               data, err := ic.Find(name, "v1", "", nil)
                if err != nil {
                        t.Fatalf("TestInstanceFind returned an error (%s)", err)
                }
@@ -633,6 +642,9 @@ func TestInstanceFind(t *testing.T) {
                                        RBVersion:   "v1",
                                        ProfileName: "profile1",
                                        CloudRegion: "region1",
+                                       Labels: map[string]string{
+                                               "vf_module_id": "test-vf-module-id",
+                                       },
                                },
                                Namespace: "testnamespace",
 
@@ -656,7 +668,7 @@ func TestInstanceFind(t *testing.T) {
                }
                ic := NewInstanceClient()
                name := "test-rbdef"
-               data, err := ic.Find(name, "v1", "profile1")
+               data, err := ic.Find(name, "v1", "profile1", nil)
                if err != nil {
                        t.Fatalf("TestInstanceFind returned an error (%s)", err)
                }
@@ -715,7 +727,7 @@ func TestInstanceFind(t *testing.T) {
 
                ic := NewInstanceClient()
                name := "non-existing"
-               resp, _ := ic.Find(name, "", "")
+               resp, _ := ic.Find(name, "", "", nil)
                if len(resp) != 0 {
                        t.Fatalf("Expected 0 responses, but got %d", len(resp))
                }