Skip to content
This repository has been archived by the owner on Jun 17, 2024. It is now read-only.

Commit

Permalink
Re-designed the resource_configuration schema
Browse files Browse the repository at this point in the history
1. Re-designed the resource_configuration schema
2. Updated the create and update logic as per the new schema
3. Modify read deployment to read all the resource properties retuned from the API

Signed-off-by: Prativa Bawri <bawrip@vmware.com>
  • Loading branch information
Prativa20 committed Feb 4, 2020
1 parent c63c377 commit d1ea0ff
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 139 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ require (
gopkg.in/jarcoal/httpmock.v1 v1.0.0-20170412085702-cf52904a3cf0
)

go 1.13
6 changes: 3 additions & 3 deletions sdk/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ type BusinessGroup struct {

// RequestResourceView - resource view of a provisioned request
type RequestResourceView struct {
Content []DeploymentResource `json:"content,omitempty"`
Links []interface{} `json:"links,omitempty"`
Content []interface{} `json:"content,omitempty"`
Links []interface{} `json:"links,omitempty"`
}

// DeploymentResource - deployment level view of the provisionined request
Expand All @@ -55,7 +55,7 @@ type DeploymentResource struct {
RequestID string `json:"requestId,omitempty"`
ResourceID string `json:"resourceId,omitempty"`
ResourceType string `json:"resourceType,omitempty"`
ResourcesData DeploymentResourceData `json:"data,omitempty"`
ResourcesData map[string]interface{} `json:"data,omitempty"`
}

// DeploymentResourceData - view of the resources/machines in a deployment
Expand Down
2 changes: 2 additions & 0 deletions sdk/vra7_sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ func (c *APIClient) GetCatalogItemRequestTemplate(catalogItemID string) (*Catalo
if unmarshallErr != nil {
return nil, unmarshallErr
}
// j, _ := json.Marshal(requestTemplate)
// log.Critical("the template is ====> %v ", string(j))
return &requestTemplate, nil
}

Expand Down
38 changes: 14 additions & 24 deletions utils/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"encoding/json"
"reflect"
"strconv"
"strings"
)

// terraform provider constants
Expand Down Expand Up @@ -53,29 +52,6 @@ func ConvertInterfaceToString(interfaceData interface{}) string {
return stringData
}

// UpdateResourceConfigurationMap updates the resource configuration with
//the deployment resource data if there is difference
// between the config data and deployment data, return true
func UpdateResourceConfigurationMap(
resourceConfiguration map[string]interface{}, vmData map[string]map[string]interface{}) (map[string]interface{}, bool) {
var changed bool
for configKey1, configValue1 := range resourceConfiguration {
for configKey2, configValue2 := range vmData {
if strings.HasPrefix(configKey1, configKey2+".") {
trimmedKey := strings.TrimPrefix(configKey1, configKey2+".")
currentValue := configValue1
updatedValue := ConvertInterfaceToString(configValue2[trimmedKey])

if updatedValue != "" && updatedValue != currentValue {
resourceConfiguration[configKey1] = updatedValue
changed = true
}
}
}
}
return resourceConfiguration, changed
}

// ReplaceValueInRequestTemplate replaces the value for a given key in a catalog
// request template.
func ReplaceValueInRequestTemplate(templateInterface map[string]interface{}, field string, value interface{}) (map[string]interface{}, bool) {
Expand Down Expand Up @@ -116,3 +92,17 @@ func AddValueToRequestTemplate(templateInterface map[string]interface{}, field s
//Return updated map interface type
return templateInterface
}

// ResourceMapper returns the mapping of resource attributes from ResourceView APIs
// to Catalog Item Request Template APIs
func ResourceMapper() map[string]string {
m := make(map[string]string)
m["MachineName"] = "name"
m["MachineDescription"] = "description"
m["MachineMemory"] = "memory"
m["MachineStorage"] = "storage"
m["MachineCPU"] = "cpu"
m["MachineStatus"] = "status"
m["MachineType"] = "type"
return m
}
166 changes: 166 additions & 0 deletions vra7/resource_configuration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package vra7

import (
"reflect"
"strconv"

"github.com/hashicorp/terraform/helper/schema"
"github.com/terraform-providers/terraform-provider-vra7/utils"
)

// ResourceConfigurationStruct - structure representing the resource_configuration
type ResourceConfigurationStruct struct {
Name string `json:"name"`
Configuration map[string]interface{} `json:"configuration"`
}

func resourceConfigurationSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"configuration": &schema.Schema{
Type: schema.TypeMap,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"name": {
Type: schema.TypeString,
Required: true,
},
},
},
}
}

