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