Skip to content

Commit

Permalink
Apply case-spacing-insensitive diffing to all location properties (#2281
Browse files Browse the repository at this point in the history
)

All `location` properties in Azure are case- and space- insensitive, so
both "West Europe" and "westeurope" are valid values representing the
same region.

This PR adjusts our diff calculation logic with this special rule. We
get a diff calculated by vanilla platform diffing, then we check if
there is an Update to the property called `location`, and if so, it
normalizes both values and compares those. Any non-significant changes
are ignored.

Fix #1809
Fix #1005
  • Loading branch information
mikhailshilkov committed Mar 3, 2023
1 parent 21a1c47 commit d6346cb
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 0 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,11 @@

## HEAD (Unreleased)

### Enhancements

- Treat location as case- and spacing-insensitive while calculating resource diffs
[#2281](https://github.com/pulumi/pulumi-azure-native/pull/2281)

## 1.96.0 (2023-02-24)

- New resource providers `networkcloud` (API version _2022-12-12-preview_) and `resourcehealth` (API version _2022-10-01-preview_).
Expand Down
25 changes: 25 additions & 0 deletions provider/pkg/provider/diff.go
Expand Up @@ -53,6 +53,8 @@ func calculateDetailedDiff(resource *resources.AzureAPIResource, types resources
}
}

applyAzureSpecificDiff(diff)

d := differ{replaceKeys: replaceKeys}
return d.calculateObjectDiff(diff, "", "")
}
Expand Down Expand Up @@ -162,3 +164,26 @@ func applyDiff(values resource.PropertyMap, diff *resource.ObjectDiff) resource.
}
return result
}

// applyAzureSpecificDiff modifies a generic diff calculated by the Platform with any
// Azure-specific diffing adjustments.
func applyAzureSpecificDiff(diff *resource.ObjectDiff) {
updates := map[resource.PropertyKey]resource.ValueDiff{}
for k, v := range diff.Updates {
// Apply special diffing logic to top-level properties called "location".
// Those are special in the sense that casing and spaces are not significant.
if string(k) == "location" && v.Old.IsString() && v.New.IsString() {
if normalizedLocation(v.Old.StringValue()) == normalizedLocation(v.New.StringValue()) {
continue
}
}
updates[k] = v
}
diff.Updates = updates
}

// normalizedLocation converts Azure location values of a format like "West US 2" and
// "WestUS2" to the lowercase and no-space format of "westus2".
func normalizedLocation(location string) string {
return strings.ToLower(strings.ReplaceAll(location, " ", ""))
}
39 changes: 39 additions & 0 deletions provider/pkg/provider/diff_test.go
Expand Up @@ -31,6 +31,7 @@ func TestCalculateDiffBodyProperties(t *testing.T) {
"p6": {Type: "array", Items: &resources.AzureAPIProperty{
Ref: "#/types/azure-native:foobar/v20200101:SomeType",
}},
"location": {Type: "string"},
},
},
},
Expand Down Expand Up @@ -103,6 +104,10 @@ func TestCalculateDiffBodyProperties(t *testing.T) {
},
},
},
"location": {
Old: resource.PropertyValue{V: "East US"},
New: resource.PropertyValue{V: "East US 2"},
},
},
Adds: map[resource.PropertyKey]resource.PropertyValue{
"p2": {V: 123},
Expand All @@ -126,6 +131,7 @@ func TestCalculateDiffBodyProperties(t *testing.T) {
"p5[2]": {Kind: rpc.PropertyDiff_DELETE},
"p6[0].p61": {Kind: rpc.PropertyDiff_UPDATE},
"p6[0].p62": {Kind: rpc.PropertyDiff_ADD},
"location": {Kind: rpc.PropertyDiff_UPDATE},
}
assert.Equal(t, expected, actual)
}
Expand Down Expand Up @@ -322,3 +328,36 @@ func TestApplyDiff(t *testing.T) {
}
assert.Equal(t, expected, actual)
}

func TestLocationDiffingIsInsensitiveToSpacesAndCasing(t *testing.T) {
res := resources.AzureAPIResource{
PutParameters: []resources.AzureAPIParameter{
{
Location: "body",
Name: "bodyProperties",
Body: &resources.AzureAPIType{
Properties: map[string]resources.AzureAPIProperty{
"location": {Type: "string"},
},
},
},
},
}
variantsSame := []string{"West US 2", "WestUS2", "west us 2", "westus2"}
for _, oldValue := range variantsSame {
for _, newValue := range variantsSame {
diff := resource.ObjectDiff{
Updates: map[resource.PropertyKey]resource.ValueDiff{
"location": {
Old: resource.PropertyValue{V: oldValue},
New: resource.PropertyValue{V: newValue},
},
},
}
emptyTypes := resources.NewPartialMap[resources.AzureAPIType]()
actual := calculateDetailedDiff(&res, &emptyTypes, &diff)
expected := map[string]*rpc.PropertyDiff{}
assert.Equal(t, expected, actual)
}
}
}

0 comments on commit d6346cb

Please sign in to comment.