ignore the order of the elements in a list (#455)
This commit is contained in:
Родитель
388e86e417
Коммит
1a5e281f85
|
@ -14,6 +14,7 @@ ENHANCEMENTS:
|
|||
- `azapi_resource` resource, `azapi_update_resource` resource, `azapi_resource_action` resource, `azapi_data_plane_resource` resource, `azapi_resource_action` data source, `azapi_resource` data source, `azapi_resource_list` data source: The `output` field supports the dynamic schema and allows user to read the output as an HCL object.
|
||||
- `azapi` provider: Support `client_id_file_path`and `client_secret_file_path` fields, which are used to specify the file path of the client id and client secret.
|
||||
- `azapi_data_plane_resource` resource: Support `Microsoft.Synapse/workspaces/databases` type.
|
||||
- `azapi_resource` resource, `azapi_update_resource` resource: Ignore the order of the elements in a list if the element has a `name` field as identifier.
|
||||
|
||||
BUG FIXES:
|
||||
- Fix a bug that `azapi_resource_action` doesn't support 204 status code as a success response.
|
||||
|
|
|
@ -129,6 +129,20 @@ func TestAccGenericUpdateResource_ignoreChangesArray(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccGenericUpdateResource_ignoreOrderInArray(t *testing.T) {
|
||||
data := acceptance.BuildTestData(t, "azapi_update_resource", "test")
|
||||
r := GenericUpdateResource{}
|
||||
|
||||
data.ResourceTest(t, r, []resource.TestStep{
|
||||
{
|
||||
Config: r.ignoreOrderInArray(data),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
check.That(data.ResourceName).ExistsInAzure(r),
|
||||
),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (r GenericUpdateResource) Exists(ctx context.Context, client *clients.Client, state *terraform.InstanceState) (*bool, error) {
|
||||
resourceType := state.Attributes["type"]
|
||||
id, err := parse.ResourceIDWithResourceType(state.ID, resourceType)
|
||||
|
@ -372,6 +386,69 @@ resource "azapi_update_resource" "test" {
|
|||
`, r.template(data), data.RandomInt())
|
||||
}
|
||||
|
||||
func (r GenericUpdateResource) ignoreOrderInArray(data acceptance.TestData) string {
|
||||
return fmt.Sprintf(`
|
||||
%[1]s
|
||||
|
||||
resource "azapi_resource" "vnet" {
|
||||
type = "Microsoft.Network/virtualNetworks@2023-09-01"
|
||||
parent_id = azurerm_resource_group.test.id
|
||||
name = "acctest%[2]d"
|
||||
location = azurerm_resource_group.test.location
|
||||
body = {
|
||||
properties = {
|
||||
addressSpace = {
|
||||
addressPrefixes = [
|
||||
"10.0.0.0/16",
|
||||
]
|
||||
}
|
||||
dhcpOptions = {
|
||||
dnsServers = [
|
||||
]
|
||||
}
|
||||
subnets = [
|
||||
{
|
||||
name = "first"
|
||||
properties = {
|
||||
addressPrefix = "10.0.3.0/24"
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "second"
|
||||
properties = {
|
||||
addressPrefix = "10.0.4.0/24"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "azapi_update_resource" "test" {
|
||||
type = "Microsoft.Network/virtualNetworks@2022-07-01"
|
||||
resource_id = azapi_resource.vnet.id
|
||||
body = {
|
||||
properties = {
|
||||
subnets = [
|
||||
{
|
||||
name = "second"
|
||||
properties = {
|
||||
addressPrefix = "10.0.4.0/24"
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "first"
|
||||
properties = {
|
||||
addressPrefix = "10.0.3.0/24"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
`, r.template(data), data.RandomInt())
|
||||
}
|
||||
|
||||
func (GenericUpdateResource) template(data acceptance.TestData) string {
|
||||
return fmt.Sprintf(`
|
||||
terraform {
|
||||
|
|
|
@ -81,12 +81,23 @@ func UpdateObject(old interface{}, new interface{}, option UpdateJsonOption) int
|
|||
}
|
||||
case []interface{}:
|
||||
if newArr, ok := new.([]interface{}); ok {
|
||||
if len(oldValue) != len(newArr) {
|
||||
return newArr
|
||||
}
|
||||
res := make([]interface{}, 0)
|
||||
for index := range oldValue {
|
||||
res = append(res, UpdateObject(oldValue[index], newArr[index], option))
|
||||
used := make([]bool, len(newArr))
|
||||
|
||||
for _, oldItem := range oldValue {
|
||||
for index, newItem := range newArr {
|
||||
if areSameArrayItems(oldItem, newItem) {
|
||||
res = append(res, UpdateObject(oldItem, newItem, option))
|
||||
used[index] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for index, newItem := range newArr {
|
||||
if !used[index] {
|
||||
res = append(res, newItem)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
@ -103,6 +114,31 @@ func UpdateObject(old interface{}, new interface{}, option UpdateJsonOption) int
|
|||
return new
|
||||
}
|
||||
|
||||
func areSameArrayItems(a, b interface{}) bool {
|
||||
aId := identifierOfArrayItem(a)
|
||||
bId := identifierOfArrayItem(b)
|
||||
if aId == "" || bId == "" {
|
||||
return false
|
||||
}
|
||||
return aId == bId
|
||||
}
|
||||
|
||||
func identifierOfArrayItem(input interface{}) string {
|
||||
inputMap, ok := input.(map[string]interface{})
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
name := inputMap["name"]
|
||||
if name == nil {
|
||||
return ""
|
||||
}
|
||||
nameValue, ok := name.(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return nameValue
|
||||
}
|
||||
|
||||
// ExtractObject is used to extract object from old for a json path
|
||||
func ExtractObject(old interface{}, path string) interface{} {
|
||||
if len(path) == 0 {
|
||||
|
|
|
@ -17,6 +17,125 @@ func Test_UpdateObject(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
OldJson: `
|
||||
{
|
||||
"properties": {
|
||||
"addressSpace": {
|
||||
"addressPrefixes": [
|
||||
"10.0.0.0/16"
|
||||
]
|
||||
},
|
||||
"dhcpOptions": {
|
||||
"dnsServers": null
|
||||
},
|
||||
"subnets": [
|
||||
{
|
||||
"name": "default",
|
||||
"properties": {
|
||||
"addressPrefix": "10.0.3.0/24"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`,
|
||||
NewJson: `
|
||||
{
|
||||
"etag": "W/\"5633f421-aaa4-4cf3-b9a6-40625807bd75\"",
|
||||
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/henglu422/providers/Microsoft.Network/virtualNetworks/henglu422",
|
||||
"location": "westus",
|
||||
"name": "henglu422",
|
||||
"properties": {
|
||||
"addressSpace": {
|
||||
"addressPrefixes": [
|
||||
"10.0.0.0/16"
|
||||
]
|
||||
},
|
||||
"dhcpOptions": {
|
||||
"dnsServers": []
|
||||
},
|
||||
"enableDdosProtection": false,
|
||||
"provisioningState": "Succeeded",
|
||||
"resourceGuid": "86ec5186-a958-4b83-b5e7-3b88a728c34c",
|
||||
"subnets": [
|
||||
{
|
||||
"etag": "W/\"5633f421-aaa4-4cf3-b9a6-40625807bd75\"",
|
||||
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/henglu422/providers/Microsoft.Network/virtualNetworks/henglu422/subnets/henglu422",
|
||||
"name": "henglu422",
|
||||
"properties": {
|
||||
"addressPrefix": "10.0.2.0/24",
|
||||
"delegations": [],
|
||||
"networkSecurityGroup": {
|
||||
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/henglu422/providers/Microsoft.Network/networkSecurityGroups/NRMS-zpedr2ai6dglmhenglu422"
|
||||
},
|
||||
"privateEndpointNetworkPolicies": "Disabled",
|
||||
"privateLinkServiceNetworkPolicies": "Enabled",
|
||||
"provisioningState": "Succeeded"
|
||||
},
|
||||
"type": "Microsoft.Network/virtualNetworks/subnets"
|
||||
},
|
||||
{
|
||||
"etag": "W/\"5633f421-aaa4-4cf3-b9a6-40625807bd75\"",
|
||||
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/henglu422/providers/Microsoft.Network/virtualNetworks/henglu422/subnets/default",
|
||||
"name": "default",
|
||||
"properties": {
|
||||
"addressPrefix": "10.0.3.0/24",
|
||||
"delegations": [],
|
||||
"networkSecurityGroup": {
|
||||
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/henglu422/providers/Microsoft.Network/networkSecurityGroups/NRMS-zpedr2ai6dglmhenglu422"
|
||||
},
|
||||
"privateEndpointNetworkPolicies": "Disabled",
|
||||
"privateLinkServiceNetworkPolicies": "Enabled",
|
||||
"provisioningState": "Succeeded"
|
||||
},
|
||||
"type": "Microsoft.Network/virtualNetworks/subnets"
|
||||
}
|
||||
],
|
||||
"virtualNetworkPeerings": []
|
||||
},
|
||||
"type": "Microsoft.Network/virtualNetworks"
|
||||
}
|
||||
`,
|
||||
ExpectJson: `
|
||||
{
|
||||
"properties": {
|
||||
"addressSpace": {
|
||||
"addressPrefixes": [
|
||||
"10.0.0.0/16"
|
||||
]
|
||||
},
|
||||
"dhcpOptions": {
|
||||
"dnsServers": []
|
||||
},
|
||||
"subnets": [
|
||||
{
|
||||
"name": "default",
|
||||
"properties": {
|
||||
"addressPrefix": "10.0.3.0/24"
|
||||
}
|
||||
},
|
||||
{
|
||||
"etag": "W/\"5633f421-aaa4-4cf3-b9a6-40625807bd75\"",
|
||||
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/henglu422/providers/Microsoft.Network/virtualNetworks/henglu422/subnets/henglu422",
|
||||
"name": "henglu422",
|
||||
"properties": {
|
||||
"addressPrefix": "10.0.2.0/24",
|
||||
"delegations": [],
|
||||
"networkSecurityGroup": {
|
||||
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/henglu422/providers/Microsoft.Network/networkSecurityGroups/NRMS-zpedr2ai6dglmhenglu422"
|
||||
},
|
||||
"privateEndpointNetworkPolicies": "Disabled",
|
||||
"privateLinkServiceNetworkPolicies": "Enabled",
|
||||
"provisioningState": "Succeeded"
|
||||
},
|
||||
"type": "Microsoft.Network/virtualNetworks/subnets"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
OldJson: `
|
||||
{
|
||||
"properties": {
|
||||
"compression": "None",
|
||||
|
|
Загрузка…
Ссылка в новой задаче