Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug Fix - azurerm_api_management_api_operation] - Handling example.value none-string types #14848

Merged
merged 4 commits into from
Apr 7, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,18 @@ func resourceApiManagementApiOperationRead(d *pluginsdk.ResourceData, meta inter
d.Set("method", props.Method)
d.Set("url_template", props.URLTemplate)

flattenedRequest := flattenApiManagementOperationRequestContract(props.Request)
flattenedRequest, err := flattenApiManagementOperationRequestContract(props.Request)
if err != nil {
return err
}
if err := d.Set("request", flattenedRequest); err != nil {
return fmt.Errorf("flattening `request`: %+v", err)
}

flattenedResponse := flattenApiManagementOperationResponseContract(props.Responses)
flattenedResponse, err := flattenApiManagementOperationResponseContract(props.Responses)
if err != nil {
return err
}
if err := d.Set("response", flattenedResponse); err != nil {
return fmt.Errorf("flattening `response`: %+v", err)
}
Expand Down Expand Up @@ -284,9 +290,9 @@ func expandApiManagementOperationRequestContract(d *pluginsdk.ResourceData, sche
}, nil
}

func flattenApiManagementOperationRequestContract(input *apimanagement.RequestContract) []interface{} {
func flattenApiManagementOperationRequestContract(input *apimanagement.RequestContract) ([]interface{}, error) {
if input == nil {
return []interface{}{}
return []interface{}{}, nil
}

output := make(map[string]interface{})
Expand All @@ -297,9 +303,13 @@ func flattenApiManagementOperationRequestContract(input *apimanagement.RequestCo

output["header"] = schemaz.FlattenApiManagementOperationParameterContract(input.Headers)
output["query_parameter"] = schemaz.FlattenApiManagementOperationParameterContract(input.QueryParameters)
output["representation"] = schemaz.FlattenApiManagementOperationRepresentation(input.Representations)
representation, err := schemaz.FlattenApiManagementOperationRepresentation(input.Representations)
if err != nil {
return nil, err
}
output["representation"] = representation

return []interface{}{output}
return []interface{}{output}, nil
}

func expandApiManagementOperationResponseContract(d *pluginsdk.ResourceData, schemaPath string, input []interface{}) (*[]apimanagement.ResponseContract, error) {
Expand Down Expand Up @@ -337,9 +347,9 @@ func expandApiManagementOperationResponseContract(d *pluginsdk.ResourceData, sch
return &outputs, nil
}

func flattenApiManagementOperationResponseContract(input *[]apimanagement.ResponseContract) []interface{} {
func flattenApiManagementOperationResponseContract(input *[]apimanagement.ResponseContract) ([]interface{}, error) {
if input == nil {
return []interface{}{}
return []interface{}{}, nil
}

outputs := make([]interface{}, 0)
Expand All @@ -356,10 +366,15 @@ func flattenApiManagementOperationResponseContract(input *[]apimanagement.Respon
}

output["header"] = schemaz.FlattenApiManagementOperationParameterContract(v.Headers)
output["representation"] = schemaz.FlattenApiManagementOperationRepresentation(v.Representations)

representation, err := schemaz.FlattenApiManagementOperationRepresentation(v.Representations)
if err != nil {
return nil, err
}
output["representation"] = representation

outputs = append(outputs, output)
}

return outputs
return outputs, nil
}
81 changes: 65 additions & 16 deletions internal/services/apimanagement/schemaz/api_management.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package schemaz

import (
"encoding/json"
"fmt"
"reflect"
"strings"

"github.com/hashicorp/terraform-provider-azurerm/internal/features"

"github.com/Azure/azure-sdk-for-go/services/apimanagement/mgmt/2021-08-01/apimanagement"
"github.com/hashicorp/terraform-provider-azurerm/internal/features"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/apimanagement/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
Expand Down Expand Up @@ -180,9 +181,9 @@ func ExpandApiManagementOperationRepresentation(d *pluginsdk.ResourceData, schem
return &outputs, nil
}

func FlattenApiManagementOperationRepresentation(input *[]apimanagement.RepresentationContract) []interface{} {
func FlattenApiManagementOperationRepresentation(input *[]apimanagement.RepresentationContract) ([]interface{}, error) {
if input == nil {
return []interface{}{}
return []interface{}{}, nil
}

outputs := make([]interface{}, 0)
Expand All @@ -197,10 +198,18 @@ func FlattenApiManagementOperationRepresentation(input *[]apimanagement.Represen
output["form_parameter"] = FlattenApiManagementOperationParameterContract(v.FormParameters)

if v.Examples != nil {
output["example"] = FlattenApiManagementOperationParameterExampleContract(v.Examples)

if features.ThreePointOhBeta() && v.Examples["default"] != nil && v.Examples["default"].Value != nil {
output["sample"] = v.Examples["default"].Value.(string)
example, err := FlattenApiManagementOperationParameterExampleContract(v.Examples)
if err != nil {
return nil, err
}
output["example"] = example

if !features.ThreePointOhBeta() && v.Examples["default"] != nil && v.Examples["default"].Value != nil {
value, err := convert2Json(v.Examples["default"].Value)
if err != nil {
return nil, err
}
output["sample"] = value
}
}

Expand All @@ -215,7 +224,7 @@ func FlattenApiManagementOperationRepresentation(input *[]apimanagement.Represen
outputs = append(outputs, output)
}

return outputs
return outputs, nil
}

func SchemaApiManagementOperationParameterContract() *pluginsdk.Schema {
Expand Down Expand Up @@ -355,8 +364,9 @@ func SchemaApiManagementOperationParameterExampleContract() *pluginsdk.Schema {
},

"value": {
Type: pluginsdk.TypeString,
Optional: true,
Type: pluginsdk.TypeString,
Optional: true,
DiffSuppressFunc: exampleSuppressEquivalentJSONDiffs,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
DiffSuppressFunc: exampleSuppressEquivalentJSONDiffs,
DiffSuppressFunc: pluginsdk.SuppressJsonDiff,

},

"external_value": {
Expand Down Expand Up @@ -392,7 +402,12 @@ func ExpandApiManagementOperationParameterExampleContract(input []interface{}) m
}

if vs["value"] != nil {
outputs[name].Value = utils.String(vs["value"].(string))
var js interface{}
if json.Unmarshal([]byte(vs["value"].(string)), &js) == nil {
outputs[name].Value = js
} else {
outputs[name].Value = utils.String(vs["value"].(string))
}
}

if vs["external_value"] != nil {
Expand All @@ -403,9 +418,9 @@ func ExpandApiManagementOperationParameterExampleContract(input []interface{}) m
return outputs
}

func FlattenApiManagementOperationParameterExampleContract(input map[string]*apimanagement.ParameterExampleContract) []interface{} {
func FlattenApiManagementOperationParameterExampleContract(input map[string]*apimanagement.ParameterExampleContract) ([]interface{}, error) {
if input == nil {
return []interface{}{}
return []interface{}{}, nil
}

outputs := make([]interface{}, 0)
Expand All @@ -422,8 +437,14 @@ func FlattenApiManagementOperationParameterExampleContract(input map[string]*api
output["description"] = *v.Description
}

// value can be any type, may be a primitive value or an object
// https://github.com/Azure/azure-sdk-for-go/blob/main/services/apimanagement/mgmt/2021-08-01/apimanagement/models.go#L10236
if v.Value != nil {
output["value"] = v.Value.(string)
value, err := convert2Json(v.Value)
if err != nil {
return nil, err
}
output["value"] = value
}

if v.ExternalValue != nil {
Expand All @@ -433,7 +454,7 @@ func FlattenApiManagementOperationParameterExampleContract(input map[string]*api
outputs = append(outputs, output)
}

return outputs
return outputs, nil
}

// CopyCertificateAndPassword copies any certificate and password attributes
Expand All @@ -452,3 +473,31 @@ func CopyCertificateAndPassword(vals []interface{}, hostName string, output map[
}
}
}

func convert2Json(rawVal interface{}) (string, error) {
value := ""
if val, ok := rawVal.(string); ok {
value = val
} else {
val, err := json.Marshal(rawVal)
if err != nil {
return "", fmt.Errorf("failed to marshal `representations.examples.value` to json: %+v", err)
}
value = string(val)
}
return value, nil
}

func exampleSuppressEquivalentJSONDiffs(k, old, new string, d *pluginsdk.ResourceData) bool {
var ojs interface{}
if json.Unmarshal([]byte(old), &ojs) != nil {
return strings.Compare(old, new) == 0
}

var njs interface{}
if json.Unmarshal([]byte(new), &njs) != nil {
return strings.Compare(old, new) == 0
}

return reflect.DeepEqual(ojs, njs)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an existing diff suppress func for JSONs in the provider.

Suggested change
func exampleSuppressEquivalentJSONDiffs(k, old, new string, d *pluginsdk.ResourceData) bool {
var ojs interface{}
if json.Unmarshal([]byte(old), &ojs) != nil {
return strings.Compare(old, new) == 0
}
var njs interface{}
if json.Unmarshal([]byte(new), &njs) != nil {
return strings.Compare(old, new) == 0
}
return reflect.DeepEqual(ojs, njs)
}