Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional_pod_ranges_config field #8622

Merged
merged 5 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1580,6 +1580,24 @@ func ResourceContainerCluster() *schema.Resource {
},
},

"additional_pod_ranges_config": {
zli82016 marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
jeperetz marked this conversation as resolved.
Show resolved Hide resolved
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.`,
},
},
},
},

"networking_mode": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -2433,6 +2451,38 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
}
}

if names, ok := d.GetOk("additional_pod_ranges_config.0.pod_range_names"); ok {
zli82016 marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -2606,6 +2656,11 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
}
}
}
if aprc := flattenAdditionalPodRangesConfig(cluster.IpAllocationPolicy); aprc != nil {
zli82016 marked this conversation as resolved.
Show resolved Hide resolved
if err := d.Set("additional_pod_ranges_config", aprc); err != nil {
return fmt.Errorf("Error setting additional_pod_ranges_config: %s", err)
}
}
if cluster.ShieldedNodes != nil {
if err := d.Set("enable_shielded_nodes", cluster.ShieldedNodes.Enabled); err != nil {
return fmt.Errorf("Error setting enable_shielded_nodes: %s", err)
Expand Down Expand Up @@ -3355,6 +3410,51 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er

}

if d.HasChange("additional_pod_ranges_config") {
o, n := d.GetChange("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 @@ -4649,6 +4749,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
Original file line number Diff line number Diff line change
Expand Up @@ -3924,6 +3924,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 @@ -8061,3 +8135,84 @@ 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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ below](#nested_ip_allocation_policy).
Options are `VPC_NATIVE` or `ROUTES`. `VPC_NATIVE` enables [IP aliasing](https://cloud.google.com/kubernetes-engine/docs/how-to/ip-aliases),
and requires the `ip_allocation_policy` block to be defined. By default, when this field is unspecified and no `ip_allocation_policy` blocks are set, GKE will create a `ROUTES`-based cluster.

* `additional_pod_ranges_config` - (Optional) The configuration for additional pod secondary ranges at
zli82016 marked this conversation as resolved.
Show resolved Hide resolved
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.

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

* `logging_config` - (Optional) Logging configuration for the cluster.
Structure is [documented below](#nested_logging_config).

Expand Down