From 275b903577912834e7fc85c13602ee76c17395bb Mon Sep 17 00:00:00 2001 From: Sandeep Sukhani Date: Wed, 26 Jun 2019 17:10:06 +0530 Subject: [PATCH] Allow updating workload identity in GKE clusters without force create Since gcloud allows updating workload identity from console and sdk without recreating the cluster, terraform also should not force recreation. --- google-beta/resource_container_cluster.go | 33 ++++++++- .../resource_container_cluster_test.go | 73 +++++++++++++++++++ 2 files changed, 103 insertions(+), 3 deletions(-) diff --git a/google-beta/resource_container_cluster.go b/google-beta/resource_container_cluster.go index 0788185849..3431331b83 100644 --- a/google-beta/resource_container_cluster.go +++ b/google-beta/resource_container_cluster.go @@ -705,13 +705,11 @@ func resourceContainerCluster() *schema.Resource { Type: schema.TypeList, MaxItems: 1, Optional: true, - ForceNew: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "identity_namespace": { Type: schema.TypeString, Required: true, - ForceNew: true, }, }, }, @@ -1797,6 +1795,35 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er } } + if d.HasChange("workload_identity_config") { + // Because GKE uses a non-RESTful update function, when removing the + // feature you need to specify a fairly full request body or it fails: + // "update": {"desiredWorkloadIdentityConfig": {"identityNamespace": ""}} + req := &containerBeta.UpdateClusterRequest{} + if v, ok := d.GetOk("workload_identity_config"); !ok { + req.Update = &containerBeta.ClusterUpdate{ + DesiredWorkloadIdentityConfig: &containerBeta.WorkloadIdentityConfig{ + IdentityNamespace: "", + ForceSendFields: []string{"IdentityNamespace"}, + }, + } + } else { + req.Update = &containerBeta.ClusterUpdate{ + DesiredWorkloadIdentityConfig: expandWorkloadIdentityConfig(v), + } + } + + updateF := updateFunc(req, "updating GKE cluster workload identity config") + // Call update serially. + if err := lockedCall(lockKey, updateF); err != nil { + return err + } + + log.Printf("[INFO] GKE cluster %s workload identity config has been updated", d.Id()) + + d.SetPartial("workload_identity_config") + } + if d.HasChange("resource_labels") { resourceLabels := d.Get("resource_labels").(map[string]interface{}) req := &containerBeta.SetLabelsRequest{ @@ -2266,7 +2293,7 @@ func expandVerticalPodAutoscaling(configured interface{}) *containerBeta.Vertica func expandWorkloadIdentityConfig(configured interface{}) *containerBeta.WorkloadIdentityConfig { l := configured.([]interface{}) - if len(l) == 0 { + if len(l) == 0 || l[0] == nil { return nil } config := l[0].(map[string]interface{}) diff --git a/google-beta/resource_container_cluster_test.go b/google-beta/resource_container_cluster_test.go index 3a1fb81d3d..cd00d0b005 100644 --- a/google-beta/resource_container_cluster_test.go +++ b/google-beta/resource_container_cluster_test.go @@ -1316,6 +1316,33 @@ func TestAccContainerCluster_withWorkloadIdentityConfig(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + Config: testAccContainerCluster_updateWorkloadMetadataConfig(pid, clusterName, "SECURE"), + }, + { + ResourceName: "google_container_cluster.with_workload_identity_config", + ImportStateIdPrefix: "us-central1-a/", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccContainerCluster_updateWorkloadIdentityConfig(pid, clusterName, false), + }, + { + ResourceName: "google_container_cluster.with_workload_identity_config", + ImportStateIdPrefix: "us-central1-a/", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccContainerCluster_updateWorkloadIdentityConfig(pid, clusterName, true), + }, + { + ResourceName: "google_container_cluster.with_workload_identity_config", + ImportStateIdPrefix: "us-central1-a/", + ImportState: true, + ImportStateVerify: true, + }, }, }) @@ -2215,6 +2242,30 @@ resource "google_container_cluster" "with_workload_metadata_config" { `, acctest.RandString(10)) } +func testAccContainerCluster_updateWorkloadMetadataConfig(projectID string, clusterName string, workloadMetadataConfig string) string { + return fmt.Sprintf(` +data "google_project" "project" { + project_id = "%s" +} + +resource "google_container_cluster" "with_workload_identity_config" { + name = "%s" + zone = "us-central1-a" + initial_node_count = 1 + + node_config { + oauth_scopes = [ + "https://www.googleapis.com/auth/logging.write", + "https://www.googleapis.com/auth/monitoring" + ] + + workload_metadata_config { + node_metadata = "%s" + } + } +}`, projectID, clusterName, workloadMetadataConfig) +} + func testAccContainerCluster_withSandboxConfig() string { return fmt.Sprintf(` data "google_container_engine_versions" "central1a" { @@ -2934,6 +2985,28 @@ resource "google_container_cluster" "with_workload_identity_config" { `, projectID, clusterName) } +func testAccContainerCluster_updateWorkloadIdentityConfig(projectID string, clusterName string, enable bool) string { + workloadIdentityConfig := "" + if enable { + workloadIdentityConfig = ` + workload_identity_config { + identity_namespace = "${data.google_project.project.project_id}.svc.id.goog" + }` + } + return fmt.Sprintf(` +data "google_project" "project" { + project_id = "%s" +} + +resource "google_container_cluster" "with_workload_identity_config" { + name = "%s" + zone = "us-central1-a" + initial_node_count = 1 + + %s +}`, projectID, clusterName, workloadIdentityConfig) +} + func testAccContainerCluster_withBinaryAuthorization(clusterName string, enabled bool) string { return fmt.Sprintf(` resource "google_container_cluster" "with_binary_authorization" {