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

fixes to updating node versions #2872

Merged
merged 1 commit into from
Jan 18, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
115 changes: 65 additions & 50 deletions google/resource_container_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -902,56 +902,6 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
d.SetPartial("master_authorized_networks_config")
}

// The master must be updated before the nodes
if d.HasChange("min_master_version") {
desiredMasterVersion := d.Get("min_master_version").(string)
currentMasterVersion := d.Get("master_version").(string)
des, err := version.NewVersion(desiredMasterVersion)
if err != nil {
return err
}
cur, err := version.NewVersion(currentMasterVersion)
if err != nil {
return err
}

// Only upgrade the master if the current version is lower than the desired version
if cur.LessThan(des) {
req := &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredMasterVersion: desiredMasterVersion,
},
}

updateF := updateFunc(req, "updating GKE master version")
// Call update serially.
if err := lockedCall(lockKey, updateF); err != nil {
return err
}
log.Printf("[INFO] GKE cluster %s: master has been updated to %s", d.Id(), desiredMasterVersion)
}
d.SetPartial("min_master_version")
}

if d.HasChange("node_version") {
desiredNodeVersion := d.Get("node_version").(string)
req := &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredNodeVersion: desiredNodeVersion,
},
}

updateF := updateFunc(req, "updating GKE node version")
// Call update serially.
if err := lockedCall(lockKey, updateF); err != nil {
return err
}
log.Printf("[INFO] GKE cluster %s: nodes have been updated to %s", d.Id(),
desiredNodeVersion)

d.SetPartial("node_version")
}

if d.HasChange("addons_config") {
if ac, ok := d.GetOk("addons_config"); ok {
req := &containerBeta.UpdateClusterRequest{
Expand Down Expand Up @@ -1178,6 +1128,71 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
d.SetPartial("node_pool")
}

// The master must be updated before the nodes
if d.HasChange("min_master_version") {
desiredMasterVersion := d.Get("min_master_version").(string)
currentMasterVersion := d.Get("master_version").(string)
des, err := version.NewVersion(desiredMasterVersion)
if err != nil {
return err
}
cur, err := version.NewVersion(currentMasterVersion)
if err != nil {
return err
}

// Only upgrade the master if the current version is lower than the desired version
if cur.LessThan(des) {
req := &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredMasterVersion: desiredMasterVersion,
},
}

updateF := updateFunc(req, "updating GKE master version")
// Call update serially.
if err := lockedCall(lockKey, updateF); err != nil {
return err
}
log.Printf("[INFO] GKE cluster %s: master has been updated to %s", d.Id(), desiredMasterVersion)
}
d.SetPartial("min_master_version")
}

// It's not super important that this come after updating the node pools, but it still seems like a better
// idea than doing it before.
if d.HasChange("node_version") {
foundDefault := false
if n, ok := d.GetOk("node_pool.#"); ok {
for i := 0; i < n.(int); i++ {
key := fmt.Sprintf("node_pool.%d.", i)
if d.Get(key+"name").(string) == "default-pool" {
desiredNodeVersion := d.Get("node_version").(string)
req := &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredNodeVersion: desiredNodeVersion,
DesiredNodePoolId: "default-pool",
},
}
updateF := updateFunc(req, "updating GKE default node pool node version")
// Call update serially.
if err := lockedCall(lockKey, updateF); err != nil {
return err
}
log.Printf("[INFO] GKE cluster %s: default node pool has been updated to %s", d.Id(),
desiredNodeVersion)
foundDefault = true
}
}
}

if !foundDefault {
return fmt.Errorf("node_version was updated but default-pool was not found. To update the version for a non-default pool, use the version attribute on that pool.")
}

d.SetPartial("node_version")
}

if d.HasChange("node_config") {
if d.HasChange("node_config.0.image_type") {
it := d.Get("node_config.0.image_type").(string)
Expand Down
75 changes: 75 additions & 0 deletions google/resource_container_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,41 @@ func TestAccContainerCluster_withNodePoolBasic(t *testing.T) {
})
}

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

clusterName := fmt.Sprintf("tf-cluster-nodepool-test-%s", acctest.RandString(10))
npName := fmt.Sprintf("tf-cluster-nodepool-test-%s", acctest.RandString(10))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccContainerCluster_withNodePoolLowerVersion(clusterName, npName),
},
{
ResourceName: "google_container_cluster.with_node_pool",
ImportStateIdPrefix: "us-central1-a/",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"min_master_version"},
},
{
Config: testAccContainerCluster_withNodePoolUpdateVersion(clusterName, npName),
},
{
ResourceName: "google_container_cluster.with_node_pool",
ImportStateIdPrefix: "us-central1-a/",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"min_master_version"},
},
},
})
}

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

Expand Down Expand Up @@ -1821,6 +1856,46 @@ resource "google_container_cluster" "with_node_pool" {
}`, cluster, nodePool)
}

func testAccContainerCluster_withNodePoolLowerVersion(cluster, nodePool string) string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1a" {
zone = "us-central1-a"
}

resource "google_container_cluster" "with_node_pool" {
name = "%s"
zone = "us-central1-a"

min_master_version = "${data.google_container_engine_versions.central1a.valid_master_versions.1}"

node_pool {
name = "%s"
initial_node_count = 2
version = "${data.google_container_engine_versions.central1a.valid_node_versions.2}"
}
}`, cluster, nodePool)
}

func testAccContainerCluster_withNodePoolUpdateVersion(cluster, nodePool string) string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1a" {
zone = "us-central1-a"
}

resource "google_container_cluster" "with_node_pool" {
name = "%s"
zone = "us-central1-a"

min_master_version = "${data.google_container_engine_versions.central1a.valid_master_versions.1}"

node_pool {
name = "%s"
initial_node_count = 2
version = "${data.google_container_engine_versions.central1a.valid_node_versions.1}"
}
}`, cluster, nodePool)
}

func testAccContainerCluster_withNodePoolAdditionalZones(cluster, nodePool string) string {
return fmt.Sprintf(`
resource "google_container_cluster" "with_node_pool" {
Expand Down
2 changes: 1 addition & 1 deletion google/resource_container_node_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node
if d.HasChange(prefix + "version") {
req := &containerBeta.UpdateNodePoolRequest{
NodePoolId: name,
NodeVersion: d.Get("version").(string),
NodeVersion: d.Get(prefix + "version").(string),
}
updateF := func() error {
op, err := config.clientContainerBeta.Projects.
Expand Down
4 changes: 3 additions & 1 deletion website/docs/r/container_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ to the datasource. A `region` can have a different set of supported versions tha

* `node_version` - (Optional) The Kubernetes version on the nodes. Must either be unset
or set to the same value as `min_master_version` on create. Defaults to the default
version set by GKE which is not necessarily the latest version.
version set by GKE which is not necessarily the latest version. This only affects
nodes in the default node pool. To update nodes in other node pools, use the `version`
attribute on the node pool.

* `pod_security_policy_config` - (Optional, [Beta](https://terraform.io/docs/providers/google/provider_versions.html)) Configuration for the
[PodSecurityPolicy](https://cloud.google.com/kubernetes-engine/docs/how-to/pod-security-policies) feature.
Expand Down