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