Skip to content

Commit

Permalink
Add additional_pod_ranges_config field (#8622) (#15600)
Browse files Browse the repository at this point in the history
* support additional_pod_ranges_config field

* fix update upon creation logic

* finalize tests, suppress permadiff, add docs

* nest within ip_allocation_policy block + update docs

* minor docs fix

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Aug 22, 2023
1 parent bee7121 commit 16cceaa
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/8622.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
container: added `additional_pod_ranges_config` field to `google_container_cluster` resource
```
114 changes: 114 additions & 0 deletions google/services/container/resource_container_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -1369,6 +1369,23 @@ func ResourceContainerCluster() *schema.Resource {
},
},
},
"additional_pod_ranges_config": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Description: `AdditionalPodRangesConfig is the configuration for additional pod secondary ranges supporting the ClusterUpdate message.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"pod_range_names": {
Type: schema.TypeSet,
MinItems: 1,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
Description: `Name for pod secondary ipv4 range which has the actual range defined ahead.`,
},
},
},
},
},
},
},
Expand Down Expand Up @@ -2149,6 +2166,38 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
}
}

if names, ok := d.GetOk("ip_allocation_policy.0.additional_pod_ranges_config.0.pod_range_names"); ok {
name := containerClusterFullName(project, location, clusterName)
additionalPodRangesConfig := &container.AdditionalPodRangesConfig{
PodRangeNames: tpgresource.ConvertStringSet(names.(*schema.Set)),
}

req := &container.UpdateClusterRequest{
Update: &container.ClusterUpdate{
AdditionalPodRangesConfig: additionalPodRangesConfig,
},
}

err = transport_tpg.Retry(transport_tpg.RetryOptions{
RetryFunc: func() error {
clusterUpdateCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.Update(name, req)
if config.UserProjectOverride {
clusterUpdateCall.Header().Add("X-Goog-User-Project", project)
}
op, err = clusterUpdateCall.Do()
return err
},
})
if err != nil {
return errwrap.Wrapf("Error updating AdditionalPodRangesConfig: {{err}}", err)
}

err = ContainerOperationWait(config, op, project, location, "updating AdditionalPodRangesConfig", userAgent, d.Timeout(schema.TimeoutCreate))
if err != nil {
return errwrap.Wrapf("Error while waiting to update AdditionalPodRangesConfig: {{err}}", err)
}
}

if err := resourceContainerClusterRead(d, meta); err != nil {
return err
}
Expand Down Expand Up @@ -3038,6 +3087,51 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er

}

if d.HasChange("ip_allocation_policy.0.additional_pod_ranges_config") {
o, n := d.GetChange("ip_allocation_policy.0.additional_pod_ranges_config.0.pod_range_names")
old_names := o.(*schema.Set)
new_names := n.(*schema.Set)

// Filter unchanged names.
removed_names := old_names.Difference(new_names)
added_names := new_names.Difference(old_names)

var additional_config *container.AdditionalPodRangesConfig
var removed_config *container.AdditionalPodRangesConfig
if added_names.Len() > 0 {
var names []string
for _, name := range added_names.List() {
names = append(names, name.(string))
}
additional_config = &container.AdditionalPodRangesConfig{
PodRangeNames: names,
}
}
if removed_names.Len() > 0 {
var names []string
for _, name := range removed_names.List() {
names = append(names, name.(string))
}
removed_config = &container.AdditionalPodRangesConfig{
PodRangeNames: names,
}
}
req := &container.UpdateClusterRequest{
Update: &container.ClusterUpdate{
AdditionalPodRangesConfig: additional_config,
RemovedAdditionalPodRangesConfig: removed_config,
},
}

updateF := updateFunc(req, "updating AdditionalPodRangesConfig")
// Call update serially.
if err := transport_tpg.LockedCall(lockKey, updateF); err != nil {
return err
}

log.Printf("[INFO] GKE cluster %s's AdditionalPodRangesConfig has been updated", d.Id())
}