func expandResourceConfiguration(rConfigurations []interface{}) []ResourceConfigurationStruct {
configs := make([]ResourceConfigurationStruct, 0, len(rConfigurations))

for _, config := range rConfigurations {
configMap := config.(map[string]interface{})

rConfig := ResourceConfigurationStruct{
Name: configMap["name"].(string),
Configuration: configMap["configuration"].(map[string]interface{}),
}
configs = append(configs, rConfig)
}
return configs
}

func flattenResourceConfigurations(configs []ResourceConfigurationStruct) []map[string]interface{} {
if len(configs) == 0 {
return make([]map[string]interface{}, 0)
}
rConfigs := make([]map[string]interface{}, 0, len(configs))
for _, config := range configs {
componentName, resourceDataMap := parseDataMap(config.Configuration)
helper := make(map[string]interface{})
helper["name"] = componentName
helper["configuration"] = resourceDataMap
rConfigs = append(rConfigs, helper)
}
return rConfigs
}

func parseDataMap(resourceData map[string]interface{}) (string, map[string]interface{}) {
m := make(map[string]interface{})
componentName := ""
resourcePropertyMapper := utils.ResourceMapper()
for key, value := range resourceData {

// Component property is within data of a resource, so fetching it from there and putting it as resource level property
if key == "Component" {
componentName = convToString(value)
}
if i, ok := resourcePropertyMapper[key]; ok {
key = i
}
v := reflect.ValueOf(value)
switch v.Kind() {
case reflect.Slice:
parseArray(key, m, value.([]interface{}))
case reflect.Map:
parseMap(key, m, value.(map[string]interface{}))
default:
m[key] = convToString(value)
}
}
return componentName, m
}

func parseMap(prefix string, m map[string]interface{}, data map[string]interface{}) {

for key, value := range data {
v := reflect.ValueOf(value)

switch v.Kind() {
case reflect.Slice:
parseArray(prefix+"."+key, m, value.([]interface{}))
case reflect.Map:
parseMap(prefix+"."+key, m, value.(map[string]interface{}))
default:
m[prefix+"."+key] = convToString(value)
}
}
}

func parseArray(prefix string, m map[string]interface{}, value []interface{}) {

for index, val := range value {
v := reflect.ValueOf(val)
switch v.Kind() {
case reflect.Map:
/* for properties like NETWORK_LIST, DISK_VOLUMES etc, the value is a slice of map as follows.
Out of all the information, only data is important information, so leaving out rest of the properties
"NETWORK_LIST":[
{
"componentTypeId":"",
"componentId":null,
"classId":"",
"typeFilter":null,
"data":{
"NETWORK_MAC_ADDRESS":"00:50:56:b6:78:c6",
"NETWORK_NAME":"dvPortGroup-wdc-sdm-vm-1521"
}
}
]
*/
objMap := val.(map[string]interface{})
for k, v := range objMap {
if k == "data" {
parseMap(prefix+"."+convToString(index), m, v.(map[string]interface{}))
}
}
default:
m[prefix+"."+convToString(index)] = convToString(val)
}
}
}

func convToString(value interface{}) string {

v := reflect.ValueOf(value)
switch v.Kind() {
case reflect.String:
return value.(string)
case reflect.Float64:
return strconv.FormatFloat(value.(float64), 'f', 0, 64)
case reflect.Float32:
return strconv.FormatFloat(value.(float64), 'f', 0, 32)
case reflect.Int:
return strconv.Itoa(value.(int))
case reflect.Int32:
return strconv.Itoa(value.(int))
case reflect.Int64:
return strconv.FormatInt(value.(int64), 10)
case reflect.Bool:
return strconv.FormatBool(value.(bool))
}
return ""
}
Loading

0 comments on commit d1ea0ff

Please sign in to comment.