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