Instantiate infra_workload based on vf-module-*-ids
[multicloud/k8s.git] / src / k8splugin / api / brokerhandler.go
index 28e4423..7671db4 100644 (file)
@@ -16,9 +16,11 @@ package api
 import (
        "encoding/json"
        "io"
+       "log"
        "net/http"
 
-       "k8splugin/internal/app"
+       "github.com/onap/multicloud-k8s/src/k8splugin/internal/app"
+       "github.com/onap/multicloud-k8s/src/k8splugin/internal/helm"
 
        "github.com/gorilla/mux"
 )
@@ -37,22 +39,78 @@ 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 map[string][]string `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
+// "user_attributes": {
+//             "attributes": [
+//             {
+//                     "attribute_value": "foo",
+//                     "attribute_name": "bar"
+//             },
+//             {
+//                     "attribute_value": "value2",
+//                     "attribute_name": "name2"
+//             }
+//             ]
+// }
+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 ""
+       }
+
+       for _, value := range attributes {
+
+               attribute, ok := value.(map[string]interface{})
+               if !ok {
+                       log.Println("Unable to cast attribute to map[string]interface{}")
+                       return ""
+               }
+
+               attributeName, ok := attribute["attribute_name"].(string)
+               if !ok {
+                       log.Println("Unable to cast attribute_name to string")
+                       return ""
+               }
+               if attributeName == inp {
+                       attributevalue, ok := attribute["attribute_value"].(string)
+                       if !ok {
+                               log.Println("Unable to cast attribute_value to string")
+                               return ""
+                       }
+
+                       return attributevalue
+               }
+       }
+       return ""
 }
 
 func (b brokerInstanceHandler) createHandler(w http.ResponseWriter, r *http.Request) {
@@ -76,30 +134,37 @@ func (b brokerInstanceHandler) createHandler(w http.ResponseWriter, r *http.Requ
                return
        }
 
-       rbName, ok := req.UserDirectives["definition-name"]
-       if !ok {
-               http.Error(w, "definition-name is missing from user-directives", http.StatusBadRequest)
+       if req.VFModuleModelInvariantID == "" {
+               http.Error(w, "vf-module-model-invariant-id is empty", http.StatusBadRequest)
                return
        }
 
-       rbVersion, ok := req.UserDirectives["definition-version"]
-       if !ok {
-               http.Error(w, "definition-version is missing from user-directives", http.StatusBadRequest)
+       if req.VFModuleModelVersionID == "" {
+               http.Error(w, "vf-module-model-version-id is empty", http.StatusBadRequest)
                return
        }
 
-       profileName, ok := req.UserDirectives["profile-name"]
-       if !ok {
-               http.Error(w, "profile-name is missing from user-directives", http.StatusBadRequest)
+       profileName := req.getAttributeValue(req.SDNCDirectives, "k8s-rb-profile-name")
+       if profileName == "" {
+               http.Error(w, "k8s-rb-profile-name is missing from sdnc-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.(string)
-       instReq.RBVersion = rbVersion.(string)
-       instReq.ProfileName = profileName.(string)
+       instReq.RBName = req.VFModuleModelInvariantID
+       instReq.RBVersion = req.VFModuleModelVersionID
+       instReq.ProfileName = profileName
        instReq.CloudRegion = cloudRegion
+       instReq.Labels = map[string]string{
+               "vf_module_name": vfModuleName,
+       }
 
        resp, err := b.client.Create(instReq)
        if err != nil {
@@ -111,6 +176,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")
@@ -136,7 +202,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")
@@ -148,6 +214,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)
@@ -159,6 +264,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
+       }
 }