github.com/IBM-Cloud/terraform@v0.6.4-0.20170726051544-8872b87621df/builtin/providers/google/resource_sql_database_instance.go (about)

     1  package google
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/hashicorp/terraform/helper/resource"
     8  	"github.com/hashicorp/terraform/helper/schema"
     9  
    10  	"google.golang.org/api/googleapi"
    11  	"google.golang.org/api/sqladmin/v1beta4"
    12  )
    13  
    14  func resourceSqlDatabaseInstance() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceSqlDatabaseInstanceCreate,
    17  		Read:   resourceSqlDatabaseInstanceRead,
    18  		Update: resourceSqlDatabaseInstanceUpdate,
    19  		Delete: resourceSqlDatabaseInstanceDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"region": &schema.Schema{
    23  				Type:     schema.TypeString,
    24  				Required: true,
    25  				ForceNew: true,
    26  			},
    27  
    28  			"settings": &schema.Schema{
    29  				Type:     schema.TypeList,
    30  				Required: true,
    31  				Elem: &schema.Resource{
    32  					Schema: map[string]*schema.Schema{
    33  						"version": &schema.Schema{
    34  							Type:     schema.TypeInt,
    35  							Computed: true,
    36  						},
    37  						"tier": &schema.Schema{
    38  							Type:     schema.TypeString,
    39  							Required: true,
    40  						},
    41  						"activation_policy": &schema.Schema{
    42  							Type:     schema.TypeString,
    43  							Optional: true,
    44  						},
    45  						"authorized_gae_applications": &schema.Schema{
    46  							Type:     schema.TypeList,
    47  							Optional: true,
    48  							Elem:     &schema.Schema{Type: schema.TypeString},
    49  						},
    50  						"backup_configuration": &schema.Schema{
    51  							Type:     schema.TypeList,
    52  							Optional: true,
    53  							Elem: &schema.Resource{
    54  								Schema: map[string]*schema.Schema{
    55  									"binary_log_enabled": &schema.Schema{
    56  										Type:     schema.TypeBool,
    57  										Optional: true,
    58  									},
    59  									"enabled": &schema.Schema{
    60  										Type:     schema.TypeBool,
    61  										Optional: true,
    62  									},
    63  									"start_time": &schema.Schema{
    64  										Type:     schema.TypeString,
    65  										Optional: true,
    66  									},
    67  								},
    68  							},
    69  						},
    70  						"crash_safe_replication": &schema.Schema{
    71  							Type:     schema.TypeBool,
    72  							Optional: true,
    73  							Computed: true,
    74  						},
    75  						"database_flags": &schema.Schema{
    76  							Type:     schema.TypeList,
    77  							Optional: true,
    78  							Elem: &schema.Resource{
    79  								Schema: map[string]*schema.Schema{
    80  									"value": &schema.Schema{
    81  										Type:     schema.TypeString,
    82  										Optional: true,
    83  									},
    84  									"name": &schema.Schema{
    85  										Type:     schema.TypeString,
    86  										Optional: true,
    87  									},
    88  								},
    89  							},
    90  						},
    91  						"disk_autoresize": &schema.Schema{
    92  							Type:     schema.TypeBool,
    93  							Optional: true,
    94  						},
    95  						"disk_size": &schema.Schema{
    96  							Type:     schema.TypeInt,
    97  							Optional: true,
    98  						},
    99  						"disk_type": &schema.Schema{
   100  							Type:     schema.TypeString,
   101  							Optional: true,
   102  						},
   103  						"ip_configuration": &schema.Schema{
   104  							Type:     schema.TypeList,
   105  							Optional: true,
   106  							Elem: &schema.Resource{
   107  								Schema: map[string]*schema.Schema{
   108  									"authorized_networks": &schema.Schema{
   109  										Type:     schema.TypeList,
   110  										Optional: true,
   111  										Elem: &schema.Resource{
   112  											Schema: map[string]*schema.Schema{
   113  												"expiration_time": &schema.Schema{
   114  													Type:     schema.TypeString,
   115  													Optional: true,
   116  												},
   117  												"name": &schema.Schema{
   118  													Type:     schema.TypeString,
   119  													Optional: true,
   120  												},
   121  												"value": &schema.Schema{
   122  													Type:     schema.TypeString,
   123  													Optional: true,
   124  												},
   125  											},
   126  										},
   127  									},
   128  									"ipv4_enabled": &schema.Schema{
   129  										Type:     schema.TypeBool,
   130  										Optional: true,
   131  									},
   132  									"require_ssl": &schema.Schema{
   133  										Type:     schema.TypeBool,
   134  										Optional: true,
   135  									},
   136  								},
   137  							},
   138  						},
   139  						"location_preference": &schema.Schema{
   140  							Type:     schema.TypeList,
   141  							Optional: true,
   142  							Elem: &schema.Resource{
   143  								Schema: map[string]*schema.Schema{
   144  									"follow_gae_application": &schema.Schema{
   145  										Type:     schema.TypeString,
   146  										Optional: true,
   147  									},
   148  									"zone": &schema.Schema{
   149  										Type:     schema.TypeString,
   150  										Optional: true,
   151  									},
   152  								},
   153  							},
   154  						},
   155  						"maintenance_window": &schema.Schema{
   156  							Type:     schema.TypeList,
   157  							Optional: true,
   158  							MaxItems: 1,
   159  							Elem: &schema.Resource{
   160  								Schema: map[string]*schema.Schema{
   161  									"day": &schema.Schema{
   162  										Type:     schema.TypeInt,
   163  										Optional: true,
   164  										ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
   165  											return validateNumericRange(v, k, 1, 7)
   166  										},
   167  									},
   168  									"hour": &schema.Schema{
   169  										Type:     schema.TypeInt,
   170  										Optional: true,
   171  										ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
   172  											return validateNumericRange(v, k, 0, 23)
   173  										},
   174  									},
   175  									"update_track": &schema.Schema{
   176  										Type:     schema.TypeString,
   177  										Optional: true,
   178  									},
   179  								},
   180  							},
   181  						},
   182  						"pricing_plan": &schema.Schema{
   183  							Type:     schema.TypeString,
   184  							Optional: true,
   185  						},
   186  						"replication_type": &schema.Schema{
   187  							Type:     schema.TypeString,
   188  							Optional: true,
   189  						},
   190  					},
   191  				},
   192  			},
   193  
   194  			"database_version": &schema.Schema{
   195  				Type:     schema.TypeString,
   196  				Optional: true,
   197  				Default:  "MYSQL_5_6",
   198  				ForceNew: true,
   199  			},
   200  
   201  			"ip_address": &schema.Schema{
   202  				Type:     schema.TypeList,
   203  				Computed: true,
   204  				Elem: &schema.Resource{
   205  					Schema: map[string]*schema.Schema{
   206  						"ip_address": &schema.Schema{
   207  							Type:     schema.TypeString,
   208  							Computed: true,
   209  						},
   210  						"time_to_retire": &schema.Schema{
   211  							Type:     schema.TypeString,
   212  							Optional: true,
   213  							Computed: true,
   214  						},
   215  					},
   216  				},
   217  			},
   218  
   219  			"name": &schema.Schema{
   220  				Type:     schema.TypeString,
   221  				Optional: true,
   222  				Computed: true,
   223  				ForceNew: true,
   224  			},
   225  
   226  			"master_instance_name": &schema.Schema{
   227  				Type:     schema.TypeString,
   228  				Optional: true,
   229  				ForceNew: true,
   230  			},
   231  
   232  			"project": &schema.Schema{
   233  				Type:     schema.TypeString,
   234  				Optional: true,
   235  				ForceNew: true,
   236  			},
   237  
   238  			"replica_configuration": &schema.Schema{
   239  				Type:     schema.TypeList,
   240  				Optional: true,
   241  				Elem: &schema.Resource{
   242  					Schema: map[string]*schema.Schema{
   243  						"ca_certificate": &schema.Schema{
   244  							Type:     schema.TypeString,
   245  							Optional: true,
   246  							ForceNew: true,
   247  						},
   248  						"client_certificate": &schema.Schema{
   249  							Type:     schema.TypeString,
   250  							Optional: true,
   251  							ForceNew: true,
   252  						},
   253  						"client_key": &schema.Schema{
   254  							Type:     schema.TypeString,
   255  							Optional: true,
   256  							ForceNew: true,
   257  						},
   258  						"connect_retry_interval": &schema.Schema{
   259  							Type:     schema.TypeInt,
   260  							Optional: true,
   261  							ForceNew: true,
   262  						},
   263  						"dump_file_path": &schema.Schema{
   264  							Type:     schema.TypeString,
   265  							Optional: true,
   266  							ForceNew: true,
   267  						},
   268  						"master_heartbeat_period": &schema.Schema{
   269  							Type:     schema.TypeInt,
   270  							Optional: true,
   271  							ForceNew: true,
   272  						},
   273  						"password": &schema.Schema{
   274  							Type:     schema.TypeString,
   275  							Optional: true,
   276  							ForceNew: true,
   277  						},
   278  						"ssl_cipher": &schema.Schema{
   279  							Type:     schema.TypeString,
   280  							Optional: true,
   281  							ForceNew: true,
   282  						},
   283  						"username": &schema.Schema{
   284  							Type:     schema.TypeString,
   285  							Optional: true,
   286  							ForceNew: true,
   287  						},
   288  						"verify_server_certificate": &schema.Schema{
   289  							Type:     schema.TypeBool,
   290  							Optional: true,
   291  							ForceNew: true,
   292  						},
   293  					},
   294  				},
   295  			},
   296  
   297  			"self_link": &schema.Schema{
   298  				Type:     schema.TypeString,
   299  				Computed: true,
   300  			},
   301  		},
   302  	}
   303  }
   304  
   305  func resourceSqlDatabaseInstanceCreate(d *schema.ResourceData, meta interface{}) error {
   306  	config := meta.(*Config)
   307  
   308  	project, err := getProject(d, config)
   309  	if err != nil {
   310  		return err
   311  	}
   312  
   313  	region := d.Get("region").(string)
   314  	databaseVersion := d.Get("database_version").(string)
   315  
   316  	_settingsList := d.Get("settings").([]interface{})
   317  	if len(_settingsList) > 1 {
   318  		return fmt.Errorf("At most one settings block is allowed")
   319  	}
   320  
   321  	_settings := _settingsList[0].(map[string]interface{})
   322  	settings := &sqladmin.Settings{
   323  		Tier: _settings["tier"].(string),
   324  	}
   325  
   326  	if v, ok := _settings["activation_policy"]; ok {
   327  		settings.ActivationPolicy = v.(string)
   328  	}
   329  
   330  	if v, ok := _settings["authorized_gae_applications"]; ok {
   331  		settings.AuthorizedGaeApplications = make([]string, 0)
   332  		for _, app := range v.([]interface{}) {
   333  			settings.AuthorizedGaeApplications = append(settings.AuthorizedGaeApplications,
   334  				app.(string))
   335  		}
   336  	}
   337  
   338  	if v, ok := _settings["backup_configuration"]; ok {
   339  		_backupConfigurationList := v.([]interface{})
   340  		if len(_backupConfigurationList) > 1 {
   341  			return fmt.Errorf("At most one backup_configuration block is allowed")
   342  		}
   343  
   344  		if len(_backupConfigurationList) == 1 && _backupConfigurationList[0] != nil {
   345  			settings.BackupConfiguration = &sqladmin.BackupConfiguration{}
   346  			_backupConfiguration := _backupConfigurationList[0].(map[string]interface{})
   347  
   348  			if vp, okp := _backupConfiguration["binary_log_enabled"]; okp {
   349  				settings.BackupConfiguration.BinaryLogEnabled = vp.(bool)
   350  			}
   351  
   352  			if vp, okp := _backupConfiguration["enabled"]; okp {
   353  				settings.BackupConfiguration.Enabled = vp.(bool)
   354  			}
   355  
   356  			if vp, okp := _backupConfiguration["start_time"]; okp {
   357  				settings.BackupConfiguration.StartTime = vp.(string)
   358  			}
   359  		}
   360  	}
   361  
   362  	if v, ok := _settings["crash_safe_replication"]; ok {
   363  		settings.CrashSafeReplicationEnabled = v.(bool)
   364  	}
   365  
   366  	if v, ok := _settings["disk_autoresize"]; ok && v.(bool) {
   367  		settings.StorageAutoResize = v.(bool)
   368  	}
   369  
   370  	if v, ok := _settings["disk_size"]; ok && v.(int) > 0 {
   371  		settings.DataDiskSizeGb = int64(v.(int))
   372  	}
   373  
   374  	if v, ok := _settings["disk_type"]; ok && len(v.(string)) > 0 {
   375  		settings.DataDiskType = v.(string)
   376  	}
   377  
   378  	if v, ok := _settings["database_flags"]; ok {
   379  		settings.DatabaseFlags = make([]*sqladmin.DatabaseFlags, 0)
   380  		_databaseFlagsList := v.([]interface{})
   381  		for _, _flag := range _databaseFlagsList {
   382  			_entry := _flag.(map[string]interface{})
   383  			flag := &sqladmin.DatabaseFlags{}
   384  			if vp, okp := _entry["name"]; okp {
   385  				flag.Name = vp.(string)
   386  			}
   387  
   388  			if vp, okp := _entry["value"]; okp {
   389  				flag.Value = vp.(string)
   390  			}
   391  
   392  			settings.DatabaseFlags = append(settings.DatabaseFlags, flag)
   393  		}
   394  	}
   395  
   396  	if v, ok := _settings["ip_configuration"]; ok {
   397  		_ipConfigurationList := v.([]interface{})
   398  		if len(_ipConfigurationList) > 1 {
   399  			return fmt.Errorf("At most one ip_configuration block is allowed")
   400  		}
   401  
   402  		if len(_ipConfigurationList) == 1 && _ipConfigurationList[0] != nil {
   403  			settings.IpConfiguration = &sqladmin.IpConfiguration{}
   404  			_ipConfiguration := _ipConfigurationList[0].(map[string]interface{})
   405  
   406  			if vp, okp := _ipConfiguration["ipv4_enabled"]; okp {
   407  				settings.IpConfiguration.Ipv4Enabled = vp.(bool)
   408  			}
   409  
   410  			if vp, okp := _ipConfiguration["require_ssl"]; okp {
   411  				settings.IpConfiguration.RequireSsl = vp.(bool)
   412  			}
   413  
   414  			if vp, okp := _ipConfiguration["authorized_networks"]; okp {
   415  				settings.IpConfiguration.AuthorizedNetworks = make([]*sqladmin.AclEntry, 0)
   416  				_authorizedNetworksList := vp.([]interface{})
   417  				for _, _acl := range _authorizedNetworksList {
   418  					_entry := _acl.(map[string]interface{})
   419  					entry := &sqladmin.AclEntry{}
   420  
   421  					if vpp, okpp := _entry["expiration_time"]; okpp {
   422  						entry.ExpirationTime = vpp.(string)
   423  					}
   424  
   425  					if vpp, okpp := _entry["name"]; okpp {
   426  						entry.Name = vpp.(string)
   427  					}
   428  
   429  					if vpp, okpp := _entry["value"]; okpp {
   430  						entry.Value = vpp.(string)
   431  					}
   432  
   433  					settings.IpConfiguration.AuthorizedNetworks = append(
   434  						settings.IpConfiguration.AuthorizedNetworks, entry)
   435  				}
   436  			}
   437  		}
   438  	}
   439  
   440  	if v, ok := _settings["location_preference"]; ok {
   441  		_locationPreferenceList := v.([]interface{})
   442  		if len(_locationPreferenceList) > 1 {
   443  			return fmt.Errorf("At most one location_preference block is allowed")
   444  		}
   445  
   446  		if len(_locationPreferenceList) == 1 && _locationPreferenceList[0] != nil {
   447  			settings.LocationPreference = &sqladmin.LocationPreference{}
   448  			_locationPreference := _locationPreferenceList[0].(map[string]interface{})
   449  
   450  			if vp, okp := _locationPreference["follow_gae_application"]; okp {
   451  				settings.LocationPreference.FollowGaeApplication = vp.(string)
   452  			}
   453  
   454  			if vp, okp := _locationPreference["zone"]; okp {
   455  				settings.LocationPreference.Zone = vp.(string)
   456  			}
   457  		}
   458  	}
   459  
   460  	if v, ok := _settings["maintenance_window"]; ok && len(v.([]interface{})) > 0 {
   461  		settings.MaintenanceWindow = &sqladmin.MaintenanceWindow{}
   462  		_maintenanceWindow := v.([]interface{})[0].(map[string]interface{})
   463  
   464  		if vp, okp := _maintenanceWindow["day"]; okp {
   465  			settings.MaintenanceWindow.Day = int64(vp.(int))
   466  		}
   467  
   468  		if vp, okp := _maintenanceWindow["hour"]; okp {
   469  			settings.MaintenanceWindow.Hour = int64(vp.(int))
   470  		}
   471  
   472  		if vp, ok := _maintenanceWindow["update_track"]; ok {
   473  			if len(vp.(string)) > 0 {
   474  				settings.MaintenanceWindow.UpdateTrack = vp.(string)
   475  			}
   476  		}
   477  	}
   478  
   479  	if v, ok := _settings["pricing_plan"]; ok {
   480  		settings.PricingPlan = v.(string)
   481  	}
   482  
   483  	if v, ok := _settings["replication_type"]; ok {
   484  		settings.ReplicationType = v.(string)
   485  	}
   486  
   487  	instance := &sqladmin.DatabaseInstance{
   488  		Region:          region,
   489  		Settings:        settings,
   490  		DatabaseVersion: databaseVersion,
   491  	}
   492  
   493  	if v, ok := d.GetOk("name"); ok {
   494  		instance.Name = v.(string)
   495  	} else {
   496  		instance.Name = resource.UniqueId()
   497  		d.Set("name", instance.Name)
   498  	}
   499  
   500  	if v, ok := d.GetOk("replica_configuration"); ok {
   501  		_replicaConfigurationList := v.([]interface{})
   502  		if len(_replicaConfigurationList) > 1 {
   503  			return fmt.Errorf("Only one replica_configuration block may be defined")
   504  		}
   505  
   506  		if len(_replicaConfigurationList) == 1 && _replicaConfigurationList[0] != nil {
   507  			replicaConfiguration := &sqladmin.ReplicaConfiguration{}
   508  			mySqlReplicaConfiguration := &sqladmin.MySqlReplicaConfiguration{}
   509  			_replicaConfiguration := _replicaConfigurationList[0].(map[string]interface{})
   510  
   511  			if vp, okp := _replicaConfiguration["ca_certificate"]; okp {
   512  				mySqlReplicaConfiguration.CaCertificate = vp.(string)
   513  			}
   514  
   515  			if vp, okp := _replicaConfiguration["client_certificate"]; okp {
   516  				mySqlReplicaConfiguration.ClientCertificate = vp.(string)
   517  			}
   518  
   519  			if vp, okp := _replicaConfiguration["client_key"]; okp {
   520  				mySqlReplicaConfiguration.ClientKey = vp.(string)
   521  			}
   522  
   523  			if vp, okp := _replicaConfiguration["connect_retry_interval"]; okp {
   524  				mySqlReplicaConfiguration.ConnectRetryInterval = int64(vp.(int))
   525  			}
   526  
   527  			if vp, okp := _replicaConfiguration["dump_file_path"]; okp {
   528  				mySqlReplicaConfiguration.DumpFilePath = vp.(string)
   529  			}
   530  
   531  			if vp, okp := _replicaConfiguration["master_heartbeat_period"]; okp {
   532  				mySqlReplicaConfiguration.MasterHeartbeatPeriod = int64(vp.(int))
   533  			}
   534  
   535  			if vp, okp := _replicaConfiguration["password"]; okp {
   536  				mySqlReplicaConfiguration.Password = vp.(string)
   537  			}
   538  
   539  			if vp, okp := _replicaConfiguration["ssl_cipher"]; okp {
   540  				mySqlReplicaConfiguration.SslCipher = vp.(string)
   541  			}
   542  
   543  			if vp, okp := _replicaConfiguration["username"]; okp {
   544  				mySqlReplicaConfiguration.Username = vp.(string)
   545  			}
   546  
   547  			if vp, okp := _replicaConfiguration["verify_server_certificate"]; okp {
   548  				mySqlReplicaConfiguration.VerifyServerCertificate = vp.(bool)
   549  			}
   550  
   551  			replicaConfiguration.MysqlReplicaConfiguration = mySqlReplicaConfiguration
   552  			instance.ReplicaConfiguration = replicaConfiguration
   553  		}
   554  	}
   555  
   556  	if v, ok := d.GetOk("master_instance_name"); ok {
   557  		instance.MasterInstanceName = v.(string)
   558  	}
   559  
   560  	op, err := config.clientSqlAdmin.Instances.Insert(project, instance).Do()
   561  	if err != nil {
   562  		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 409 {
   563  			return fmt.Errorf("Error, the name %s is unavailable because it was used recently", instance.Name)
   564  		} else {
   565  			return fmt.Errorf("Error, failed to create instance %s: %s", instance.Name, err)
   566  		}
   567  	}
   568  
   569  	err = sqladminOperationWait(config, op, "Create Instance")
   570  	if err != nil {
   571  		return err
   572  	}
   573  
   574  	err = resourceSqlDatabaseInstanceRead(d, meta)
   575  	if err != nil {
   576  		return err
   577  	}
   578  
   579  	// If a root user exists with a wildcard ('%') hostname, delete it.
   580  	users, err := config.clientSqlAdmin.Users.List(project, instance.Name).Do()
   581  	if err != nil {
   582  		return fmt.Errorf("Error, attempting to list users associated with instance %s: %s", instance.Name, err)
   583  	}
   584  	for _, u := range users.Items {
   585  		if u.Name == "root" && u.Host == "%" {
   586  			op, err = config.clientSqlAdmin.Users.Delete(project, instance.Name, u.Host, u.Name).Do()
   587  			if err != nil {
   588  				return fmt.Errorf("Error, failed to delete default 'root'@'*' user, but the database was created successfully: %s", err)
   589  			}
   590  			err = sqladminOperationWait(config, op, "Delete default root User")
   591  			if err != nil {
   592  				return err
   593  			}
   594  		}
   595  	}
   596  
   597  	return nil
   598  }
   599  
   600  func resourceSqlDatabaseInstanceRead(d *schema.ResourceData, meta interface{}) error {
   601  	config := meta.(*Config)
   602  
   603  	project, err := getProject(d, config)
   604  	if err != nil {
   605  		return err
   606  	}
   607  
   608  	instance, err := config.clientSqlAdmin.Instances.Get(project,
   609  		d.Get("name").(string)).Do()
   610  
   611  	if err != nil {
   612  		return handleNotFoundError(err, d, fmt.Sprintf("SQL Database Instance %q", d.Get("name").(string)))
   613  	}
   614  
   615  	_settingsList := d.Get("settings").([]interface{})
   616  	_settings := _settingsList[0].(map[string]interface{})
   617  
   618  	settings := instance.Settings
   619  	_settings["version"] = settings.SettingsVersion
   620  	_settings["tier"] = settings.Tier
   621  
   622  	// Take care to only update attributes that the user has defined explicitly
   623  	if v, ok := _settings["activation_policy"]; ok && len(v.(string)) > 0 {
   624  		_settings["activation_policy"] = settings.ActivationPolicy
   625  	}
   626  
   627  	if v, ok := _settings["authorized_gae_applications"]; ok && len(v.([]interface{})) > 0 {
   628  		_authorized_gae_applications := make([]interface{}, 0)
   629  		for _, app := range settings.AuthorizedGaeApplications {
   630  			_authorized_gae_applications = append(_authorized_gae_applications, app)
   631  		}
   632  		_settings["authorized_gae_applications"] = _authorized_gae_applications
   633  	}
   634  
   635  	if v, ok := _settings["backup_configuration"]; ok {
   636  		_backupConfigurationList := v.([]interface{})
   637  		if len(_backupConfigurationList) > 1 {
   638  			return fmt.Errorf("At most one backup_configuration block is allowed")
   639  		}
   640  
   641  		if len(_backupConfigurationList) == 1 && _backupConfigurationList[0] != nil {
   642  			_backupConfiguration := _backupConfigurationList[0].(map[string]interface{})
   643  
   644  			if vp, okp := _backupConfiguration["binary_log_enabled"]; okp && vp != nil {
   645  				_backupConfiguration["binary_log_enabled"] = settings.BackupConfiguration.BinaryLogEnabled
   646  			}
   647  
   648  			if vp, okp := _backupConfiguration["enabled"]; okp && vp != nil {
   649  				_backupConfiguration["enabled"] = settings.BackupConfiguration.Enabled
   650  			}
   651  
   652  			if vp, okp := _backupConfiguration["start_time"]; okp && len(vp.(string)) > 0 {
   653  				_backupConfiguration["start_time"] = settings.BackupConfiguration.StartTime
   654  			}
   655  
   656  			_backupConfigurationList[0] = _backupConfiguration
   657  			_settings["backup_configuration"] = _backupConfigurationList
   658  		}
   659  	}
   660  
   661  	if v, ok := _settings["crash_safe_replication"]; ok && v != nil {
   662  		_settings["crash_safe_replication"] = settings.CrashSafeReplicationEnabled
   663  	}
   664  
   665  	if v, ok := _settings["disk_autoresize"]; ok && v != nil {
   666  		if v.(bool) {
   667  			_settings["disk_autoresize"] = settings.StorageAutoResize
   668  		}
   669  	}
   670  
   671  	if v, ok := _settings["disk_size"]; ok && v != nil {
   672  		if v.(int) > 0 && settings.DataDiskSizeGb < int64(v.(int)) {
   673  			_settings["disk_size"] = settings.DataDiskSizeGb
   674  		}
   675  	}
   676  
   677  	if v, ok := _settings["disk_type"]; ok && v != nil {
   678  		if len(v.(string)) > 0 {
   679  			_settings["disk_type"] = settings.DataDiskType
   680  		}
   681  	}
   682  
   683  	if v, ok := _settings["database_flags"]; ok && len(v.([]interface{})) > 0 {
   684  		_flag_map := make(map[string]string)
   685  		// First keep track of localy defined flag pairs
   686  		for _, _flag := range _settings["database_flags"].([]interface{}) {
   687  			_entry := _flag.(map[string]interface{})
   688  			_flag_map[_entry["name"].(string)] = _entry["value"].(string)
   689  		}
   690  
   691  		_database_flags := make([]interface{}, 0)
   692  		// Next read the flag pairs from the server, and reinsert those that
   693  		// correspond to ones defined locally
   694  		for _, entry := range settings.DatabaseFlags {
   695  			if _, okp := _flag_map[entry.Name]; okp {
   696  				_entry := make(map[string]interface{})
   697  				_entry["name"] = entry.Name
   698  				_entry["value"] = entry.Value
   699  				_database_flags = append(_database_flags, _entry)
   700  			}
   701  		}
   702  		_settings["database_flags"] = _database_flags
   703  	}
   704  
   705  	if v, ok := _settings["ip_configuration"]; ok {
   706  		_ipConfigurationList := v.([]interface{})
   707  		if len(_ipConfigurationList) > 1 {
   708  			return fmt.Errorf("At most one ip_configuration block is allowed")
   709  		}
   710  
   711  		if len(_ipConfigurationList) == 1 && _ipConfigurationList[0] != nil {
   712  			_ipConfiguration := _ipConfigurationList[0].(map[string]interface{})
   713  
   714  			if vp, okp := _ipConfiguration["ipv4_enabled"]; okp && vp != nil {
   715  				_ipConfiguration["ipv4_enabled"] = settings.IpConfiguration.Ipv4Enabled
   716  			}
   717  
   718  			if vp, okp := _ipConfiguration["require_ssl"]; okp && vp != nil {
   719  				_ipConfiguration["require_ssl"] = settings.IpConfiguration.RequireSsl
   720  			}
   721  
   722  			if vp, okp := _ipConfiguration["authorized_networks"]; okp && vp != nil {
   723  				_authorizedNetworksList := vp.([]interface{})
   724  				_ipc_map := make(map[string]interface{})
   725  				// First keep track of locally defined ip configurations
   726  				for _, _ipc := range _authorizedNetworksList {
   727  					if _ipc == nil {
   728  						continue
   729  					}
   730  					_entry := _ipc.(map[string]interface{})
   731  					if _entry["value"] == nil {
   732  						continue
   733  					}
   734  					_value := make(map[string]interface{})
   735  					_value["name"] = _entry["name"]
   736  					_value["expiration_time"] = _entry["expiration_time"]
   737  					// We key on value, since that is the only required part of
   738  					// this 3-tuple
   739  					_ipc_map[_entry["value"].(string)] = _value
   740  				}
   741  				_authorized_networks := make([]interface{}, 0)
   742  				// Next read the network tuples from the server, and reinsert those that
   743  				// correspond to ones defined locally
   744  				for _, entry := range settings.IpConfiguration.AuthorizedNetworks {
   745  					if _, okp := _ipc_map[entry.Value]; okp {
   746  						_entry := make(map[string]interface{})
   747  						_entry["value"] = entry.Value
   748  						_entry["name"] = entry.Name
   749  						_entry["expiration_time"] = entry.ExpirationTime
   750  						_authorized_networks = append(_authorized_networks, _entry)
   751  					}
   752  				}
   753  				_ipConfiguration["authorized_networks"] = _authorized_networks
   754  			}
   755  			_ipConfigurationList[0] = _ipConfiguration
   756  			_settings["ip_configuration"] = _ipConfigurationList
   757  		}
   758  	}
   759  
   760  	if v, ok := _settings["location_preference"]; ok && len(v.([]interface{})) > 0 {
   761  		_locationPreferenceList := v.([]interface{})
   762  		if len(_locationPreferenceList) > 1 {
   763  			return fmt.Errorf("At most one location_preference block is allowed")
   764  		}
   765  
   766  		if len(_locationPreferenceList) == 1 && _locationPreferenceList[0] != nil &&
   767  			settings.LocationPreference != nil {
   768  			_locationPreference := _locationPreferenceList[0].(map[string]interface{})
   769  
   770  			if vp, okp := _locationPreference["follow_gae_application"]; okp && vp != nil {
   771  				_locationPreference["follow_gae_application"] =
   772  					settings.LocationPreference.FollowGaeApplication
   773  			}
   774  
   775  			if vp, okp := _locationPreference["zone"]; okp && vp != nil {
   776  				_locationPreference["zone"] = settings.LocationPreference.Zone
   777  			}
   778  
   779  			_locationPreferenceList[0] = _locationPreference
   780  			_settings["location_preference"] = _locationPreferenceList[0]
   781  		}
   782  	}
   783  
   784  	if v, ok := _settings["maintenance_window"]; ok && len(v.([]interface{})) > 0 &&
   785  		settings.MaintenanceWindow != nil {
   786  		_maintenanceWindow := v.([]interface{})[0].(map[string]interface{})
   787  
   788  		if vp, okp := _maintenanceWindow["day"]; okp && vp != nil {
   789  			_maintenanceWindow["day"] = settings.MaintenanceWindow.Day
   790  		}
   791  
   792  		if vp, okp := _maintenanceWindow["hour"]; okp && vp != nil {
   793  			_maintenanceWindow["hour"] = settings.MaintenanceWindow.Hour
   794  		}
   795  
   796  		if vp, ok := _maintenanceWindow["update_track"]; ok && vp != nil {
   797  			if len(vp.(string)) > 0 {
   798  				_maintenanceWindow["update_track"] = settings.MaintenanceWindow.UpdateTrack
   799  			}
   800  		}
   801  	}
   802  
   803  	if v, ok := _settings["pricing_plan"]; ok && len(v.(string)) > 0 {
   804  		_settings["pricing_plan"] = settings.PricingPlan
   805  	}
   806  
   807  	if v, ok := _settings["replication_type"]; ok && len(v.(string)) > 0 {
   808  		_settings["replication_type"] = settings.ReplicationType
   809  	}
   810  
   811  	_settingsList[0] = _settings
   812  	d.Set("settings", _settingsList)
   813  
   814  	if v, ok := d.GetOk("replica_configuration"); ok && v != nil {
   815  		_replicaConfigurationList := v.([]interface{})
   816  		if len(_replicaConfigurationList) > 1 {
   817  			return fmt.Errorf("Only one replica_configuration block may be defined")
   818  		}
   819  
   820  		if len(_replicaConfigurationList) == 1 && _replicaConfigurationList[0] != nil {
   821  			mySqlReplicaConfiguration := instance.ReplicaConfiguration.MysqlReplicaConfiguration
   822  			_replicaConfiguration := _replicaConfigurationList[0].(map[string]interface{})
   823  
   824  			if vp, okp := _replicaConfiguration["ca_certificate"]; okp && vp != nil {
   825  				_replicaConfiguration["ca_certificate"] = mySqlReplicaConfiguration.CaCertificate
   826  			}
   827  
   828  			if vp, okp := _replicaConfiguration["client_certificate"]; okp && vp != nil {
   829  				_replicaConfiguration["client_certificate"] = mySqlReplicaConfiguration.ClientCertificate
   830  			}
   831  
   832  			if vp, okp := _replicaConfiguration["client_key"]; okp && vp != nil {
   833  				_replicaConfiguration["client_key"] = mySqlReplicaConfiguration.ClientKey
   834  			}
   835  
   836  			if vp, okp := _replicaConfiguration["connect_retry_interval"]; okp && vp != nil {
   837  				_replicaConfiguration["connect_retry_interval"] = mySqlReplicaConfiguration.ConnectRetryInterval
   838  			}
   839  
   840  			if vp, okp := _replicaConfiguration["dump_file_path"]; okp && vp != nil {
   841  				_replicaConfiguration["dump_file_path"] = mySqlReplicaConfiguration.DumpFilePath
   842  			}
   843  
   844  			if vp, okp := _replicaConfiguration["master_heartbeat_period"]; okp && vp != nil {
   845  				_replicaConfiguration["master_heartbeat_period"] = mySqlReplicaConfiguration.MasterHeartbeatPeriod
   846  			}
   847  
   848  			if vp, okp := _replicaConfiguration["password"]; okp && vp != nil {
   849  				_replicaConfiguration["password"] = mySqlReplicaConfiguration.Password
   850  			}
   851  
   852  			if vp, okp := _replicaConfiguration["ssl_cipher"]; okp && vp != nil {
   853  				_replicaConfiguration["ssl_cipher"] = mySqlReplicaConfiguration.SslCipher
   854  			}
   855  
   856  			if vp, okp := _replicaConfiguration["username"]; okp && vp != nil {
   857  				_replicaConfiguration["username"] = mySqlReplicaConfiguration.Username
   858  			}
   859  
   860  			if vp, okp := _replicaConfiguration["verify_server_certificate"]; okp && vp != nil {
   861  				_replicaConfiguration["verify_server_certificate"] = mySqlReplicaConfiguration.VerifyServerCertificate
   862  			}
   863  
   864  			_replicaConfigurationList[0] = _replicaConfiguration
   865  			d.Set("replica_configuration", _replicaConfigurationList)
   866  		}
   867  	}
   868  
   869  	_ipAddresses := make([]interface{}, len(instance.IpAddresses))
   870  
   871  	for i, ip := range instance.IpAddresses {
   872  		_ipAddress := make(map[string]interface{})
   873  
   874  		_ipAddress["ip_address"] = ip.IpAddress
   875  		_ipAddress["time_to_retire"] = ip.TimeToRetire
   876  
   877  		_ipAddresses[i] = _ipAddress
   878  	}
   879  
   880  	d.Set("ip_address", _ipAddresses)
   881  
   882  	if v, ok := d.GetOk("master_instance_name"); ok && v != nil {
   883  		d.Set("master_instance_name", strings.TrimPrefix(instance.MasterInstanceName, project+":"))
   884  	}
   885  
   886  	d.Set("self_link", instance.SelfLink)
   887  	d.SetId(instance.Name)
   888  
   889  	return nil
   890  }
   891  
   892  func resourceSqlDatabaseInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
   893  	config := meta.(*Config)
   894  
   895  	project, err := getProject(d, config)
   896  	if err != nil {
   897  		return err
   898  	}
   899  
   900  	d.Partial(true)
   901  
   902  	instance, err := config.clientSqlAdmin.Instances.Get(project,
   903  		d.Get("name").(string)).Do()
   904  
   905  	if err != nil {
   906  		return fmt.Errorf("Error retrieving instance %s: %s",
   907  			d.Get("name").(string), err)
   908  	}
   909  
   910  	if d.HasChange("settings") {
   911  		_oListCast, _settingsListCast := d.GetChange("settings")
   912  		_oList := _oListCast.([]interface{})
   913  		_o := _oList[0].(map[string]interface{})
   914  		_settingsList := _settingsListCast.([]interface{})
   915  		if len(_settingsList) > 1 {
   916  			return fmt.Errorf("At most one settings block is allowed")
   917  		}
   918  
   919  		_settings := _settingsList[0].(map[string]interface{})
   920  		settings := &sqladmin.Settings{
   921  			Tier:            _settings["tier"].(string),
   922  			SettingsVersion: instance.Settings.SettingsVersion,
   923  		}
   924  
   925  		if v, ok := _settings["activation_policy"]; ok {
   926  			settings.ActivationPolicy = v.(string)
   927  		}
   928  
   929  		if v, ok := _settings["authorized_gae_applications"]; ok {
   930  			settings.AuthorizedGaeApplications = make([]string, 0)
   931  			for _, app := range v.([]interface{}) {
   932  				settings.AuthorizedGaeApplications = append(settings.AuthorizedGaeApplications,
   933  					app.(string))
   934  			}
   935  		}
   936  
   937  		if v, ok := _settings["backup_configuration"]; ok {
   938  			_backupConfigurationList := v.([]interface{})
   939  			if len(_backupConfigurationList) > 1 {
   940  				return fmt.Errorf("At most one backup_configuration block is allowed")
   941  			}
   942  
   943  			if len(_backupConfigurationList) == 1 && _backupConfigurationList[0] != nil {
   944  				settings.BackupConfiguration = &sqladmin.BackupConfiguration{}
   945  				_backupConfiguration := _backupConfigurationList[0].(map[string]interface{})
   946  
   947  				if vp, okp := _backupConfiguration["binary_log_enabled"]; okp {
   948  					settings.BackupConfiguration.BinaryLogEnabled = vp.(bool)
   949  				}
   950  
   951  				if vp, okp := _backupConfiguration["enabled"]; okp {
   952  					settings.BackupConfiguration.Enabled = vp.(bool)
   953  				}
   954  
   955  				if vp, okp := _backupConfiguration["start_time"]; okp {
   956  					settings.BackupConfiguration.StartTime = vp.(string)
   957  				}
   958  			}
   959  		}
   960  
   961  		if v, ok := _settings["crash_safe_replication"]; ok {
   962  			settings.CrashSafeReplicationEnabled = v.(bool)
   963  		}
   964  
   965  		if v, ok := _settings["disk_autoresize"]; ok && v.(bool) {
   966  			settings.StorageAutoResize = v.(bool)
   967  		}
   968  
   969  		if v, ok := _settings["disk_size"]; ok {
   970  			if v.(int) > 0 && int64(v.(int)) > instance.Settings.DataDiskSizeGb {
   971  				settings.DataDiskSizeGb = int64(v.(int))
   972  			}
   973  		}
   974  
   975  		if v, ok := _settings["disk_type"]; ok && len(v.(string)) > 0 {
   976  			settings.DataDiskType = v.(string)
   977  		}
   978  
   979  		_oldDatabaseFlags := make([]interface{}, 0)
   980  		if ov, ook := _o["database_flags"]; ook {
   981  			_oldDatabaseFlags = ov.([]interface{})
   982  		}
   983  
   984  		if v, ok := _settings["database_flags"]; ok || len(_oldDatabaseFlags) > 0 {
   985  			oldDatabaseFlags := settings.DatabaseFlags
   986  			settings.DatabaseFlags = make([]*sqladmin.DatabaseFlags, 0)
   987  			_databaseFlagsList := make([]interface{}, 0)
   988  			if v != nil {
   989  				_databaseFlagsList = v.([]interface{})
   990  			}
   991  
   992  			_odbf_map := make(map[string]interface{})
   993  			for _, _dbf := range _oldDatabaseFlags {
   994  				_entry := _dbf.(map[string]interface{})
   995  				_odbf_map[_entry["name"].(string)] = true
   996  			}
   997  
   998  			// First read the flags from the server, and reinsert those that
   999  			// were not previously defined
  1000  			for _, entry := range oldDatabaseFlags {
  1001  				_, ok_old := _odbf_map[entry.Name]
  1002  				if !ok_old {
  1003  					settings.DatabaseFlags = append(
  1004  						settings.DatabaseFlags, entry)
  1005  				}
  1006  			}
  1007  			// finally, insert only those that were previously defined
  1008  			// and are still defined.
  1009  			for _, _flag := range _databaseFlagsList {
  1010  				_entry := _flag.(map[string]interface{})
  1011  				flag := &sqladmin.DatabaseFlags{}
  1012  				if vp, okp := _entry["name"]; okp {
  1013  					flag.Name = vp.(string)
  1014  				}
  1015  
  1016  				if vp, okp := _entry["value"]; okp {
  1017  					flag.Value = vp.(string)
  1018  				}
  1019  
  1020  				settings.DatabaseFlags = append(settings.DatabaseFlags, flag)
  1021  			}
  1022  		}
  1023  
  1024  		if v, ok := _settings["ip_configuration"]; ok {
  1025  			_ipConfigurationList := v.([]interface{})
  1026  			if len(_ipConfigurationList) > 1 {
  1027  				return fmt.Errorf("At most one ip_configuration block is allowed")
  1028  			}
  1029  
  1030  			if len(_ipConfigurationList) == 1 && _ipConfigurationList[0] != nil {
  1031  				settings.IpConfiguration = &sqladmin.IpConfiguration{}
  1032  				_ipConfiguration := _ipConfigurationList[0].(map[string]interface{})
  1033  
  1034  				if vp, okp := _ipConfiguration["ipv4_enabled"]; okp {
  1035  					settings.IpConfiguration.Ipv4Enabled = vp.(bool)
  1036  				}
  1037  
  1038  				if vp, okp := _ipConfiguration["require_ssl"]; okp {
  1039  					settings.IpConfiguration.RequireSsl = vp.(bool)
  1040  				}
  1041  
  1042  				_oldAuthorizedNetworkList := make([]interface{}, 0)
  1043  				if ov, ook := _o["ip_configuration"]; ook {
  1044  					_oldIpConfList := ov.([]interface{})
  1045  					if len(_oldIpConfList) > 0 {
  1046  						_oldIpConf := _oldIpConfList[0].(map[string]interface{})
  1047  						if ovp, ookp := _oldIpConf["authorized_networks"]; ookp {
  1048  							_oldAuthorizedNetworkList = ovp.([]interface{})
  1049  						}
  1050  					}
  1051  				}
  1052  
  1053  				if vp, okp := _ipConfiguration["authorized_networks"]; okp || len(_oldAuthorizedNetworkList) > 0 {
  1054  					oldAuthorizedNetworks := instance.Settings.IpConfiguration.AuthorizedNetworks
  1055  					settings.IpConfiguration.AuthorizedNetworks = make([]*sqladmin.AclEntry, 0)
  1056  
  1057  					_authorizedNetworksList := make([]interface{}, 0)
  1058  					if vp != nil {
  1059  						_authorizedNetworksList = vp.([]interface{})
  1060  					}
  1061  					_oipc_map := make(map[string]interface{})
  1062  					for _, _ipc := range _oldAuthorizedNetworkList {
  1063  						_entry := _ipc.(map[string]interface{})
  1064  						_oipc_map[_entry["value"].(string)] = true
  1065  					}
  1066  					// Next read the network tuples from the server, and reinsert those that
  1067  					// were not previously defined
  1068  					for _, entry := range oldAuthorizedNetworks {
  1069  						_, ok_old := _oipc_map[entry.Value]
  1070  						if !ok_old {
  1071  							settings.IpConfiguration.AuthorizedNetworks = append(
  1072  								settings.IpConfiguration.AuthorizedNetworks, entry)
  1073  						}
  1074  					}
  1075  					// finally, update old entries and insert new ones
  1076  					// and are still defined.
  1077  					for _, _ipc := range _authorizedNetworksList {
  1078  						_entry := _ipc.(map[string]interface{})
  1079  						entry := &sqladmin.AclEntry{}
  1080  
  1081  						if vpp, okpp := _entry["expiration_time"]; okpp {
  1082  							entry.ExpirationTime = vpp.(string)
  1083  						}
  1084  
  1085  						if vpp, okpp := _entry["name"]; okpp {
  1086  							entry.Name = vpp.(string)
  1087  						}
  1088  
  1089  						if vpp, okpp := _entry["value"]; okpp {
  1090  							entry.Value = vpp.(string)
  1091  						}
  1092  
  1093  						settings.IpConfiguration.AuthorizedNetworks = append(
  1094  							settings.IpConfiguration.AuthorizedNetworks, entry)
  1095  					}
  1096  				}
  1097  			}
  1098  		}
  1099  
  1100  		if v, ok := _settings["location_preference"]; ok {
  1101  			_locationPreferenceList := v.([]interface{})
  1102  			if len(_locationPreferenceList) > 1 {
  1103  				return fmt.Errorf("At most one location_preference block is allowed")
  1104  			}
  1105  
  1106  			if len(_locationPreferenceList) == 1 && _locationPreferenceList[0] != nil {
  1107  				settings.LocationPreference = &sqladmin.LocationPreference{}
  1108  				_locationPreference := _locationPreferenceList[0].(map[string]interface{})
  1109  
  1110  				if vp, okp := _locationPreference["follow_gae_application"]; okp {
  1111  					settings.LocationPreference.FollowGaeApplication = vp.(string)
  1112  				}
  1113  
  1114  				if vp, okp := _locationPreference["zone"]; okp {
  1115  					settings.LocationPreference.Zone = vp.(string)
  1116  				}
  1117  			}
  1118  		}
  1119  
  1120  		if v, ok := _settings["maintenance_window"]; ok && len(v.([]interface{})) > 0 {
  1121  			settings.MaintenanceWindow = &sqladmin.MaintenanceWindow{}
  1122  			_maintenanceWindow := v.([]interface{})[0].(map[string]interface{})
  1123  
  1124  			if vp, okp := _maintenanceWindow["day"]; okp {
  1125  				settings.MaintenanceWindow.Day = int64(vp.(int))
  1126  			}
  1127  
  1128  			if vp, okp := _maintenanceWindow["hour"]; okp {
  1129  				settings.MaintenanceWindow.Hour = int64(vp.(int))
  1130  			}
  1131  
  1132  			if vp, ok := _maintenanceWindow["update_track"]; ok {
  1133  				if len(vp.(string)) > 0 {
  1134  					settings.MaintenanceWindow.UpdateTrack = vp.(string)
  1135  				}
  1136  			}
  1137  		}
  1138  
  1139  		if v, ok := _settings["pricing_plan"]; ok {
  1140  			settings.PricingPlan = v.(string)
  1141  		}
  1142  
  1143  		if v, ok := _settings["replication_type"]; ok {
  1144  			settings.ReplicationType = v.(string)
  1145  		}
  1146  
  1147  		instance.Settings = settings
  1148  	}
  1149  
  1150  	d.Partial(false)
  1151  
  1152  	op, err := config.clientSqlAdmin.Instances.Update(project, instance.Name, instance).Do()
  1153  	if err != nil {
  1154  		return fmt.Errorf("Error, failed to update instance %s: %s", instance.Name, err)
  1155  	}
  1156  
  1157  	err = sqladminOperationWait(config, op, "Create Instance")
  1158  	if err != nil {
  1159  		return err
  1160  	}
  1161  
  1162  	return resourceSqlDatabaseInstanceRead(d, meta)
  1163  }
  1164  
  1165  func resourceSqlDatabaseInstanceDelete(d *schema.ResourceData, meta interface{}) error {
  1166  	config := meta.(*Config)
  1167  
  1168  	project, err := getProject(d, config)
  1169  	if err != nil {
  1170  		return err
  1171  	}
  1172  
  1173  	op, err := config.clientSqlAdmin.Instances.Delete(project, d.Get("name").(string)).Do()
  1174  
  1175  	if err != nil {
  1176  		return fmt.Errorf("Error, failed to delete instance %s: %s", d.Get("name").(string), err)
  1177  	}
  1178  
  1179  	err = sqladminOperationWait(config, op, "Delete Instance")
  1180  	if err != nil {
  1181  		return err
  1182  	}
  1183  
  1184  	return nil
  1185  }
  1186  
  1187  func validateNumericRange(v interface{}, k string, min int, max int) (ws []string, errors []error) {
  1188  	value := v.(int)
  1189  	if min > value || value > max {
  1190  		errors = append(errors, fmt.Errorf(
  1191  			"%q outside range %d-%d.", k, min, max))
  1192  	}
  1193  	return
  1194  }