Skip to content

Commit a89cc88

Browse files
GKE L4 ILB Subsetting support (#4626) (#3095)
* mark field as updatable Co-authored-by: upodroid <[email protected]> * add l4 subsetting support Co-authored-by: upodroid <[email protected]> * fix beta guarding * fix change typo * add more beta guards Signed-off-by: Modular Magician <[email protected]>
1 parent 832121a commit a89cc88

File tree

5 files changed

+201
-3
lines changed

5 files changed

+201
-3
lines changed

.changelog/4626.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
container: added `enable_l4_ilb_subsetting` (beta) and `private_ipv6_google_access` fields to `google_container_cluster`
3+
```

google-beta/resource_container_cluster.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,20 @@ func rfc5545RecurrenceDiffSuppress(k, o, n string, d *schema.ResourceData) bool
9696
return false
9797
}
9898

99+
// Has enable_l4_ilb_subsetting been enabled before?
100+
func isBeenEnabled(_ context.Context, old, new, _ interface{}) bool {
101+
if old == nil || new == nil {
102+
return false
103+
}
104+
105+
// if subsetting is enabled, but is not now
106+
if old.(bool) && !new.(bool) {
107+
return true
108+
}
109+
110+
return false
111+
}
112+
99113
func resourceContainerCluster() *schema.Resource {
100114
return &schema.Resource{
101115
UseJSONNumber: true,
@@ -107,6 +121,7 @@ func resourceContainerCluster() *schema.Resource {
107121
CustomizeDiff: customdiff.All(
108122
resourceNodeConfigEmptyGuestAccelerator,
109123
containerClusterPrivateClusterConfigCustomDiff,
124+
customdiff.ForceNewIfChange("enable_l4_ilb_subsetting", isBeenEnabled),
110125
),
111126

112127
Timeouts: &schema.ResourceTimeout{
@@ -1148,6 +1163,18 @@ func resourceContainerCluster() *schema.Resource {
11481163
Description: `Whether Intra-node visibility is enabled for this cluster. This makes same node pod to pod traffic visible for VPC network.`,
11491164
Default: false,
11501165
},
1166+
"enable_l4_ilb_subsetting": {
1167+
Type: schema.TypeBool,
1168+
Optional: true,
1169+
Description: `Whether L4ILB Subsetting is enabled for this cluster.`,
1170+
Default: false,
1171+
},
1172+
"private_ipv6_google_access": {
1173+
Type: schema.TypeString,
1174+
Optional: true,
1175+
Description: `The desired state of IPv6 connectivity to Google Services. By default, no private IPv6 access to or from Google Services (all access will be via IPv4).`,
1176+
Computed: true,
1177+
},
11511178

11521179
"resource_usage_export_config": {
11531180
Type: schema.TypeList,
@@ -1306,6 +1333,8 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
13061333
EnableIntraNodeVisibility: d.Get("enable_intranode_visibility").(bool),
13071334
DefaultSnatStatus: expandDefaultSnatStatus(d.Get("default_snat_status")),
13081335
DatapathProvider: d.Get("datapath_provider").(string),
1336+
PrivateIpv6GoogleAccess: d.Get("private_ipv6_google_access").(string),
1337+
EnableL4ilbSubsetting: d.Get("enable_l4_ilb_subsetting").(bool),
13091338
},
13101339
MasterAuth: expandMasterAuth(d.Get("master_auth")),
13111340
NotificationConfig: expandNotificationConfig(d.Get("notification_config")),
@@ -1636,6 +1665,9 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
16361665
if err := d.Set("confidential_nodes", flattenConfidentialNodes(cluster.ConfidentialNodes)); err != nil {
16371666
return err
16381667
}
1668+
if err := d.Set("enable_l4_ilb_subsetting", cluster.NetworkConfig.EnableL4ilbSubsetting); err != nil {
1669+
return fmt.Errorf("Error setting enable_l4_ilb_subsetting: %s", err)
1670+
}
16391671
if err := d.Set("enable_tpu", cluster.EnableTpu); err != nil {
16401672
return fmt.Errorf("Error setting enable_tpu: %s", err)
16411673
}
@@ -1651,6 +1683,9 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
16511683
if err := d.Set("enable_intranode_visibility", cluster.NetworkConfig.EnableIntraNodeVisibility); err != nil {
16521684
return fmt.Errorf("Error setting enable_intranode_visibility: %s", err)
16531685
}
1686+
if err := d.Set("private_ipv6_google_access", cluster.NetworkConfig.PrivateIpv6GoogleAccess); err != nil {
1687+
return fmt.Errorf("Error setting private_ipv6_google_access: %s", err)
1688+
}
16541689
if err := d.Set("authenticator_groups_config", flattenAuthenticatorGroupsConfig(cluster.AuthenticatorGroupsConfig)); err != nil {
16551690
return err
16561691
}
@@ -1932,6 +1967,75 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
19321967
log.Printf("[INFO] GKE cluster %s Intra Node Visibility has been updated to %v", d.Id(), enabled)
19331968
}
19341969

1970+
if d.HasChange("private_ipv6_google_access") {
1971+
req := &containerBeta.UpdateClusterRequest{
1972+
Update: &containerBeta.ClusterUpdate{
1973+
DesiredPrivateIpv6GoogleAccess: d.Get("private_ipv6_google_access").(string),
1974+
},
1975+
}
1976+
updateF := func() error {
1977+
log.Println("[DEBUG] updating private_ipv6_google_access")
1978+
name := containerClusterFullName(project, location, clusterName)
1979+
clusterUpdateCall := config.NewContainerBetaClient(userAgent).Projects.Locations.Clusters.Update(name, req)
1980+
if config.UserProjectOverride {
1981+
clusterUpdateCall.Header().Add("X-Goog-User-Project", project)
1982+
}
1983+
op, err := clusterUpdateCall.Do()
1984+
if err != nil {
1985+
return err
1986+
}
1987+
1988+
// Wait until it's updated
1989+
err = containerOperationWait(config, op, project, location, "updating GKE Private IPv6 Google Access", userAgent, d.Timeout(schema.TimeoutUpdate))
1990+
log.Println("[DEBUG] done updating private_ipv6_google_access")
1991+
return err
1992+
}
1993+
1994+
// Call update serially.
1995+
if err := lockedCall(lockKey, updateF); err != nil {
1996+
return err
1997+
}
1998+
1999+
log.Printf("[INFO] GKE cluster %s Private IPv6 Google Access has been updated", d.Id())
2000+
}
2001+
2002+
if d.HasChange("enable_l4_ilb_subsetting") {
2003+
// This field can be changed from false to true but not from false to true. CustomizeDiff handles that check.
2004+
enabled := d.Get("enable_l4_ilb_subsetting").(bool)
2005+
req := &containerBeta.UpdateClusterRequest{
2006+
Update: &containerBeta.ClusterUpdate{
2007+
DesiredL4ilbSubsettingConfig: &containerBeta.ILBSubsettingConfig{
2008+
Enabled: enabled,
2009+
ForceSendFields: []string{"Enabled"},
2010+
},
2011+
},
2012+
}
2013+
updateF := func() error {
2014+
log.Println("[DEBUG] updating enable_l4_ilb_subsetting")
2015+
name := containerClusterFullName(project, location, clusterName)
2016+
clusterUpdateCall := config.NewContainerBetaClient(userAgent).Projects.Locations.Clusters.Update(name, req)
2017+
if config.UserProjectOverride {
2018+
clusterUpdateCall.Header().Add("X-Goog-User-Project", project)
2019+
}
2020+
op, err := clusterUpdateCall.Do()
2021+
if err != nil {
2022+
return err
2023+
}
2024+
2025+
// Wait until it's updated
2026+
err = containerOperationWait(config, op, project, location, "updating L4", userAgent, d.Timeout(schema.TimeoutUpdate))
2027+
log.Println("[DEBUG] done updating enable_intranode_visibility")
2028+
return err
2029+
}
2030+
2031+
// Call update serially.
2032+
if err := lockedCall(lockKey, updateF); err != nil {
2033+
return err
2034+
}
2035+
2036+
log.Printf("[INFO] GKE cluster %s L4 ILB Subsetting has been updated to %v", d.Id(), enabled)
2037+
}
2038+
19352039
if d.HasChange("default_snat_status") {
19362040
req := &containerBeta.UpdateClusterRequest{
19372041
Update: &containerBeta.ClusterUpdate{

google-beta/resource_container_cluster_test.go

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,45 @@ func TestAccContainerCluster_withConfidentialNodes(t *testing.T) {
260260
})
261261
}
262262

263+
func TestAccContainerCluster_withILBSubsetting(t *testing.T) {
264+
t.Parallel()
265+
266+
clusterName := fmt.Sprintf("tf-test-cluster-%s", randString(t, 10))
267+
npName := fmt.Sprintf("tf-test-cluster-nodepool-%s", randString(t, 10))
268+
269+
vcrTest(t, resource.TestCase{
270+
PreCheck: func() { testAccPreCheck(t) },
271+
Providers: testAccProviders,
272+
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
273+
Steps: []resource.TestStep{
274+
{
275+
Config: testAccContainerCluster_disableILBSubSetting(clusterName, npName),
276+
},
277+
{
278+
ResourceName: "google_container_cluster.confidential_nodes",
279+
ImportState: true,
280+
ImportStateVerify: true,
281+
},
282+
{
283+
Config: testAccContainerCluster_withILBSubSetting(clusterName, npName),
284+
},
285+
{
286+
ResourceName: "google_container_cluster.confidential_nodes",
287+
ImportState: true,
288+
ImportStateVerify: true,
289+
},
290+
{
291+
Config: testAccContainerCluster_disableILBSubSetting(clusterName, npName),
292+
},
293+
{
294+
ResourceName: "google_container_cluster.confidential_nodes",
295+
ImportState: true,
296+
ImportStateVerify: true,
297+
},
298+
},
299+
})
300+
}
301+
263302
func TestAccContainerCluster_withMasterAuthConfig(t *testing.T) {
264303
t.Parallel()
265304

@@ -2490,6 +2529,52 @@ resource "google_container_cluster" "confidential_nodes" {
24902529
`, clusterName, npName)
24912530
}
24922531

