diff --git a/google/resource_container_cluster.go b/google/resource_container_cluster.go index db06099b72c..6badc77d652 100644 --- a/google/resource_container_cluster.go +++ b/google/resource_container_cluster.go @@ -175,21 +175,18 @@ func resourceContainerCluster() *schema.Resource { "maintenance_policy": { Type: schema.TypeList, Optional: true, - ForceNew: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "daily_maintenance_window": { Type: schema.TypeList, Required: true, - ForceNew: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "start_time": { Type: schema.TypeString, Required: true, - ForceNew: true, ValidateFunc: validateRFC3339Time, DiffSuppressFunc: rfc3339TimeDiffSuppress, }, @@ -407,16 +404,7 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er timeoutInMinutes := int(d.Timeout(schema.TimeoutCreate).Minutes()) if v, ok := d.GetOk("maintenance_policy"); ok { - maintenancePolicy := v.([]interface{})[0].(map[string]interface{}) - dailyMaintenanceWindow := maintenancePolicy["daily_maintenance_window"].([]interface{})[0].(map[string]interface{}) - startTime := dailyMaintenanceWindow["start_time"].(string) - cluster.MaintenancePolicy = &container.MaintenancePolicy{ - Window: &container.MaintenanceWindow{ - DailyMaintenanceWindow: &container.DailyMaintenanceWindow{ - StartTime: startTime, - }, - }, - } + cluster.MaintenancePolicy = expandMaintenancePolicy(v) } if v, ok := d.GetOk("master_auth"); ok { @@ -603,18 +591,8 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro d.Set("endpoint", cluster.Endpoint) - if cluster.MaintenancePolicy != nil && cluster.MaintenancePolicy.Window != nil && cluster.MaintenancePolicy.Window.DailyMaintenanceWindow != nil { - maintenancePolicy := []map[string]interface{}{ - { - "daily_maintenance_window": []map[string]interface{}{ - { - "start_time": cluster.MaintenancePolicy.Window.DailyMaintenanceWindow.StartTime, - "duration": cluster.MaintenancePolicy.Window.DailyMaintenanceWindow.Duration, - }, - }, - }, - } - d.Set("maintenance_policy", maintenancePolicy) + if cluster.MaintenancePolicy != nil { + d.Set("maintenance_policy", flattenMaintenancePolicy(cluster.MaintenancePolicy)) } masterAuth := []map[string]interface{}{ @@ -799,6 +777,35 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er } } + if d.HasChange("maintenance_policy") { + var req *container.SetMaintenancePolicyRequest + if mp, ok := d.GetOk("maintenance_policy"); ok { + req = &container.SetMaintenancePolicyRequest{ + MaintenancePolicy: expandMaintenancePolicy(mp), + } + } else { + req = &container.SetMaintenancePolicyRequest{ + NullFields: []string{"MaintenancePolicy"}, + } + } + + op, err := config.clientContainer.Projects.Zones.Clusters.SetMaintenancePolicy( + project, zoneName, clusterName, req).Do() + if err != nil { + return err + } + + // Wait until it's updated + waitErr := containerOperationWait(config, op, project, zoneName, "updating GKE cluster maintenance policy", timeoutInMinutes, 2) + if waitErr != nil { + return waitErr + } + + log.Printf("[INFO] GKE cluster %s maintenance policy has been updated", d.Id()) + + d.SetPartial("maintenance_policy") + } + if d.HasChange("additional_zones") { azSet := d.Get("additional_zones").(*schema.Set) if azSet.Contains(zoneName) { @@ -1049,6 +1056,21 @@ func expandIPAllocationPolicy(configured interface{}) (*container.IPAllocationPo return ap, nil } +func expandMaintenancePolicy(configured interface{}) *container.MaintenancePolicy { + result := &container.MaintenancePolicy{} + if len(configured.([]interface{})) > 0 { + maintenancePolicy := configured.([]interface{})[0].(map[string]interface{}) + dailyMaintenanceWindow := maintenancePolicy["daily_maintenance_window"].([]interface{})[0].(map[string]interface{}) + startTime := dailyMaintenanceWindow["start_time"].(string) + result.Window = &container.MaintenanceWindow{ + DailyMaintenanceWindow: &container.DailyMaintenanceWindow{ + StartTime: startTime, + }, + } + } + return result +} + func expandMasterAuthorizedNetworksConfig(configured interface{}) *container.MasterAuthorizedNetworksConfig { result := &container.MasterAuthorizedNetworksConfig{} if len(configured.([]interface{})) > 0 { @@ -1143,6 +1165,19 @@ func flattenIPAllocationPolicy(c *container.IPAllocationPolicy) []map[string]int } } +func flattenMaintenancePolicy(mp *container.MaintenancePolicy) []map[string]interface{} { + return []map[string]interface{}{ + { + "daily_maintenance_window": []map[string]interface{}{ + { + "start_time": mp.Window.DailyMaintenanceWindow.StartTime, + "duration": mp.Window.DailyMaintenanceWindow.Duration, + }, + }, + }, + } +} + func flattenMasterAuthorizedNetworksConfig(c *container.MasterAuthorizedNetworksConfig) []map[string]interface{} { result := make(map[string]interface{}) if c.Enabled && len(c.CidrBlocks) > 0 { diff --git a/google/resource_container_cluster_test.go b/google/resource_container_cluster_test.go index 7c8d939e0b1..e634c2dce9a 100644 --- a/google/resource_container_cluster_test.go +++ b/google/resource_container_cluster_test.go @@ -610,6 +610,8 @@ func TestAccContainerCluster_withNodePoolNodeConfig(t *testing.T) { func TestAccContainerCluster_withMaintenanceWindow(t *testing.T) { t.Parallel() + clusterName := acctest.RandString(10) + resourceName := "google_container_cluster.with_maintenance_window" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -617,10 +619,17 @@ func TestAccContainerCluster_withMaintenanceWindow(t *testing.T) { CheckDestroy: testAccCheckContainerClusterDestroy, Steps: []resource.TestStep{ { - Config: testAccContainerCluster_withMaintenanceWindow("03:00"), + Config: testAccContainerCluster_withMaintenanceWindow(clusterName, "03:00"), Check: resource.ComposeTestCheckFunc( - testAccCheckContainerCluster( - "google_container_cluster.with_maintenance_window"), + testAccCheckContainerCluster(resourceName), + ), + }, + { + Config: testAccContainerCluster_withMaintenanceWindow(clusterName, ""), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr(resourceName, + "maintenance_policy.0.daily_maintenance_window.0.start_time"), + testAccCheckContainerCluster(resourceName), ), }, }, @@ -1609,19 +1618,25 @@ resource "google_container_cluster" "with_node_pool_node_config" { `, testId, testId) } -func testAccContainerCluster_withMaintenanceWindow(startTime string) string { +func testAccContainerCluster_withMaintenanceWindow(clusterName string, startTime string) string { + maintenancePolicy := "" + if len(startTime) > 0 { + maintenancePolicy = fmt.Sprintf(` + maintenance_policy { + daily_maintenance_window { + start_time = "%s" + } + }`, startTime) + } + return fmt.Sprintf(` resource "google_container_cluster" "with_maintenance_window" { name = "cluster-test-%s" zone = "us-central1-a" initial_node_count = 1 - maintenance_policy { - daily_maintenance_window { - start_time = "%s" - } - } -}`, acctest.RandString(10), startTime) + %s +}`, clusterName, maintenancePolicy) } func testAccContainerCluster_withIPAllocationPolicy(cluster string, ranges, policy map[string]string) string {