From b1fc6cd0036d125648f50d6e4ad05e4b51ca8c78 Mon Sep 17 00:00:00 2001 From: alex hemard Date: Wed, 1 Feb 2023 09:15:54 -0600 Subject: [PATCH] refactor(Cloud Databases): configuration uses cloud-databases-go-sdk (#4234) * refactor(Cloud Databases): configuration uses cloud-databases-go-sdk * address PR comments * remove unused bluemix client --- go.mod | 2 +- go.sum | 4 +- ibm/service/database/resource_ibm_database.go | 149 +++++++++++++----- .../resource_ibm_database_mysql_test.go | 43 +++-- .../resource_ibm_database_rabbitmq_test.go | 63 ++++---- 5 files changed, 165 insertions(+), 96 deletions(-) diff --git a/go.mod b/go.mod index 0def8b221e..f93fe2aa21 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/IBM/apigateway-go-sdk v0.0.0-20210714141226-a5d5d49caaca github.com/IBM/appconfiguration-go-admin-sdk v0.3.0 github.com/IBM/appid-management-go-sdk v0.0.0-20210908164609-dd0e0eaf732f - github.com/IBM/cloud-databases-go-sdk v0.3.0 + github.com/IBM/cloud-databases-go-sdk v0.3.1 github.com/IBM/cloudant-go-sdk v0.0.43 github.com/IBM/container-registry-go-sdk v0.0.15 github.com/IBM/continuous-delivery-go-sdk v1.0.4 diff --git a/go.sum b/go.sum index 6493d4c780..01d1dd920c 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,8 @@ github.com/IBM/appconfiguration-go-admin-sdk v0.3.0 h1:OqFxnDxro0JiRwHBKytCcseY2 github.com/IBM/appconfiguration-go-admin-sdk v0.3.0/go.mod h1:xPxAYhr/uywUIDEo/JqWbkUdTryPdzRdYBfUpA5IjoE= github.com/IBM/appid-management-go-sdk v0.0.0-20210908164609-dd0e0eaf732f h1:4c1kqY4GqmkQ+tO03rneDb74Tv7BhTj8jDiDB1p8mdM= github.com/IBM/appid-management-go-sdk v0.0.0-20210908164609-dd0e0eaf732f/go.mod h1:d22kTYY7RYBWcQlZpqrSdshpB/lJ16viWS5Sbjtlc8s= -github.com/IBM/cloud-databases-go-sdk v0.3.0 h1:yTCfBF05PjBLTuhrwBH5P1onCSls/vbJB2HawBjheOU= -github.com/IBM/cloud-databases-go-sdk v0.3.0/go.mod h1:ZOujnMABgw39Mr/5sFd16eniw9mSS4/if1Vht3m+F4M= +github.com/IBM/cloud-databases-go-sdk v0.3.1 h1:wmR9RX9aFUtW1EPrgHGvE6nruGilW8XrU1o//4lHuFM= +github.com/IBM/cloud-databases-go-sdk v0.3.1/go.mod h1:o05Dt04BOr+0ArQPeAEeZBBYK3Fe7vQwShX/6PJvh4Q= github.com/IBM/cloudant-go-sdk v0.0.43 h1:YxTy4RpAEezX32YIWnds76hrBREmO4u6IkBz1WylNuQ= github.com/IBM/cloudant-go-sdk v0.0.43/go.mod h1:WeYrJPaHTw19943ndWnVfwMIlZ5z0XUM2uEXNBrwZ1M= github.com/IBM/container-registry-go-sdk v0.0.15 h1:sfEXm4qNj9ZCwTlFOsdjF5P/lvajU/Sc22yNlzg0F9I= diff --git a/ibm/service/database/resource_ibm_database.go b/ibm/service/database/resource_ibm_database.go index 3b83f95223..ddc7590eec 100644 --- a/ibm/service/database/resource_ibm_database.go +++ b/ibm/service/database/resource_ibm_database.go @@ -1242,10 +1242,53 @@ func resourceIBMDatabaseInstanceDiff(_ context.Context, diff *schema.ResourceDif return fmt.Errorf("[ERROR] logical_replication_slot is only supported for databases-for-postgresql") } - _, configurationSet := diff.GetOk("configuration") + configJSON, configOk := diff.GetOk("configuration") - if (service != "databases-for-postgresql" && service != "databases-for-redis" && service != "databases-for-enterprisedb") && configurationSet { - return fmt.Errorf("[ERROR] configuration is not supported for %s", service) + if configOk { + var rawConfig map[string]json.RawMessage + err = json.Unmarshal([]byte(configJSON.(string)), &rawConfig) + if err != nil { + return fmt.Errorf("[ERROR] configuration JSON invalid\n%s", err) + } + + var unmarshalFn func(m map[string]json.RawMessage, result interface{}) (err error) + + var configuration clouddatabasesv5.ConfigurationIntf = new(clouddatabasesv5.Configuration) + + switch service { + case "databases-for-postgresql": + unmarshalFn = clouddatabasesv5.UnmarshalConfigurationPgConfiguration + case "databases-for-enterprisedb": + unmarshalFn = clouddatabasesv5.UnmarshalConfigurationPgConfiguration + case "databases-for-redis": + unmarshalFn = clouddatabasesv5.UnmarshalConfigurationRedisConfiguration + case "databases-for-mysql": + unmarshalFn = clouddatabasesv5.UnmarshalConfigurationMySQLConfiguration + case "messages-for-rabbitmq": + unmarshalFn = clouddatabasesv5.UnmarshalConfigurationRabbitMqConfiguration + default: + return fmt.Errorf("[ERROR] configuration is not supported for %s", service) + } + + err = core.UnmarshalModel(rawConfig, "", &configuration, unmarshalFn) + if err != nil { + return fmt.Errorf("[ERROR] configuration is invalid\n%s", err) + } + + b, _ := json.Marshal(configuration) + var result map[string]json.RawMessage + json.Unmarshal(b, &result) + + invalidFields := []string{} + for k, _ := range rawConfig { + if _, ok := result[k]; !ok { + invalidFields = append(invalidFields, k) + } + } + + if len(invalidFields) != 0 { + return fmt.Errorf("[ERROR] configuration contained invalid field(s): %s", invalidFields) + } } return nil @@ -1499,11 +1542,6 @@ func resourceIBMDatabaseInstanceCreate(context context.Context, d *schema.Resour instanceID := *instance.ID icdId := flex.EscapeUrlParm(instanceID) - icdClient, err := meta.(conns.ClientSession).ICDAPI() - if err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error getting database client settings: %s", err)) - } - if pw, ok := d.GetOk("adminpassword"); ok { adminPassword := pw.(string) @@ -1634,22 +1672,36 @@ func resourceIBMDatabaseInstanceCreate(context context.Context, d *schema.Resour } if config, ok := d.GetOk("configuration"); ok { - service := d.Get("service").(string) - if service == "databases-for-postgresql" || service == "databases-for-redis" || service == "databases-for-enterprisedb" { - var configuration interface{} - json.Unmarshal([]byte(config.(string)), &configuration) - configPayload := icdv4.ConfigurationReq{Configuration: configuration} - task, err := icdClient.Configurations().UpdateConfiguration(icdId, configPayload) - if err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error updating database (%s) configuration: %s", icdId, err)) - } - _, err = waitForDatabaseTaskComplete(task.Id, d, meta, d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return diag.FromErr(fmt.Errorf( - "[ERROR] Error waiting for database (%s) configuration update task to complete: %s", icdId, err)) - } - } else { - return diag.FromErr(fmt.Errorf("[ERROR] given database type %s is not configurable", service)) + var rawConfig map[string]json.RawMessage + err = json.Unmarshal([]byte(config.(string)), &rawConfig) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] configuration JSON invalid\n%s", err)) + } + + var configuration clouddatabasesv5.ConfigurationIntf = new(clouddatabasesv5.Configuration) + err = core.UnmarshalModel(rawConfig, "", &configuration, clouddatabasesv5.UnmarshalConfiguration) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] database configuration is invalid")) + } + + updateDatabaseConfigurationOptions := &clouddatabasesv5.UpdateDatabaseConfigurationOptions{ + ID: &instanceID, + Configuration: configuration, + } + + updateDatabaseConfigurationResponse, response, err := cloudDatabasesClient.UpdateDatabaseConfiguration(updateDatabaseConfigurationOptions) + + if err != nil { + return diag.FromErr(fmt.Errorf( + "[ERROR] Error updating database configuration failed %s\n%s", err, response)) + } + + taskID := *updateDatabaseConfigurationResponse.Task.ID + + _, err = waitForDatabaseTaskComplete(taskID, d, meta, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return diag.FromErr(fmt.Errorf( + "[ERROR] Error waiting for database (%s) configuration update task to complete: %s", icdId, err)) } } @@ -1960,28 +2012,41 @@ func resourceIBMDatabaseInstanceUpdate(context context.Context, d *schema.Resour return diag.FromErr(err) } } + if d.HasChange("configuration") { - service := d.Get("service").(string) - if service == "databases-for-postgresql" || service == "databases-for-redis" || service == "databases-for-enterprisedb" { - if s, ok := d.GetOk("configuration"); ok { - var configuration interface{} - json.Unmarshal([]byte(s.(string)), &configuration) - configPayload := icdv4.ConfigurationReq{Configuration: configuration} - task, err := icdClient.Configurations().UpdateConfiguration(icdId, configPayload) - if err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error updating database (%s) configuration: %s", icdId, err)) - } - _, err = waitForDatabaseTaskComplete(task.Id, d, meta, d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return diag.FromErr(fmt.Errorf( - "[ERROR] Error waiting for database (%s) configuration update task to complete: %s", icdId, err)) - } + if config, ok := d.GetOk("configuration"); ok { + var rawConfig map[string]json.RawMessage + err = json.Unmarshal([]byte(config.(string)), &rawConfig) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] configuration JSON invalid\n%s", err)) } - } else { - return diag.FromErr(fmt.Errorf("[ERROR] given database type %s is not configurable", service)) - } + var configuration clouddatabasesv5.ConfigurationIntf = new(clouddatabasesv5.Configuration) + err = core.UnmarshalModel(rawConfig, "", &configuration, clouddatabasesv5.UnmarshalConfiguration) + if err != nil { + return diag.FromErr(err) + } + + updateDatabaseConfigurationOptions := &clouddatabasesv5.UpdateDatabaseConfigurationOptions{ + ID: &instanceID, + Configuration: configuration, + } + + updateDatabaseConfigurationResponse, response, err := cloudDatabasesClient.UpdateDatabaseConfiguration(updateDatabaseConfigurationOptions) + + if err != nil { + return diag.FromErr(fmt.Errorf( + "[ERROR] Error updating database configuration failed %s\n%s", err, response)) + } + + taskID := *updateDatabaseConfigurationResponse.Task.ID + _, err = waitForDatabaseTaskComplete(taskID, d, meta, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return diag.FromErr(fmt.Errorf( + "[ERROR] Error waiting for database (%s) configuration update task to complete: %s", icdId, err)) + } + } } if d.HasChange("members_memory_allocation_mb") || d.HasChange("members_disk_allocation_mb") || d.HasChange("members_cpu_allocation_count") || d.HasChange("node_memory_allocation_mb") || d.HasChange("node_disk_allocation_mb") || d.HasChange("node_cpu_allocation_count") { diff --git a/ibm/service/database/resource_ibm_database_mysql_test.go b/ibm/service/database/resource_ibm_database_mysql_test.go index 5a93100930..423d48d800 100644 --- a/ibm/service/database/resource_ibm_database_mysql_test.go +++ b/ibm/service/database/resource_ibm_database_mysql_test.go @@ -17,7 +17,7 @@ func TestAccIBMMysqlDatabaseInstanceBasic(t *testing.T) { t.Parallel() databaseResourceGroup := "default" var databaseInstanceOne string - rnd := fmt.Sprintf("tf-mysql-%d", acctest.RandIntRange(10, 100)) + rnd := fmt.Sprintf("tf-mysql-%s", acctest.RandString(6)) testName := rnd name := "ibm_database." + testName @@ -70,13 +70,6 @@ func TestAccIBMMysqlDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, - { - ResourceName: name, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "wait_time_minutes", "plan_validation", "adminpassword"}, - }, }, }) } @@ -86,7 +79,7 @@ func testAccCheckIBMDatabaseInstanceMysqlBasic(databaseResourceGroup string, nam data "ibm_resource_group" "test_acc" { name = "%[1]s" } - + resource "ibm_database" "%[2]s" { resource_group_id = data.ibm_resource_group.test_acc.id name = "%[2]s" @@ -98,12 +91,12 @@ func testAccCheckIBMDatabaseInstanceMysqlBasic(databaseResourceGroup string, nam members_disk_allocation_mb = 61440 tags = ["one:two"] users { - name = "user123" - password = "password12" + name = "user123" + password = "password12" } allowlist { - address = "172.168.1.2/32" - description = "desc1" + address = "172.168.1.2/32" + description = "desc1" } timeouts { create = "120m" @@ -119,7 +112,7 @@ func testAccCheckIBMDatabaseInstanceMysqlFullyspecified(databaseResourceGroup st data "ibm_resource_group" "test_acc" { name = "%[1]s" } - + resource "ibm_database" "%[2]s" { resource_group_id = data.ibm_resource_group.test_acc.id name = "%[2]s" @@ -133,21 +126,27 @@ func testAccCheckIBMDatabaseInstanceMysqlFullyspecified(databaseResourceGroup st service_endpoints = "public-and-private" tags = ["one:two"] users { - name = "user123" - password = "password12" + name = "user123" + password = "password12" } users { - name = "user124" - password = "password12" + name = "user124" + password = "password12" } allowlist { - address = "172.168.1.2/32" - description = "desc1" + address = "172.168.1.2/32" + description = "desc1" } allowlist { - address = "172.168.1.1/32" - description = "desc" + address = "172.168.1.1/32" + description = "desc" + } + configuration = <