2532+
func testAccContainerCluster_withILBSubSetting(clusterName string, npName string) string {
2533+
return fmt.Sprintf(`
2534+
resource "google_container_cluster" "confidential_nodes" {
2535+
name = "%s"
2536+
location = "us-central1-a"
2537+
enable_shielded_nodes = true
2538+
release_channel {
2539+
channel = "RAPID"
2540+
}
2541+
2542+
node_pool {
2543+
name = "%s"
2544+
initial_node_count = 1
2545+
node_config {
2546+
machine_type = "n2d-standard-2"
2547+
}
2548+
}
2549+
2550+
enable_l4_ilb_subsetting = true
2551+
}
2552+
`, clusterName, npName)
2553+
}
2554+
2555+
func testAccContainerCluster_disableILBSubSetting(clusterName string, npName string) string {
2556+
return fmt.Sprintf(`
2557+
resource "google_container_cluster" "confidential_nodes" {
2558+
name = "%s"
2559+
location = "us-central1-a"
2560+
enable_shielded_nodes = true
2561+
release_channel {
2562+
channel = "RAPID"
2563+
}
2564+
2565+
node_pool {
2566+
name = "%s"
2567+
initial_node_count = 1
2568+
node_config {
2569+
machine_type = "n2d-standard-2"
2570+
}
2571+
}
2572+
2573+
enable_l4_ilb_subsetting = false
2574+
}
2575+
`, clusterName, npName)
2576+
}
2577+
24932578
func testAccContainerCluster_withMasterAuth(clusterName string) string {
24942579
return fmt.Sprintf(`
24952580
resource "google_container_cluster" "with_master_auth" {
@@ -2863,7 +2948,7 @@ resource "google_container_cluster" "with_intranode_visibility" {
28632948
name = "%s"
28642949
location = "us-central1-a"
28652950
initial_node_count = 1
2866-
enable_intranode_visibility = true
2951+
enable_intranode_visibility = true
28672952
}
28682953
`, clusterName)
28692954
}
@@ -2875,6 +2960,7 @@ resource "google_container_cluster" "with_intranode_visibility" {
28752960
location = "us-central1-a"
28762961
initial_node_count = 1
28772962
enable_intranode_visibility = false
2963+
private_ipv6_google_access = "PRIVATE_IPV6_GOOGLE_ACCESS_BIDIRECTIONAL"
28782964
}
28792965
`, clusterName)
28802966
}

google-beta/resource_dataproc_cluster_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ import (
1313
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
1414
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1515

16-
"google.golang.org/api/googleapi"
17-
1816
dataproc "google.golang.org/api/dataproc/v1beta2"
17+
"google.golang.org/api/googleapi"
1918
)
2019

2120
func TestDataprocExtractInitTimeout(t *testing.T) {

website/docs/r/container_cluster.html.markdown

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,12 @@ subnetwork in which the cluster's instances are launched.
301301
* `enable_intranode_visibility` - (Optional)
302302
Whether Intra-node visibility is enabled for this cluster. This makes same node pod to pod traffic visible for VPC network.
303303

304+
* `enable_l4_ilb_subsetting` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html))
305+
Whether L4ILB Subsetting is enabled for this cluster.
306+
307+
* `private_ipv6_google_access` - (Optional)
308+
The desired state of IPv6 connectivity to Google Services. By default, no private IPv6 access to or from Google Services (all access will be via IPv4).
309+
304310
* `datapath_provider` - (Optional)
305311
The desired datapath provider for this cluster. By default, uses the IPTables-based kube-proxy implementation.
306312

0 commit comments

Comments
 (0)