diff --git a/build/terraform b/build/terraform index 97e421ab926c..aa20a0efe764 160000 --- a/build/terraform +++ b/build/terraform @@ -1 +1 @@ -Subproject commit 97e421ab926c1d0b6d2b13f7fce183f374535477 +Subproject commit aa20a0efe7645f6710917a63ff7d7f764a0a183f diff --git a/products/compute/terraform.yaml b/products/compute/terraform.yaml index 8a04832a43f3..128ec41e3f28 100644 --- a/products/compute/terraform.yaml +++ b/products/compute/terraform.yaml @@ -657,6 +657,8 @@ overrides: !ruby/object:Provider::ResourceOverrides function: 'validateGCPName' secondaryIpRanges: !ruby/object:Provider::Terraform::PropertyOverride name: secondaryIpRange + unordered_list: true + default_from_api: true secondaryIpRanges.rangeName: !ruby/object:Provider::Terraform::PropertyOverride validation: !ruby/object:Provider::Terraform::Validation function: 'validateGCPName' diff --git a/provider/terraform/property_override.rb b/provider/terraform/property_override.rb index 71dbdb9bbb84..f026bf643dc9 100644 --- a/provider/terraform/property_override.rb +++ b/provider/terraform/property_override.rb @@ -24,6 +24,8 @@ module OverrideFields attr_reader :state_func # Adds a StateFunc to the schema attr_reader :sensitive # Adds `Sensitive: true` to the schema attr_reader :validation # Adds a ValidateFunc to the schema + # Indicates that this is an Array that should have Set diff semantics. + attr_reader :unordered_list attr_reader :is_set # Uses a Set instead of an Array # Optional function to determine the unique ID of an item in the set @@ -92,6 +94,7 @@ def validate # Ensures boolean values are set to false if nil @sensitive ||= false @is_set ||= false + @unordered_list ||= false @default_from_api ||= false check_property :sensitive, :boolean diff --git a/templates/terraform/resource.erb b/templates/terraform/resource.erb index 1e06c5747c3e..a67e98938032 100644 --- a/templates/terraform/resource.erb +++ b/templates/terraform/resource.erb @@ -36,6 +36,13 @@ func resource<%= resource_name -%>() *schema.Resource { Update: resource<%= resource_name -%>Update, <% end -%> Delete: resource<%= resource_name -%>Delete, + <% if settable_properties.any? {|p| p.unordered_list} && !object.custom_code.resource_definition -%> + CustomizeDiff: customdiff.All( + <%= settable_properties.select { |p| p.unordered_list } + .map { |p| "resource#{resource_name}#{Google::StringUtils.camelize(p.name, :upper)}SetStyleDiff"} + .join(",\n")-%> + ), + <% end -%> Importer: &schema.ResourceImporter{ State: resource<%= resource_name -%>Import, @@ -74,6 +81,13 @@ func resource<%= resource_name -%>() *schema.Resource { }, } } +<% settable_properties.select {|p| p.unordered_list}.each do |prop| -%> +func resource<%= resource_name -%><%= Google::StringUtils.camelize(prop.name, :upper) -%>SetStyleDiff(diff *schema.ResourceDiff, meta interface{}) error { +<%= compile_template('templates/terraform/unordered_list_customize_diff.erb', + prop: prop, + resource_name: resource_name) -%> +} +<% end -%> func resource<%= resource_name -%>Create(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) diff --git a/templates/terraform/resource_definition/subnetwork.erb b/templates/terraform/resource_definition/subnetwork.erb index 4164a77de9c0..b1d206878809 100644 --- a/templates/terraform/resource_definition/subnetwork.erb +++ b/templates/terraform/resource_definition/subnetwork.erb @@ -1,3 +1,4 @@ CustomizeDiff: customdiff.All( - customdiff.ForceNewIfChange("ip_cidr_range", isShrinkageIpCidr), + customdiff.ForceNewIfChange("ip_cidr_range", isShrinkageIpCidr), + resourceComputeSubnetworkSecondaryIpRangeSetStyleDiff, ), diff --git a/templates/terraform/unordered_list_customize_diff.erb b/templates/terraform/unordered_list_customize_diff.erb new file mode 100644 index 000000000000..f308e10d9459 --- /dev/null +++ b/templates/terraform/unordered_list_customize_diff.erb @@ -0,0 +1,39 @@ +keys := diff.GetChangedKeysPrefix(<%= go_literal(Google::StringUtils.underscore(prop.name)) -%>) +if len(keys) == 0 { + return nil +} +oldCount, newCount := diff.GetChange("<%= Google::StringUtils.underscore(prop.name) -%>.#") +var count int +// There could be duplicates - worth continuing even if the counts are unequal. +if oldCount.(int) < newCount.(int) { + count = newCount.(int) +} else { + count = oldCount.(int) +} + +if count < 1 { + return nil +} +old := make([]interface{}, count) +new := make([]interface{}, count) +for i := 0; i < count; i++ { + o, n := diff.GetChange(fmt.Sprintf("<%= Google::StringUtils.underscore(prop.name) -%>.%d", i)) + + if o != nil { + old = append(old, o) + } + if n != nil { + new = append(new, n) + } +} + +oldSet := schema.NewSet(schema.HashResource(resource<%= resource_name -%>().Schema[<%= go_literal(Google::StringUtils.underscore(prop.name)) -%>].Elem.(*schema.Resource)), old) +newSet := schema.NewSet(schema.HashResource(resource<%= resource_name -%>().Schema[<%= go_literal(Google::StringUtils.underscore(prop.name)) -%>].Elem.(*schema.Resource)), new) + +if oldSet.Equal(newSet) { + if err := diff.Clear(<%= go_literal(Google::StringUtils.underscore(prop.name)) -%>); err != nil { + return err + } +} + +return nil