Skip to content

Commit 618ebe7

Browse files
authored
feat(k8s): integrate public_ip_disabled field (#2157)
* feat(k8s): integrate `public_ip_disabled` field to the provider * doc(k8s): integrate `public_ip_disabled` field * test(k8s): add test for `public_ip_disabled` field
1 parent c74497f commit 618ebe7

File tree

4 files changed

+7563
-11
lines changed

4 files changed

+7563
-11
lines changed

docs/resources/k8s_pool.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ The following arguments are supported:
8383

8484
- `region` - (Defaults to [provider](../index.md#region) `region`) The [region](../guides/regions_and_zones.md#regions) in which the pool should be created.
8585

86-
- `wait_for_pool_ready` - (Default to `false`) Whether to wait for the pool to be ready.
86+
- `wait_for_pool_ready` - (Defaults to `false`) Whether to wait for the pool to be ready.
87+
88+
- `public_ip_disabled` - (Defaults to `false`) Defines if the public IP should be removed from Nodes. To use this feature, your Cluster must have an attached [Private Network](vpc_private_network.md) set up with a [Public Gateway](vpc_public_gateway.md).
89+
~> **Important:** Updates to this field will recreate a new resource.
8790

8891
## Attributes Reference
8992

scaleway/resource_k8s_pool.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,13 @@ func resourceScalewayK8SPool() *schema.Resource {
156156
ForceNew: true,
157157
Description: "The size of the system volume of the nodes in gigabyte",
158158
},
159+
"public_ip_disabled": {
160+
Type: schema.TypeBool,
161+
Optional: true,
162+
Default: false,
163+
ForceNew: true,
164+
Description: "Defines if the public IP should be removed from the nodes.",
165+
},
159166
"zone": zoneSchema(),
160167
"region": regionSchema(),
161168
// Computed elements
@@ -227,16 +234,17 @@ func resourceScalewayK8SPoolCreate(ctx context.Context, d *schema.ResourceData,
227234
// Create pool
228235
////
229236
req := &k8s.CreatePoolRequest{
230-
Region: region,
231-
ClusterID: expandID(d.Get("cluster_id")),
232-
Name: expandOrGenerateString(d.Get("name"), "pool"),
233-
NodeType: d.Get("node_type").(string),
234-
Autoscaling: d.Get("autoscaling").(bool),
235-
Autohealing: d.Get("autohealing").(bool),
236-
Size: uint32(d.Get("size").(int)),
237-
Tags: expandStrings(d.Get("tags")),
238-
Zone: scw.Zone(d.Get("zone").(string)),
239-
KubeletArgs: expandKubeletArgs(d.Get("kubelet_args")),
237+
Region: region,
238+
ClusterID: expandID(d.Get("cluster_id")),
239+
Name: expandOrGenerateString(d.Get("name"), "pool"),
240+
NodeType: d.Get("node_type").(string),
241+
Autoscaling: d.Get("autoscaling").(bool),
242+
Autohealing: d.Get("autohealing").(bool),
243+
Size: uint32(d.Get("size").(int)),
244+
Tags: expandStrings(d.Get("tags")),
245+
Zone: scw.Zone(d.Get("zone").(string)),
246+
KubeletArgs: expandKubeletArgs(d.Get("kubelet_args")),
247+
PublicIPDisabled: d.Get("public_ip_disabled").(bool),
240248
}
241249

242250
if v, ok := d.GetOk("region"); ok {
@@ -379,6 +387,7 @@ func resourceScalewayK8SPoolRead(ctx context.Context, d *schema.ResourceData, me
379387
_ = d.Set("kubelet_args", flattenKubeletArgs(pool.KubeletArgs))
380388
_ = d.Set("zone", pool.Zone)
381389
_ = d.Set("upgrade_policy", poolUpgradePolicyFlatten(pool))
390+
_ = d.Set("public_ip_disabled", pool.PublicIPDisabled)
382391

383392
if pool.PlacementGroupID != nil {
384393
_ = d.Set("placement_group_id", newZonedID(pool.Zone, *pool.PlacementGroupID).String())

scaleway/resource_k8s_pool_test.go

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,104 @@ func TestAccScalewayK8SCluster_PoolPrivateNetwork(t *testing.T) {
414414
})
415415
}
416416

417+
func TestAccScalewayK8SCluster_PoolPublicIPDisabled(t *testing.T) {
418+
tt := NewTestTools(t)
419+
defer tt.Cleanup()
420+
421+
latestK8SVersion := testAccScalewayK8SClusterGetLatestK8SVersion(tt)
422+
423+
resource.ParallelTest(t, resource.TestCase{
424+
PreCheck: func() { testAccPreCheck(t) },
425+
ProviderFactories: tt.ProviderFactories,
426+
CheckDestroy: testAccCheckScalewayK8SClusterDestroy(tt),
427+
Steps: []resource.TestStep{
428+
{
429+
Config: fmt.Sprintf(`
430+
resource "scaleway_vpc_private_network" "public_ip" {
431+
name = "k8s-private-network"
432+
}
433+
434+
resource "scaleway_k8s_cluster" "public_ip" {
435+
name = "private-network-cluster"
436+
version = "%s"
437+
cni = "cilium"
438+
private_network_id = scaleway_vpc_private_network.public_ip.id
439+
tags = [ "terraform-test", "scaleway_k8s_cluster", "public_ip" ]
440+
delete_additional_resources = true
441+
depends_on = [scaleway_vpc_private_network.public_ip]
442+
}
443+
444+
resource "scaleway_k8s_pool" "public_ip" {
445+
cluster_id = scaleway_k8s_cluster.public_ip.id
446+
name = "pool"
447+
node_type = "gp1_xs"
448+
size = 1
449+
autoscaling = false
450+
autohealing = true
451+
wait_for_pool_ready = true
452+
}`, latestK8SVersion),
453+
Check: resource.ComposeTestCheckFunc(
454+
testAccCheckScalewayK8SClusterExists(tt, "scaleway_k8s_cluster.public_ip"),
455+
testAccCheckScalewayVPCPrivateNetworkExists(tt, "scaleway_vpc_private_network.public_ip"),
456+
testAccCheckScalewayK8SPoolExists(tt, "scaleway_k8s_pool.public_ip"),
457+
resource.TestCheckResourceAttr("scaleway_k8s_pool.public_ip", "public_ip_disabled", "false"),
458+
testAccCheckScalewayK8SPoolPublicIP(tt, "scaleway_k8s_cluster.public_ip", "scaleway_k8s_pool.public_ip", false),
459+
),
460+
},
461+
{
462+
Config: fmt.Sprintf(`
463+
resource "scaleway_vpc_private_network" "public_ip" {
464+
name = "private-network-for-public-ip"
465+
}
466+
resource "scaleway_vpc_public_gateway" "public_ip" {
467+
name = "public-gateway-for-public-ip"
468+
type = "VPC-GW-S"
469+
}
470+
resource "scaleway_vpc_public_gateway_dhcp" "public_ip" {
471+
subnet = "192.168.0.0/22"
472+
push_default_route = true
473+
}
474+
resource "scaleway_vpc_gateway_network" "public_ip" {
475+
gateway_id = scaleway_vpc_public_gateway.public_ip.id
476+
private_network_id = scaleway_vpc_private_network.public_ip.id
477+
dhcp_id = scaleway_vpc_public_gateway_dhcp.public_ip.id
478+
}
479+
480+
resource "scaleway_k8s_cluster" "public_ip" {
481+
name = "cluster-for-public-ip"
482+
version = "%s"
483+
cni = "cilium"
484+
private_network_id = scaleway_vpc_private_network.public_ip.id
485+
tags = [ "terraform-test", "scaleway_k8s_cluster", "public_ip" ]
486+
delete_additional_resources = true
487+
depends_on = [
488+
scaleway_vpc_private_network.public_ip,
489+
scaleway_vpc_gateway_network.public_ip,
490+
]
491+
}
492+
493+
resource "scaleway_k8s_pool" "public_ip" {
494+
cluster_id = scaleway_k8s_cluster.public_ip.id
495+
name = "pool"
496+
node_type = "gp1_xs"
497+
size = 1
498+
autoscaling = false
499+
autohealing = true
500+
wait_for_pool_ready = true
501+
public_ip_disabled = true
502+
}`, latestK8SVersion),
503+
Check: resource.ComposeTestCheckFunc(
504+
testAccCheckScalewayK8SClusterExists(tt, "scaleway_k8s_cluster.public_ip"),
505+
testAccCheckScalewayVPCPrivateNetworkExists(tt, "scaleway_vpc_private_network.public_ip"),
506+
testAccCheckScalewayK8SPoolExists(tt, "scaleway_k8s_pool.public_ip"),
507+
resource.TestCheckResourceAttr("scaleway_k8s_pool.public_ip", "public_ip_disabled", "true"),
508+
testAccCheckScalewayK8SPoolPublicIP(tt, "scaleway_k8s_cluster.public_ip", "scaleway_k8s_pool.public_ip", true),
509+
),
510+
},
511+
},
512+
})
513+
}
514+
417515
func testAccCheckScalewayK8SPoolServersAreInPrivateNetwork(tt *TestTools, clusterTFName, poolTFName, pnTFName string) resource.TestCheckFunc {
418516
return func(s *terraform.State) error {
419517
rs, ok := s.RootModule().Resources[clusterTFName]
@@ -489,6 +587,64 @@ func testAccCheckScalewayK8SPoolServersAreInPrivateNetwork(tt *TestTools, cluste
489587
}
490588
}
491589

590+
func testAccCheckScalewayK8SPoolPublicIP(tt *TestTools, clusterTFName, poolTFName string, disabled bool) resource.TestCheckFunc {
591+
return func(s *terraform.State) error {
592+
rs, ok := s.RootModule().Resources[clusterTFName]
593+
if !ok {
594+
return fmt.Errorf("resource not found: %s", clusterTFName)
595+
}
596+
k8sAPI, region, clusterID, err := k8sAPIWithRegionAndID(tt.Meta, rs.Primary.ID)
597+
if err != nil {
598+
return err
599+
}
600+
601+
rs, ok = s.RootModule().Resources[poolTFName]
602+
if !ok {
603+
return fmt.Errorf("resource not found: %s", poolTFName)
604+
}
605+
_, _, poolID, err := k8sAPIWithRegionAndID(tt.Meta, rs.Primary.ID)
606+
if err != nil {
607+
return err
608+
}
609+
610+
nodes, err := k8sAPI.ListNodes(&k8s.ListNodesRequest{
611+
Region: region,
612+
PoolID: &poolID,
613+
ClusterID: clusterID,
614+
})
615+
if err != nil {
616+
return err
617+
}
618+
619+
instanceAPI := instance.NewAPI(tt.Meta.scwClient)
620+
621+
for _, node := range nodes.Nodes {
622+
providerIDSplit := strings.SplitN(node.ProviderID, "/", 5)
623+
// node.ProviderID is of the form scaleway://instance/<zone>/<id>
624+
if len(providerIDSplit) < 5 {
625+
return fmt.Errorf("unexpected format for ProviderID in node %s", node.ID)
626+
}
627+
628+
server, err := instanceAPI.GetServer(&instance.GetServerRequest{
629+
Zone: scw.Zone(providerIDSplit[3]),
630+
ServerID: providerIDSplit[4],
631+
})
632+
if err != nil {
633+
return err
634+
}
635+
636+
if disabled == true && server.Server.PublicIPs != nil && len(server.Server.PublicIPs) > 0 {
637+
return fmt.Errorf("found node with public IP when none was expected")
638+
}
639+
if disabled == false && (server.Server.PublicIPs == nil || len(server.Server.PublicIPs) == 0) {
640+
return fmt.Errorf("found node with no public IP when one was expected")
641+
}
642+
}
643+
644+
return nil
645+
}
646+
}
647+
492648
func testAccCheckScalewayK8SPoolDestroy(tt *TestTools, n string) resource.TestCheckFunc {
493649
return func(s *terraform.State) error {
494650
rs, ok := s.RootModule().Resources[n]

0 commit comments

Comments
 (0)