if n, ok := d.GetOk("node_pool.#"); ok {
for i := 0; i < n.(int); i++ {
nodePoolInfo, err := extractNodePoolInformationFromCluster(d, config, clusterName)
Expand Down Expand Up @@ -4108,6 +4202,25 @@ func flattenSecurityPostureConfig(spc *container.SecurityPostureConfig) []map[st
return []map[string]interface{}{result}
}

func flattenAdditionalPodRangesConfig(ipAllocationPolicy *container.IPAllocationPolicy) []map[string]interface{} {
if ipAllocationPolicy == nil {
return nil
}
result := make(map[string]interface{})

if aprc := ipAllocationPolicy.AdditionalPodRangesConfig; aprc != nil {
if len(aprc.PodRangeNames) > 0 {
result["pod_range_names"] = aprc.PodRangeNames
} else {
return nil
}
} else {
return nil
}

return []map[string]interface{}{result}
}

func expandNotificationConfig(configured interface{}) *container.NotificationConfig {
l := configured.([]interface{})
if len(l) == 0 || l[0] == nil {
Expand Down Expand Up @@ -4878,6 +4991,7 @@ func flattenIPAllocationPolicy(c *container.Cluster, d *schema.ResourceData, con
"services_secondary_range_name": p.ServicesSecondaryRangeName,
"stack_type": p.StackType,
"pod_cidr_overprovision_config": flattenPodCidrOverprovisionConfig(p.PodCidrOverprovisionConfig),
"additional_pod_ranges_config": flattenAdditionalPodRangesConfig(c.IpAllocationPolicy),
},
}, nil
}
Expand Down
154 changes: 154 additions & 0 deletions google/services/container/resource_container_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3267,6 +3267,80 @@ func TestAccContainerCluster_autopilot_net_admin(t *testing.T) {
})
}

func TestAccContainerCluster_additional_pod_ranges_config_on_create(t *testing.T) {
t.Parallel()

clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10))
acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 1),
},
{
ResourceName: "google_container_cluster.primary",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccContainerCluster_additional_pod_ranges_config_on_update(t *testing.T) {
t.Parallel()

clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10))
acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 0),
},
{
ResourceName: "google_container_cluster.primary",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 2),
},
{
ResourceName: "google_container_cluster.primary",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 0),
},
{
ResourceName: "google_container_cluster.primary",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 1),
},
{
ResourceName: "google_container_cluster.primary",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 0),
},
{
ResourceName: "google_container_cluster.primary",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccContainerCluster_masterAuthorizedNetworksDisabled(t *testing.T, resource_name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resource_name]
Expand Down Expand Up @@ -6858,3 +6932,83 @@ resource "google_container_cluster" "cluster" {
}
}`, policyName, cluster, np)
}

func testAccContainerCluster_additional_pod_ranges_config(name string, nameCount int) string {
var podRangeNamesStr string
names := []string{"\"gke-autopilot-pods-add\",", "\"gke-autopilot-pods-add-2\""}
for i := 0; i < nameCount; i++ {
podRangeNamesStr += names[i]
}
var aprc string
if len(podRangeNamesStr) > 0 {
aprc = fmt.Sprintf(`
additional_pod_ranges_config {
pod_range_names = [%s]
}
`, podRangeNamesStr)
}

return fmt.Sprintf(`
resource "google_compute_network" "main" {
name = "%s"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "main" {
ip_cidr_range = "10.10.0.0/16"
name = "%s"
network = google_compute_network.main.self_link
region = "us-central1"
secondary_ip_range {
range_name = "gke-autopilot-services"
ip_cidr_range = "10.11.0.0/20"
}
secondary_ip_range {
range_name = "gke-autopilot-pods"
ip_cidr_range = "10.12.0.0/16"
}
secondary_ip_range {
range_name = "gke-autopilot-pods-add"
ip_cidr_range = "10.100.0.0/16"
}
secondary_ip_range {
range_name = "gke-autopilot-pods-add-2"
ip_cidr_range = "100.0.0.0/16"
}
}
resource "google_container_cluster" "primary" {
name = "%s"
location = "us-central1"
enable_autopilot = true
release_channel {
channel = "REGULAR"
}
network = google_compute_network.main.name
subnetwork = google_compute_subnetwork.main.name
private_cluster_config {
enable_private_endpoint = false
enable_private_nodes = true
master_ipv4_cidr_block = "172.16.0.0/28"
}
# supresses permadiff
dns_config {
cluster_dns = "CLOUD_DNS"
cluster_dns_domain = "cluster.local"
cluster_dns_scope = "CLUSTER_SCOPE"
}
ip_allocation_policy {
cluster_secondary_range_name = "gke-autopilot-pods"
services_secondary_range_name = "gke-autopilot-services"
%s
}
}
`, name, name, name, aprc)
}
10 changes: 10 additions & 0 deletions website/docs/r/container_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,16 @@ pick a specific range to use.
Default value is `IPV4`.
Possible values are `IPV4` and `IPV4_IPV6`.

* `additional_pod_ranges_config` - (Optional) The configuration for additional pod secondary ranges at
the cluster level. Used for Autopilot clusters and Standard clusters with which control of the
secondary Pod IP address assignment to node pools isn't needed. Structure is [documented below](#nested_additional_pod_ranges_config).


<a name="nested_additional_pod_ranges_config"></a>The `additional_pod_ranges_config` block supports:

* `pod_range_names` - (Required) The names of the Pod ranges to add to the cluster.


<a name="nested_master_auth"></a>The `master_auth` block supports:

* `client_certificate_config` - (Required) Whether client certificate authorization is enabled for this cluster. For example:
Expand Down

0 comments on commit 16cceaa

Please sign in to comment.