diff --git a/.changelog/7459.txt b/.changelog/7459.txt new file mode 100644 index 00000000000..f2fdea44dd6 --- /dev/null +++ b/.changelog/7459.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +container: added `stack_type` field to `google_container_cluster` resource +``` diff --git a/google/resource_container_cluster.go b/google/resource_container_cluster.go index d3221fda7e2..13ffcda4027 100644 --- a/google/resource_container_cluster.go +++ b/google/resource_container_cluster.go @@ -1245,6 +1245,15 @@ func ResourceContainerCluster() *schema.Resource { ConflictsWith: ipAllocationCidrBlockFields, Description: `The name of the existing secondary range in the cluster's subnetwork to use for service ClusterIPs. Alternatively, services_ipv4_cidr_block can be used to automatically create a GKE-managed one.`, }, + + "stack_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "IPV4", + ValidateFunc: validation.StringInSlice([]string{"IPV4", "IPV4_IPV6"}, false), + Description: `The IP Stack type of the cluster. Choose between IPV4 and IPV4_IPV6. Default type is IPV4 Only if not set`, + }, }, }, }, @@ -3489,6 +3498,7 @@ func expandClusterAddonsConfig(configured interface{}) *container.AddonsConfig { } func expandIPAllocationPolicy(configured interface{}, networkingMode string) (*container.IPAllocationPolicy, error) { + l := configured.([]interface{}) if len(l) == 0 || l[0] == nil { if networkingMode == "VPC_NATIVE" { @@ -3497,20 +3507,23 @@ func expandIPAllocationPolicy(configured interface{}, networkingMode string) (*c return &container.IPAllocationPolicy{ UseIpAliases: false, UseRoutes: true, + StackType: "IPV4", ForceSendFields: []string{"UseIpAliases"}, }, nil } config := l[0].(map[string]interface{}) - return &container.IPAllocationPolicy{ - UseIpAliases: networkingMode == "VPC_NATIVE" || networkingMode == "", - ClusterIpv4CidrBlock: config["cluster_ipv4_cidr_block"].(string), - ServicesIpv4CidrBlock: config["services_ipv4_cidr_block"].(string), + stackType := config["stack_type"].(string) + return &container.IPAllocationPolicy{ + UseIpAliases: networkingMode == "VPC_NATIVE" || networkingMode == "", + ClusterIpv4CidrBlock: config["cluster_ipv4_cidr_block"].(string), + ServicesIpv4CidrBlock: config["services_ipv4_cidr_block"].(string), ClusterSecondaryRangeName: config["cluster_secondary_range_name"].(string), ServicesSecondaryRangeName: config["services_secondary_range_name"].(string), ForceSendFields: []string{"UseIpAliases"}, UseRoutes: networkingMode == "ROUTES", + StackType: stackType, }, nil } @@ -4477,12 +4490,14 @@ func flattenIPAllocationPolicy(c *container.Cluster, d *schema.ResourceData, con } p := c.IpAllocationPolicy + return []map[string]interface{}{ { "cluster_ipv4_cidr_block": p.ClusterIpv4CidrBlock, "services_ipv4_cidr_block": p.ServicesIpv4CidrBlock, "cluster_secondary_range_name": p.ClusterSecondaryRangeName, "services_secondary_range_name": p.ServicesSecondaryRangeName, + "stack_type": p.StackType, }, }, nil } diff --git a/google/resource_container_cluster_test.go b/google/resource_container_cluster_test.go index f701c84df68..fc05e823010 100644 --- a/google/resource_container_cluster_test.go +++ b/google/resource_container_cluster_test.go @@ -1958,6 +1958,62 @@ func TestAccContainerCluster_withIPAllocationPolicy_specificSizes(t *testing.T) }) } +func TestAccContainerCluster_stackType_withDualStack(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", RandString(t, 10)) + containerNetName := fmt.Sprintf("tf-test-cluster-%s", RandString(t, 10)) + resourceName := "google_container_cluster.with_stack_type" + + VcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_stackType_withDualStack(containerNetName, clusterName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "ip_allocation_policy.0.stack_type", "IPV4_IPV6"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version"}, + }, + }, + }) +} + +func TestAccContainerCluster_stackType_withSingleStack(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", RandString(t, 10)) + containerNetName := fmt.Sprintf("tf-test-cluster-%s", RandString(t, 10)) + resourceName := "google_container_cluster.with_stack_type" + + VcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_stackType_withSingleStack(containerNetName, clusterName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "ip_allocation_policy.0.stack_type", "IPV4"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version"}, + }, + }, + }) +} + func TestAccContainerCluster_nodeAutoprovisioning(t *testing.T) { t.Parallel() @@ -5444,6 +5500,77 @@ resource "google_container_cluster" "with_ip_allocation_policy" { `, containerNetName, clusterName) } +func testAccContainerCluster_stackType_withDualStack(containerNetName string, clusterName string) string { + return fmt.Sprintf(` +resource "google_compute_network" "container_network" { + name = "%s" + auto_create_subnetworks = false +} + + resource "google_compute_subnetwork" "container_subnetwork" { + name = google_compute_network.container_network.name + network = google_compute_network.container_network.name + region = "us-central1" + + ip_cidr_range = "10.2.0.0/16" + stack_type = "IPV4_IPV6" + ipv6_access_type = "EXTERNAL" +} + +resource "google_container_cluster" "with_stack_type" { + name = "%s" + location = "us-central1-a" + network = google_compute_network.container_network.name + subnetwork = google_compute_subnetwork.container_subnetwork.name + + min_master_version = "1.25" + initial_node_count = 1 + datapath_provider = "ADVANCED_DATAPATH" + enable_l4_ilb_subsetting = true + + ip_allocation_policy { + cluster_ipv4_cidr_block = "10.0.0.0/16" + services_ipv4_cidr_block = "10.1.0.0/16" + stack_type = "IPV4_IPV6" + } +} +`, containerNetName, clusterName) +} + +func testAccContainerCluster_stackType_withSingleStack(containerNetName string, clusterName string) string { + return fmt.Sprintf(` +resource "google_compute_network" "container_network" { + name = "%s" + auto_create_subnetworks = false +} + + resource "google_compute_subnetwork" "container_subnetwork" { + name = google_compute_network.container_network.name + network = google_compute_network.container_network.name + region = "us-central1" + + ip_cidr_range = "10.2.0.0/16" +} + +resource "google_container_cluster" "with_stack_type" { + name = "%s" + location = "us-central1-a" + network = google_compute_network.container_network.name + subnetwork = google_compute_subnetwork.container_subnetwork.name + + min_master_version = "1.25" + initial_node_count = 1 + enable_l4_ilb_subsetting = true + + ip_allocation_policy { + cluster_ipv4_cidr_block = "10.0.0.0/16" + services_ipv4_cidr_block = "10.1.0.0/16" + stack_type = "IPV4" + } +} +`, containerNetName, clusterName) +} + func testAccContainerCluster_withResourceUsageExportConfig(clusterName, datasetId, enableMetering string) string { return fmt.Sprintf(` provider "google" { diff --git a/website/docs/r/container_cluster.html.markdown b/website/docs/r/container_cluster.html.markdown index e7c62960d97..e455d8b1130 100644 --- a/website/docs/r/container_cluster.html.markdown +++ b/website/docs/r/container_cluster.html.markdown @@ -691,6 +691,10 @@ to have a range chosen with a specific netmask. Set to a CIDR notation (e.g. 10. from the RFC-1918 private networks (e.g. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to pick a specific range to use. +* `stack_type` - (Optional) The IP Stack Type of the cluster. +Default value is `IPV4`. +Possible values are `IPV4` and `PV4_IPV6`. + The `master_auth` block supports: * `client_certificate_config` - (Required) Whether client certificate authorization is enabled for this cluster. For example: