Skip to content

Commit

Permalink
Allow configuring GKE Node Pool upgrade settings
Browse files Browse the repository at this point in the history
Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
chrissng authored and modular-magician committed Dec 3, 2019
1 parent dd21b90 commit c09b051
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 0 deletions.
78 changes: 78 additions & 0 deletions google-beta/resource_container_node_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,27 @@ var schemaNodePool = map[string]*schema.Schema{
Elem: &schema.Schema{Type: schema.TypeString},
},

"upgrade_settings": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"max_surge": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(0),
},

"max_unavailable": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(0),
},
},
},
},

"initial_node_count": {
Type: schema.TypeInt,
Optional: true,
Expand Down Expand Up @@ -492,6 +513,19 @@ func expandNodePool(d *schema.ResourceData, prefix string) (*containerBeta.NodeP
}
}

if v, ok := d.GetOk(prefix + "upgrade_settings"); ok {
upgradeSettingsConfig := v.([]interface{})[0].(map[string]interface{})
np.UpgradeSettings = &containerBeta.UpgradeSettings{}

if v, ok := upgradeSettingsConfig["max_surge"]; ok {
np.UpgradeSettings.MaxSurge = int64(v.(int))
}

if v, ok := upgradeSettingsConfig["max_unavailable"]; ok {
np.UpgradeSettings.MaxUnavailable = int64(v.(int))
}
}

return np, nil
}

Expand Down Expand Up @@ -547,6 +581,17 @@ func flattenNodePool(d *schema.ResourceData, config *Config, np *containerBeta.N
},
}

if np.UpgradeSettings != nil {
nodePool["upgrade_settings"] = []map[string]interface{}{
{
"max_surge": np.UpgradeSettings.MaxSurge,
"max_unavailable": np.UpgradeSettings.MaxUnavailable,
},
}
} else {
delete(nodePool, "upgrade_settings")
}

return nodePool, nil
}

Expand Down Expand Up @@ -766,6 +811,39 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node
}
}

if d.HasChange(prefix + "upgrade_settings") {
upgradeSettings := &containerBeta.UpgradeSettings{}
if v, ok := d.GetOk(prefix + "upgrade_settings"); ok {
upgradeSettingsConfig := v.([]interface{})[0].(map[string]interface{})
upgradeSettings.MaxSurge = int64(upgradeSettingsConfig["max_surge"].(int))
upgradeSettings.MaxUnavailable = int64(upgradeSettingsConfig["max_unavailable"].(int))
}
req := &containerBeta.UpdateNodePoolRequest{
UpgradeSettings: upgradeSettings,
}
updateF := func() error {
op, err := config.clientContainerBeta.Projects.Locations.Clusters.NodePools.Update(nodePoolInfo.fullyQualifiedName(name), req).Do()

if err != nil {
return err
}

// Wait until it's updated
return containerOperationWait(config, op, nodePoolInfo.project, nodePoolInfo.location, "updating GKE node pool upgrade settings", timeoutInMinutes)
}

// Call update serially.
if err := lockedCall(lockKey, updateF); err != nil {
return err
}

log.Printf("[INFO] Updated upgrade settings in Node Pool %s", name)

if prefix == "" {
d.SetPartial("upgrade_settings")
}
}

return nil
}

Expand Down
77 changes: 77 additions & 0 deletions google-beta/resource_container_node_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package google

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
Expand Down Expand Up @@ -239,6 +240,56 @@ func TestAccContainerNodePool_withSandboxConfig(t *testing.T) {
})
}

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

clusterName := acctest.RandString(10)
nodePoolName := acctest.RandString(10)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccContainerNodePool_withUpgradeSettings(clusterName, nodePoolName, 2, 3),
},
{
ResourceName: "google_container_node_pool.with_upgrade_settings",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccContainerNodePool_withUpgradeSettings(clusterName, nodePoolName, 1, 1),
},
{
ResourceName: "google_container_node_pool.with_upgrade_settings",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

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

clusterName := acctest.RandString(10)
nodePoolName := acctest.RandString(10)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccContainerNodePool_withUpgradeSettings(clusterName, nodePoolName, 0, 0),
ExpectError: regexp.MustCompile(`.?Max_surge and max_unavailable must not be negative and at least one of them must be greater than zero.*`),
},
},
})
}

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

Expand Down Expand Up @@ -1179,6 +1230,32 @@ resource "google_container_node_pool" "with_sandbox_config" {
`, acctest.RandString(10), acctest.RandString(10))
}

func testAccContainerNodePool_withUpgradeSettings(clusterName string, nodePoolName string, maxSurge int, maxUnavailable int) string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1" {
location = "us-central1"
}
resource "google_container_cluster" "cluster" {
name = "tf-cluster-nodepool-test-%s"
location = "us-central1"
initial_node_count = 1
min_master_version = "${data.google_container_engine_versions.central1.latest_master_version}"
}
resource "google_container_node_pool" "with_upgrade_settings" {
name = "tf-nodepool-test-%s"
location = "us-central1"
cluster = "${google_container_cluster.cluster.name}"
initial_node_count = 1
upgrade_settings {
max_surge = %d
max_unavailable = %d
}
}
`, clusterName, nodePoolName, maxSurge, maxUnavailable)
}

func testAccContainerNodePool_withGPU() string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1c" {
Expand Down
16 changes: 16 additions & 0 deletions website/docs/r/container_node_pool.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ cluster.
* `project` - (Optional) The ID of the project in which to create the node pool. If blank,
the provider-configured project will be used.

* `upgrade_settings` (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Specify node upgrade settings to change how many nodes GKE attempts to
upgrade at once. The number of nodes upgraded simultaneously is the sum of `max_surge` and `max_unavailable`.
The maximum number of nodes upgraded simultaneously is limited to 20.

* `version` - (Optional) The Kubernetes version for the nodes in this pool. Note that if this field
and `auto_upgrade` are both specified, they will fight each other for what the node version should
be, so setting both is highly discouraged. While a fuzzy version can be specified, it's
Expand All @@ -164,6 +168,18 @@ The `management` block supports:

* `auto_upgrade` - (Optional) Whether the nodes will be automatically upgraded.

The `upgrade_settings` block supports:

* `max_surge` - (Required) The number of additional nodes that can be added to the node pool during
an upgrade. Increasing `max_surge` raises the number of nodes that can be upgraded simultaneously.
Can be set to 0 or greater.

* `max_unavailable` - (Required) The number of nodes that can be simultaneously unavailable during
an upgrade. Increasing `max_unavailable` raises the number of nodes that can be upgraded in
parallel. Can be set to 0 or greater.

`max_surge` and `max_unavailable` must not be negative and at least one of them must be greater than zero.

<a id="timeouts"></a>
## Timeouts

Expand Down

0 comments on commit c09b051

Please sign in to comment.