Skip to content

Commit 6321f14

Browse files
authored
fix(k8s): acls as a set to prevent ordering issues (#3241)
* fix(k8s): acls as a set to prevent ordering issues * use set check functions in the tests
1 parent b7d2af7 commit 6321f14

File tree

3 files changed

+2009
-20
lines changed

3 files changed

+2009
-20
lines changed

internal/services/k8s/acl.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func ResourceACL() *schema.Resource {
5151
ExactlyOneOf: []string{"acl_rules"},
5252
},
5353
"acl_rules": {
54-
Type: schema.TypeList,
54+
Type: schema.TypeSet,
5555
Optional: true,
5656
Description: "The list of network rules that manage inbound traffic",
5757
ExactlyOneOf: []string{"no_ip_allowed"},
@@ -104,7 +104,7 @@ func ResourceACLCreate(ctx context.Context, d *schema.ResourceData, m any) diag.
104104
return diag.FromErr(err)
105105
}
106106

107-
acls, err := expandACL(d.Get("acl_rules").([]any))
107+
acls, err := expandACL(d.Get("acl_rules"))
108108
if err != nil {
109109
return diag.FromErr(err)
110110
}
@@ -170,7 +170,7 @@ func ResourceACLUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.
170170
}
171171

172172
if d.HasChanges("acl_rules", "no_ip_allowed") {
173-
acls, err := expandACL(d.Get("acl_rules").([]any))
173+
acls, err := expandACL(d.Get("acl_rules"))
174174
if err != nil {
175175
return diag.FromErr(err)
176176
}
@@ -230,10 +230,14 @@ func ResourceACLDelete(ctx context.Context, d *schema.ResourceData, m any) diag.
230230
return nil
231231
}
232232

233-
func expandACL(data []any) ([]*k8s.ACLRuleRequest, error) {
233+
func expandACL(data any) ([]*k8s.ACLRuleRequest, error) {
234234
expandedACLs := []*k8s.ACLRuleRequest(nil)
235235

236-
for _, rule := range data {
236+
if data == nil {
237+
return expandedACLs, nil
238+
}
239+
240+
for _, rule := range data.(*schema.Set).List() {
237241
r := rule.(map[string]any)
238242
expandedRule := &k8s.ACLRuleRequest{}
239243

internal/services/k8s/acl_test.go

Lines changed: 127 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@ func TestAccACL_Basic(t *testing.T) {
4646
resource.TestCheckResourceAttrPair("scaleway_k8s_acl.acl_basic", "cluster_id", "scaleway_k8s_cluster.acl_basic", "id"),
4747
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "no_ip_allowed", "false"),
4848
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.#", "1"),
49-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.0.ip", "1.2.3.4/32"),
50-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.0.scaleway_ranges", "false"),
51-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.0.description", "First rule"),
49+
resource.TestCheckTypeSetElemNestedAttrs("scaleway_k8s_acl.acl_basic", "acl_rules.*", map[string]string{
50+
"ip": "1.2.3.4/32",
51+
"description": "First rule",
52+
"scaleway_ranges": "false",
53+
}),
5254
resource.TestCheckResourceAttrSet("scaleway_k8s_acl.acl_basic", "acl_rules.0.id"),
5355
),
5456
},
@@ -77,13 +79,17 @@ func TestAccACL_Basic(t *testing.T) {
7779
Check: resource.ComposeTestCheckFunc(
7880
resource.TestCheckResourceAttrPair("scaleway_k8s_acl.acl_basic", "cluster_id", "scaleway_k8s_cluster.acl_basic", "id"),
7981
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.#", "2"),
80-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.0.ip", "1.2.3.4/32"),
81-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.0.scaleway_ranges", "false"),
82-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.0.description", ""),
82+
resource.TestCheckTypeSetElemNestedAttrs("scaleway_k8s_acl.acl_basic", "acl_rules.*", map[string]string{
83+
"ip": "1.2.3.4/32",
84+
"description": "",
85+
"scaleway_ranges": "false",
86+
}),
87+
resource.TestCheckTypeSetElemNestedAttrs("scaleway_k8s_acl.acl_basic", "acl_rules.*", map[string]string{
88+
"ip": "5.6.7.0/30",
89+
"description": "",
90+
"scaleway_ranges": "false",
91+
}),
8392
resource.TestCheckResourceAttrSet("scaleway_k8s_acl.acl_basic", "acl_rules.0.id"),
84-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.1.ip", "5.6.7.0/30"),
85-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.1.scaleway_ranges", "false"),
86-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.1.description", ""),
8793
resource.TestCheckResourceAttrSet("scaleway_k8s_acl.acl_basic", "acl_rules.1.id"),
8894
),
8995
},
@@ -113,13 +119,17 @@ func TestAccACL_Basic(t *testing.T) {
113119
Check: resource.ComposeTestCheckFunc(
114120
resource.TestCheckResourceAttrPair("scaleway_k8s_acl.acl_basic", "cluster_id", "scaleway_k8s_cluster.acl_basic", "id"),
115121
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.#", "2"),
116-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.0.ip", "1.2.3.4/32"),
117-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.0.scaleway_ranges", "false"),
118-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.0.description", "First rule"),
122+
resource.TestCheckTypeSetElemNestedAttrs("scaleway_k8s_acl.acl_basic", "acl_rules.*", map[string]string{
123+
"ip": "1.2.3.4/32",
124+
"description": "First rule",
125+
"scaleway_ranges": "false",
126+
}),
127+
resource.TestCheckTypeSetElemNestedAttrs("scaleway_k8s_acl.acl_basic", "acl_rules.*", map[string]string{
128+
"ip": "",
129+
"description": "Scaleway ranges rule",
130+
"scaleway_ranges": "true",
131+
}),
119132
resource.TestCheckResourceAttrSet("scaleway_k8s_acl.acl_basic", "acl_rules.0.id"),
120-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.1.ip", ""),
121-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.1.scaleway_ranges", "true"),
122-
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_basic", "acl_rules.1.description", "Scaleway ranges rule"),
123133
resource.TestCheckResourceAttrSet("scaleway_k8s_acl.acl_basic", "acl_rules.1.id"),
124134
),
125135
},
@@ -165,6 +175,108 @@ func TestAccACL_Basic(t *testing.T) {
165175
})
166176
}
167177

