diff --git a/builtin/providers/google/resource_sql_database_instance.go b/builtin/providers/google/resource_sql_database_instance.go index ee03391ef..2a1fa2f30 100644 --- a/builtin/providers/google/resource_sql_database_instance.go +++ b/builtin/providers/google/resource_sql_database_instance.go @@ -153,6 +153,33 @@ func resourceSqlDatabaseInstance() *schema.Resource { }, }, }, + "maintenance_window": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "day": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + return validateNumericRange(v, k, 1, 7) + }, + }, + "hour": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + return validateNumericRange(v, k, 0, 23) + }, + }, + "update_track": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, "pricing_plan": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -431,6 +458,25 @@ func resourceSqlDatabaseInstanceCreate(d *schema.ResourceData, meta interface{}) } } + if v, ok := _settings["maintenance_window"]; ok && len(v.([]interface{})) > 0 { + settings.MaintenanceWindow = &sqladmin.MaintenanceWindow{} + _maintenanceWindow := v.([]interface{})[0].(map[string]interface{}) + + if vp, okp := _maintenanceWindow["day"]; okp { + settings.MaintenanceWindow.Day = int64(vp.(int)) + } + + if vp, okp := _maintenanceWindow["hour"]; okp { + settings.MaintenanceWindow.Hour = int64(vp.(int)) + } + + if vp, ok := _maintenanceWindow["update_track"]; ok { + if len(vp.(string)) > 0 { + settings.MaintenanceWindow.UpdateTrack = vp.(string) + } + } + } + if v, ok := _settings["pricing_plan"]; ok { settings.PricingPlan = v.(string) } @@ -745,6 +791,25 @@ func resourceSqlDatabaseInstanceRead(d *schema.ResourceData, meta interface{}) e } } + if v, ok := _settings["maintenance_window"]; ok && len(v.([]interface{})) > 0 && + settings.MaintenanceWindow != nil { + _maintenanceWindow := v.([]interface{})[0].(map[string]interface{}) + + if vp, okp := _maintenanceWindow["day"]; okp && vp != nil { + _maintenanceWindow["day"] = settings.MaintenanceWindow.Day + } + + if vp, okp := _maintenanceWindow["hour"]; okp && vp != nil { + _maintenanceWindow["hour"] = settings.MaintenanceWindow.Hour + } + + if vp, ok := _maintenanceWindow["update_track"]; ok && vp != nil { + if len(vp.(string)) > 0 { + _maintenanceWindow["update_track"] = settings.MaintenanceWindow.UpdateTrack + } + } + } + if v, ok := _settings["pricing_plan"]; ok && len(v.(string)) > 0 { _settings["pricing_plan"] = settings.PricingPlan } @@ -1062,6 +1127,25 @@ func resourceSqlDatabaseInstanceUpdate(d *schema.ResourceData, meta interface{}) } } + if v, ok := _settings["maintenance_window"]; ok && len(v.([]interface{})) > 0 { + settings.MaintenanceWindow = &sqladmin.MaintenanceWindow{} + _maintenanceWindow := v.([]interface{})[0].(map[string]interface{}) + + if vp, okp := _maintenanceWindow["day"]; okp { + settings.MaintenanceWindow.Day = int64(vp.(int)) + } + + if vp, okp := _maintenanceWindow["hour"]; okp { + settings.MaintenanceWindow.Hour = int64(vp.(int)) + } + + if vp, ok := _maintenanceWindow["update_track"]; ok { + if len(vp.(string)) > 0 { + settings.MaintenanceWindow.UpdateTrack = vp.(string) + } + } + } + if v, ok := _settings["pricing_plan"]; ok { settings.PricingPlan = v.(string) } @@ -1109,3 +1193,12 @@ func resourceSqlDatabaseInstanceDelete(d *schema.ResourceData, meta interface{}) return nil } + +func validateNumericRange(v interface{}, k string, min int, max int) (ws []string, errors []error) { + value := v.(int) + if min > value || value > max { + errors = append(errors, fmt.Errorf( + "%q outside range %d-%d.", k, min, max)) + } + return +} diff --git a/builtin/providers/google/resource_sql_database_instance_test.go b/builtin/providers/google/resource_sql_database_instance_test.go index 0a0b1bcca..4734fac6f 100644 --- a/builtin/providers/google/resource_sql_database_instance_test.go +++ b/builtin/providers/google/resource_sql_database_instance_test.go @@ -162,6 +162,29 @@ func TestAccGoogleSqlDatabaseInstance_diskspecs(t *testing.T) { }) } +func TestAccGoogleSqlDatabaseInstance_maintenance(t *testing.T) { + var instance sqladmin.DatabaseInstance + masterID := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccGoogleSqlDatabaseInstanceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: fmt.Sprintf( + testGoogleSqlDatabaseInstance_maintenance, masterID), + Check: resource.ComposeTestCheckFunc( + testAccCheckGoogleSqlDatabaseInstanceExists( + "google_sql_database_instance.instance", &instance), + testAccCheckGoogleSqlDatabaseInstanceEquals( + "google_sql_database_instance.instance", &instance), + ), + }, + }, + }) +} + func TestAccGoogleSqlDatabaseInstance_settings_upgrade(t *testing.T) { var instance sqladmin.DatabaseInstance databaseID := acctest.RandInt() @@ -359,6 +382,26 @@ func testAccCheckGoogleSqlDatabaseInstanceEquals(n string, } } + if instance.Settings.MaintenanceWindow != nil { + server = strconv.FormatInt(instance.Settings.MaintenanceWindow.Day, 10) + local = attributes["settings.0.maintenance_window.0.day"] + if server != local && len(server) > 0 && len(local) > 0 { + return fmt.Errorf("Error settings.maintenance_window.day mismatch, (%s, %s)", server, local) + } + + server = strconv.FormatInt(instance.Settings.MaintenanceWindow.Hour, 10) + local = attributes["settings.0.maintenance_window.0.hour"] + if server != local && len(server) > 0 && len(local) > 0 { + return fmt.Errorf("Error settings.maintenance_window.hour mismatch, (%s, %s)", server, local) + } + + server = instance.Settings.MaintenanceWindow.UpdateTrack + local = attributes["settings.0.maintenance_window.0.update_track"] + if server != local && len(server) > 0 && len(local) > 0 { + return fmt.Errorf("Error settings.maintenance_window.update_track mismatch, (%s, %s)", server, local) + } + } + server = instance.Settings.PricingPlan local = attributes["settings.0.pricing_plan"] if server != local && len(server) > 0 && len(local) > 0 { @@ -639,6 +682,23 @@ resource "google_sql_database_instance" "instance" { } ` +var testGoogleSqlDatabaseInstance_maintenance = ` +resource "google_sql_database_instance" "instance" { + name = "tf-lw-%d" + region = "us-central1" + + settings { + tier = "db-f1-micro" + + maintenance_window { + day = 7 + hour = 3 + update_track = "canary" + } + } +} +` + var testGoogleSqlDatabaseInstance_authNets_step1 = ` resource "google_sql_database_instance" "instance" { name = "tf-lw-%d" diff --git a/website/source/docs/providers/google/r/sql_database_instance.html.markdown b/website/source/docs/providers/google/r/sql_database_instance.html.markdown index 9321bf096..d07c0fff2 100644 --- a/website/source/docs/providers/google/r/sql_database_instance.html.markdown +++ b/website/source/docs/providers/google/r/sql_database_instance.html.markdown @@ -134,6 +134,17 @@ The optional `settings.location_preference` subblock supports: * `zone` - (Optional) The preferred compute engine [zone](https://cloud.google.com/compute/docs/zones?hl=en). +The optional `settings.maintenance_window` subblock for Second Generation +instances declares a one-hour [maintenance window](https://cloud.google.com/sql/docs/instance-settings?hl=en#maintenance-window-2ndgen) +when an Instance can automatically restart to apply updates. It supports: + +* `day` - (Optional) Day of week (`1-7`), starting on Monday + +* `hour` - (Optional) Hour of day (`0-23`), ignored if `day` not set + +* `update_track` - (Optional) Receive updates earlier (`canary`) or later +(`stable`) + The optional `replica_configuration` block must have `master_instance_name` set to work, cannot be updated, and supports: