From bb610b59b9b0be6c03ccb9a504f5c3e79d53889a Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 25 Sep 2020 16:43:38 +0800 Subject: [PATCH 1/6] Support non-string type for parameters of azurerm_managed_application --- .../managed_application_resource.go | 91 +++++++++++++++---- .../managed_application_resource_test.go | 41 +++++---- .../docs/r/managed_application.html.markdown | 16 ++-- 3 files changed, 108 insertions(+), 40 deletions(-) diff --git a/azurerm/internal/services/managedapplications/managed_application_resource.go b/azurerm/internal/services/managedapplications/managed_application_resource.go index 023a4637587c..edf560165024 100644 --- a/azurerm/internal/services/managedapplications/managed_application_resource.go +++ b/azurerm/internal/services/managedapplications/managed_application_resource.go @@ -1,12 +1,15 @@ package managedapplications import ( + "bytes" + "encoding/json" "fmt" "log" "time" "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" @@ -70,14 +73,24 @@ func resourceManagedApplication() *schema.Resource { ValidateFunc: validate.ManagedApplicationDefinitionID, }, - "parameters": { - Type: schema.TypeMap, - Optional: true, + "parameters": { // TODO -- remove this attribute after the deprecation + Type: schema.TypeMap, + Optional: true, + Computed: true, + Deprecated: "Deprecated in favour of `parameter_values`", Elem: &schema.Schema{ Type: schema.TypeString, }, }, + "parameter_values": { + Type: schema.TypeString, + Optional: true, + Computed: true, // TODO -- remove Computed after the deprecation + ValidateFunc: validation.StringIsJSON, + DiffSuppressFunc: structure.SuppressJsonDiff, + }, + "plan": { Type: schema.TypeList, Optional: true, @@ -158,26 +171,20 @@ func resourceManagedApplicationCreateUpdate(d *schema.ResourceData, meta interfa ManagedResourceGroupID: utils.String(targetResourceGroupId), } } + if v, ok := d.GetOk("application_definition_id"); ok { parameters.ApplicationDefinitionID = utils.String(v.(string)) } + if v, ok := d.GetOk("plan"); ok { parameters.Plan = expandManagedApplicationPlan(v.([]interface{})) } - if v, ok := d.GetOk("parameters"); ok { - params := v.(map[string]interface{}) - newParams := make(map[string]interface{}, len(params)) - for key, val := range params { - newParams[key] = struct { - Value interface{} `json:"value"` - }{ - Value: val, - } - } - - parameters.Parameters = &newParams + params, err := expandManagedApplicationParameters(d) + if err != nil { + return fmt.Errorf("Error expanding `parameters` or `parameter_values`: %+v", err) } + parameters.Parameters = params future, err := client.CreateOrUpdate(ctx, resourceGroupName, name, parameters) if err != nil { @@ -235,6 +242,12 @@ func resourceManagedApplicationRead(d *schema.ResourceData, meta interface{}) er d.Set("managed_resource_group_name", id.Name) d.Set("application_definition_id", props.ApplicationDefinitionID) + parameterValues, err := flattenManagedApplicationParameterValuesValueToString(props.Parameters) + if err != nil { + return fmt.Errorf("serializing JSON from `parameter_values`: %+v", err) + } + d.Set("parameter_values", parameterValues) + if err = d.Set("parameters", flattenManagedApplicationParametersOrOutputs(props.Parameters)); err != nil { return err } @@ -284,6 +297,34 @@ func expandManagedApplicationPlan(input []interface{}) *managedapplications.Plan } } +func expandManagedApplicationParameters(d *schema.ResourceData) (*map[string]interface{}, error) { + newParams := make(map[string]interface{}) + + if v, ok := d.GetOk("parameter_values"); ok { + if err := json.Unmarshal([]byte(v.(string)), &newParams); err != nil { + return nil, fmt.Errorf("unmarshalling `parameter_values`: %+v", err) + } + } + + if v, ok := d.GetOk("parameters"); ok { + params := v.(map[string]interface{}) + + if len(newParams) > 0 && len(params) > 0 { + return nil, fmt.Errorf("cannot set both `parameters` and `parameter_values`") + } + + for key, val := range params { + newParams[key] = struct { + Value interface{} `json:"value"` + }{ + Value: val, + } + } + } + + return &newParams, nil +} + func flattenManagedApplicationPlan(input *managedapplications.Plan) []interface{} { results := make([]interface{}, 0) if input == nil { @@ -330,9 +371,27 @@ func flattenManagedApplicationParametersOrOutputs(input interface{}) map[string] for k, v := range input.(map[string]interface{}) { if v != nil { - results[k] = v.(map[string]interface{})["value"].(string) + results[k] = fmt.Sprintf("%v", v.(map[string]interface{})["value"]) // map in terraform only accepts string as its values, therefore we have to convert the value to string } } return results } + +func flattenManagedApplicationParameterValuesValueToString(input interface{}) (string, error) { + if input == nil { + return "", nil + } + + result, err := json.Marshal(input.(map[string]interface{})) + if err != nil { + return "", err + } + + compactJson := bytes.Buffer{} + if err := json.Compact(&compactJson, result); err != nil { + return "", err + } + + return compactJson.String(), nil +} diff --git a/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go b/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go index 3ef98a588d3d..15c90a05642a 100644 --- a/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go +++ b/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go @@ -170,11 +170,14 @@ resource "azurerm_managed_application" "test" { managed_resource_group_name = "infraGroup%d" application_definition_id = azurerm_managed_application_definition.test.id - parameters = { - location = azurerm_resource_group.test.location - storageAccountNamePrefix = "store%s" - storageAccountType = "Standard_LRS" - } + parameter_values = < Date: Fri, 25 Sep 2020 23:30:55 +0800 Subject: [PATCH 2/6] Update code --- .../managed_application_resource.go | 8 ++++- .../managed_application_resource_test.go | 29 +++++++++---------- .../docs/r/managed_application.html.markdown | 8 ++--- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/azurerm/internal/services/managedapplications/managed_application_resource.go b/azurerm/internal/services/managedapplications/managed_application_resource.go index edf560165024..ca1e8a2f0549 100644 --- a/azurerm/internal/services/managedapplications/managed_application_resource.go +++ b/azurerm/internal/services/managedapplications/managed_application_resource.go @@ -383,7 +383,13 @@ func flattenManagedApplicationParameterValuesValueToString(input interface{}) (s return "", nil } - result, err := json.Marshal(input.(map[string]interface{})) + for k, v := range input.(map[string]interface{}) { + if v != nil { + delete(input.(map[string]interface{})[k].(map[string]interface{}), "type") + } + } + + result, err := json.Marshal(input) if err != nil { return "", err } diff --git a/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go b/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go index 15c90a05642a..4192ebc56312 100644 --- a/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go +++ b/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go @@ -172,10 +172,9 @@ resource "azurerm_managed_application" "test" { parameter_values = < Date: Fri, 25 Sep 2020 23:37:15 +0800 Subject: [PATCH 3/6] Update code --- .../tests/managed_application_resource_test.go | 4 ++-- website/docs/r/managed_application.html.markdown | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go b/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go index 4192ebc56312..e654c911acf0 100644 --- a/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go +++ b/azurerm/internal/services/managedapplications/tests/managed_application_resource_test.go @@ -172,7 +172,7 @@ resource "azurerm_managed_application" "test" { parameter_values = < Date: Mon, 26 Apr 2021 20:33:04 +0800 Subject: [PATCH 4/6] update code --- .../managed_application_resource.go | 20 +++-- .../managed_application_resource_test.go | 78 +++++++++++++------ .../docs/r/managed_application.html.markdown | 14 ++-- 3 files changed, 71 insertions(+), 41 deletions(-) diff --git a/azurerm/internal/services/managedapplications/managed_application_resource.go b/azurerm/internal/services/managedapplications/managed_application_resource.go index 266296aed448..9429d359f986 100644 --- a/azurerm/internal/services/managedapplications/managed_application_resource.go +++ b/azurerm/internal/services/managedapplications/managed_application_resource.go @@ -73,11 +73,12 @@ func resourceManagedApplication() *schema.Resource { ValidateFunc: validate.ApplicationDefinitionID, }, - "parameters": { // TODO -- remove this attribute after the deprecation - Type: schema.TypeMap, - Optional: true, - Computed: true, - Deprecated: "Deprecated in favour of `parameter_values`", + "parameters": { + Type: schema.TypeMap, + Optional: true, + Computed: true, + Deprecated: "Deprecated in favour of `parameter_values`", + ConflictsWith: []string{"parameter_values"}, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -86,9 +87,10 @@ func resourceManagedApplication() *schema.Resource { "parameter_values": { Type: schema.TypeString, Optional: true, - Computed: true, // TODO -- remove Computed after the deprecation + Computed: true, ValidateFunc: validation.StringIsJSON, DiffSuppressFunc: structure.SuppressJsonDiff, + ConflictsWith: []string{"parameters"}, }, "plan": { @@ -309,10 +311,6 @@ func expandManagedApplicationParameters(d *schema.ResourceData) (*map[string]int if v, ok := d.GetOk("parameters"); ok { params := v.(map[string]interface{}) - if len(newParams) > 0 && len(params) > 0 { - return nil, fmt.Errorf("cannot set both `parameters` and `parameter_values`") - } - for key, val := range params { newParams[key] = struct { Value interface{} `json:"value"` @@ -371,7 +369,7 @@ func flattenManagedApplicationParametersOrOutputs(input interface{}) map[string] for k, v := range input.(map[string]interface{}) { if v != nil { - results[k] = fmt.Sprintf("%v", v.(map[string]interface{})["value"]) // map in terraform only accepts string as its values, therefore we have to convert the value to string + results[k] = v.(map[string]interface{})["value"].(string) } } diff --git a/azurerm/internal/services/managedapplications/managed_application_resource_test.go b/azurerm/internal/services/managedapplications/managed_application_resource_test.go index cfac6e5c9280..b62790136ff6 100644 --- a/azurerm/internal/services/managedapplications/managed_application_resource_test.go +++ b/azurerm/internal/services/managedapplications/managed_application_resource_test.go @@ -94,6 +94,21 @@ func TestAccManagedApplication_update(t *testing.T) { }) } +func TestAccManagedApplication_parameterValues(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_managed_application", "test") + r := ManagedApplicationResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.parameterValues(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func (ManagedApplicationResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { id, err := parse.ApplicationID(state.ID) if err != nil { @@ -120,13 +135,11 @@ resource "azurerm_managed_application" "test" { managed_resource_group_name = "infraGroup%d" application_definition_id = azurerm_managed_application_definition.test.id - parameter_values = < Date: Mon, 26 Apr 2021 20:36:49 +0800 Subject: [PATCH 5/6] update code --- website/docs/r/managed_application.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/managed_application.html.markdown b/website/docs/r/managed_application.html.markdown index 09391000a7bd..92ddc476dc85 100644 --- a/website/docs/r/managed_application.html.markdown +++ b/website/docs/r/managed_application.html.markdown @@ -77,7 +77,7 @@ The following arguments are supported: * `parameters` - (Optional) A mapping of name and value pairs to pass to the managed application as parameters. -* `parameter_values` - (Optional) Parameter values to pass to the managed application. This field is a json object that allows you to assign parameters to this managed application. +* `parameter_values` - (Optional) The parameter values to pass to the Managed Application. This field is a json object that allows you to assign parameters to this Managed Application. * `plan` - (Optional) One `plan` block as defined below. From 1a2abac910d76d561a4884a35f90bee86eae2746 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Tue, 27 Apr 2021 11:05:23 +0800 Subject: [PATCH 6/6] update code --- .../managed_application_resource.go | 1 - .../managed_application_resource_test.go | 35 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/azurerm/internal/services/managedapplications/managed_application_resource.go b/azurerm/internal/services/managedapplications/managed_application_resource.go index 9429d359f986..e8106617bfec 100644 --- a/azurerm/internal/services/managedapplications/managed_application_resource.go +++ b/azurerm/internal/services/managedapplications/managed_application_resource.go @@ -77,7 +77,6 @@ func resourceManagedApplication() *schema.Resource { Type: schema.TypeMap, Optional: true, Computed: true, - Deprecated: "Deprecated in favour of `parameter_values`", ConflictsWith: []string{"parameter_values"}, Elem: &schema.Schema{ Type: schema.TypeString, diff --git a/azurerm/internal/services/managedapplications/managed_application_resource_test.go b/azurerm/internal/services/managedapplications/managed_application_resource_test.go index b62790136ff6..f610cf4b6928 100644 --- a/azurerm/internal/services/managedapplications/managed_application_resource_test.go +++ b/azurerm/internal/services/managedapplications/managed_application_resource_test.go @@ -94,6 +94,41 @@ func TestAccManagedApplication_update(t *testing.T) { }) } +func TestAccManagedApplication_updateParameters(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_managed_application", "test") + r := ManagedApplicationResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.basic(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("parameters.%").HasValue("3"), + check.That(data.ResourceName).Key("parameter_values").Exists(), + ), + }, + data.ImportStep(), + { + Config: r.parameterValues(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("parameters.%").Exists(), + check.That(data.ResourceName).Key("parameter_values").Exists(), + ), + }, + data.ImportStep(), + { + Config: r.basic(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("parameters.%").HasValue("3"), + check.That(data.ResourceName).Key("parameter_values").Exists(), + ), + }, + data.ImportStep(), + }) +} + func TestAccManagedApplication_parameterValues(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_managed_application", "test") r := ManagedApplicationResource{}