github.com/nevins-b/terraform@v0.3.8-0.20170215184714-bbae22007d5a/builtin/providers/google/resource_sql_database_instance.go (about)

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