github.com/erriapo/terraform@v0.6.12-0.20160203182612-0340ea72354f/builtin/providers/google/resource_sql_database_instance.go (about)

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