Skip to content

Commit e1caad4

Browse files
fix: string based ordering for google_compute_region_security_policy causes recreate after apply (#14093) (#10105)
[upstream:f55da64d5c5a549bb0da32e383922adb75d79fe7] Signed-off-by: Modular Magician <[email protected]>
1 parent 0c20c44 commit e1caad4

File tree

3 files changed

+149
-4
lines changed

3 files changed

+149
-4
lines changed

.changelog/14093.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:bug
2+
compute: fixed an issue where rules ordering in `google_compute_region_security_policy` caused a diff after apply
3+
```

google-beta/services/compute/resource_compute_region_security_policy.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,35 @@ import (
3535
"github.com/hashicorp/terraform-provider-google-beta/google-beta/verify"
3636
)
3737

38+
func resourceComputeRegionSecurityPolicySpecRulesDiffSuppress(k, o, n string, d *schema.ResourceData) bool {
39+
oldCount, newCount := d.GetChange("rules.#")
40+
var count int
41+
// There could be duplicates - worth continuing even if the counts are unequal.
42+
if oldCount.(int) < newCount.(int) {
43+
count = newCount.(int)
44+
} else {
45+
count = oldCount.(int)
46+
}
47+
48+
old := make([]interface{}, 0, count)
49+
new := make([]interface{}, 0, count)
50+
for i := 0; i < count; i++ {
51+
o, n := d.GetChange(fmt.Sprintf("rules.%d", i))
52+
53+
if o != nil {
54+
old = append(old, o)
55+
}
56+
if n != nil {
57+
new = append(new, n)
58+
}
59+
}
60+
61+
oldSet := schema.NewSet(schema.HashResource(ResourceComputeRegionSecurityPolicy().Schema["rules"].Elem.(*schema.Resource)), old)
62+
newSet := schema.NewSet(schema.HashResource(ResourceComputeRegionSecurityPolicy().Schema["rules"].Elem.(*schema.Resource)), new)
63+
64+
return oldSet.Equal(newSet)
65+
}
66+
3867
func ResourceComputeRegionSecurityPolicy() *schema.Resource {
3968
return &schema.Resource{
4069
Create: resourceComputeRegionSecurityPolicyCreate,
@@ -98,10 +127,11 @@ Specifically, the name must be 1-63 characters long and match the regular expres
98127
If it is not provided, the provider region is used.`,
99128
},
100129
"rules": {
101-
Type: schema.TypeList,
102-
Computed: true,
103-
Optional: true,
104-
Description: `The set of rules that belong to this policy. There must always be a default rule (rule with priority 2147483647 and match "*"). If no rules are provided when creating a security policy, a default rule with action "allow" will be added.`,
130+
Type: schema.TypeList,
131+
Computed: true,
132+
Optional: true,
133+
DiffSuppressFunc: resourceComputeRegionSecurityPolicySpecRulesDiffSuppress,
134+
Description: `The set of rules that belong to this policy. There must always be a default rule (rule with priority 2147483647 and match "*"). If no rules are provided when creating a security policy, a default rule with action "allow" will be added.`,
105135
Elem: &schema.Resource{
106136
Schema: map[string]*schema.Schema{
107137
"action": {

google-beta/services/compute/resource_compute_region_security_policy_test.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,118 @@ func testAccComputeRegionSecurityPolicy_withMultipleEnforceOnKeyConfigs_update(c
735735
}
736736
`, context)
737737
}
738+
739+
func TestAccComputeRegionSecurityPolicy_regionSecurityPolicyRuleOrderingWithMultipleRules(t *testing.T) {
740+
t.Parallel()
741+
742+
context := map[string]interface{}{
743+
"random_suffix": acctest.RandString(t, 10),
744+
}
745+
746+
acctest.VcrTest(t, resource.TestCase{
747+
PreCheck: func() { acctest.AccTestPreCheck(t) },
748+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
749+
CheckDestroy: testAccCheckComputeRegionSecurityPolicyDestroyProducer(t),
750+
Steps: []resource.TestStep{
751+
{
752+
Config: testAccComputeRegionSecurityPolicy_ruleOrderingWithMultipleRules_create(context),
753+
},
754+
{
755+
ResourceName: "google_compute_region_security_policy.policy",
756+
ImportState: true,
757+
ImportStateVerify: true,
758+
},
759+
{
760+
Config: testAccComputeRegionSecurityPolicy_ruleOrderingWithMultipleRules_update(context),
761+
},
762+
{
763+
ResourceName: "google_compute_region_security_policy.policy",
764+
ImportState: true,
765+
ImportStateVerify: true,
766+
},
767+
},
768+
})
769+
}
770+
771+
func testAccComputeRegionSecurityPolicy_ruleOrderingWithMultipleRules_create(context map[string]interface{}) string {
772+
return acctest.Nprintf(`
773+
774+
resource "google_compute_region_security_policy" "policy" {
775+
name = "tf-test-ordering%{random_suffix}"
776+
description = "basic region security policy with multiple rules"
777+
type = "CLOUD_ARMOR"
778+
region = "us-central1"
779+
780+
rules {
781+
action = "deny"
782+
priority = "3000"
783+
match {
784+
expr {
785+
expression = "request.path.matches(\"/login.html\") && token.recaptcha_session.score < 0.2"
786+
}
787+
}
788+
}
789+
790+
rules {
791+
action = "deny"
792+
priority = "2147483647"
793+
match {
794+
versioned_expr = "SRC_IPS_V1"
795+
config {
796+
src_ip_ranges = ["*"]
797+
}
798+
}
799+
description = "default rule"
800+
}
801+
}
802+
803+
`, context)
804+
}
805+
806+
func testAccComputeRegionSecurityPolicy_ruleOrderingWithMultipleRules_update(context map[string]interface{}) string {
807+
return acctest.Nprintf(`
808+
809+
resource "google_compute_region_security_policy" "policy" {
810+
name = "tf-test-ordering%{random_suffix}"
811+
description = "basic region security policy with multiple rules, updated"
812+
type = "CLOUD_ARMOR"
813+
region = "us-central1"
814+
815+
rules {
816+
action = "allow"
817+
priority = "4000"
818+
match {
819+
expr {
820+
expression = "request.path.matches(\"/login.html\") && token.recaptcha_session.score < 0.2"
821+
}
822+
}
823+
}
824+
825+
rules {
826+
action = "allow"
827+
priority = "5000"
828+
match {
829+
expr {
830+
expression = "request.path.matches(\"/404.html\") && token.recaptcha_session.score > 0.4"
831+
}
832+
}
833+
description = "new rule"
834+
}
835+
836+
rules {
837+
action = "deny"
838+
priority = "2147483647"
839+
match {
840+
versioned_expr = "SRC_IPS_V1"
841+
config {
842+
src_ip_ranges = ["*"]
843+
}
844+
}
845+
description = "default rule"
846+
}
847+
}
848+
`, context)
849+
}
738850
func TestAccComputeRegionSecurityPolicy_regionSecurityPolicyWithRulesNetworkMatch(t *testing.T) {
739851
t.Parallel()
740852

0 commit comments

Comments
 (0)