178+
func TestAccACL_RulesOrder(t *testing.T) {
179+
tt := acctest.NewTestTools(t)
180+
defer tt.Cleanup()
181+
182+
clusterName := "k8s-acl-order"
183+
latestK8sVersion := testAccK8SClusterGetLatestK8SVersion(tt)
184+
185+
resource.ParallelTest(t, resource.TestCase{
186+
PreCheck: func() { acctest.PreCheck(t) },
187+
ProviderFactories: tt.ProviderFactories,
188+
CheckDestroy: testAccCheckK8SClusterDestroy(tt),
189+
Steps: []resource.TestStep{
190+
{
191+
Config: fmt.Sprintf(`
192+
resource "scaleway_vpc_private_network" "acl_order" {}
193+
194+
resource "scaleway_k8s_cluster" "acl_order" {
195+
name = "%s"
196+
version = "%s"
197+
cni = "cilium"
198+
delete_additional_resources = true
199+
private_network_id = scaleway_vpc_private_network.acl_order.id
200+
}
201+
202+
resource "scaleway_k8s_acl" "acl_order" {
203+
cluster_id = scaleway_k8s_cluster.acl_order.id
204+
acl_rules {
205+
ip = "12.2.3.4/32"
206+
description = "First rule"
207+
}
208+
acl_rules {
209+
ip = "11.2.3.4/32"
210+
description = "Second rule"
211+
}
212+
acl_rules {
213+
ip = "1.2.3.7/32"
214+
description = "Third rule"
215+
}
216+
acl_rules {
217+
ip = "1.2.3.4/32"
218+
description = "Fourth rule"
219+
}
220+
}`, clusterName, latestK8sVersion),
221+
Check: resource.ComposeTestCheckFunc(
222+
resource.TestCheckResourceAttrPair("scaleway_k8s_acl.acl_order", "cluster_id", "scaleway_k8s_cluster.acl_order", "id"),
223+
resource.TestCheckResourceAttr("scaleway_k8s_acl.acl_order", "acl_rules.#", "4"),
224+
resource.TestCheckTypeSetElemNestedAttrs("scaleway_k8s_acl.acl_order", "acl_rules.*", map[string]string{
225+
"ip": "12.2.3.4/32",
226+
"description": "First rule",
227+
}),
228+
resource.TestCheckTypeSetElemNestedAttrs("scaleway_k8s_acl.acl_order", "acl_rules.*", map[string]string{
229+
"ip": "11.2.3.4/32",
230+
"description": "Second rule",
231+
}),
232+
resource.TestCheckTypeSetElemNestedAttrs("scaleway_k8s_acl.acl_order", "acl_rules.*", map[string]string{
233+
"ip": "1.2.3.7/32",
234+
"description": "Third rule",
235+
}),
236+
resource.TestCheckTypeSetElemNestedAttrs("scaleway_k8s_acl.acl_order", "acl_rules.*", map[string]string{
237+
"ip": "1.2.3.4/32",
238+
"description": "Fourth rule",
239+
}),
240+
),
241+
},
242+
{
243+
Config: fmt.Sprintf(`
244+
resource "scaleway_vpc_private_network" "acl_order" {}
245+
246+
resource "scaleway_k8s_cluster" "acl_order" {
247+
name = "%s"
248+
version = "%s"
249+
cni = "cilium"
250+
delete_additional_resources = true
251+
private_network_id = scaleway_vpc_private_network.acl_order.id
252+
}
253+
254+
resource "scaleway_k8s_acl" "acl_order" {
255+
cluster_id = scaleway_k8s_cluster.acl_order.id
256+
acl_rules {
257+
ip = "12.2.3.4/32"
258+
description = "First rule"
259+
}
260+
acl_rules {
261+
ip = "11.2.3.4/32"
262+
description = "Second rule"
263+
}
264+
acl_rules {
265+
ip = "1.2.3.7/32"
266+
description = "Third rule"
267+
}
268+
acl_rules {
269+
ip = "1.2.3.4/32"
270+
description = "Fourth rule"
271+
}
272+
}`, clusterName, latestK8sVersion),
273+
PlanOnly: true,
274+
ExpectNonEmptyPlan: false,
275+
},
276+
},
277+
})
278+
}
279+
168280
func testAccCheckK8SClusterAllowedIPs(tt *acctest.TestTools, n string, expected string) resource.TestCheckFunc {
169281
return func(s *terraform.State) error {
170282
rs, ok := s.RootModule().Resources[n]

0 commit comments

Comments
 (0)