From cfc3f26277d73a454063c5c6a35328f42d1123f9 Mon Sep 17 00:00:00 2001 From: Armand Kulsh <33414169+Gogen120@users.noreply.github.com> Date: Wed, 15 May 2024 19:06:50 +0300 Subject: [PATCH] Refactor DBaaS resources (#251) * Refactor DBaaS resources - Added new package waiters with wait function for DBaaS resources - Remove redundant usage of selMutexKV - Remove usage of flag ForceNew with False value as it is a default value - Replace an old MinTimeout value with calculated value on production - Add fl_size and invalid_values fields for Flavor and ConfigurationParameters data sources, respectively * Moved DBaaS resource schemas to the separate files * Fix linters issues * Fix review change requests - Add base schemas for datastore and database resources - Add required fields for each datastore type in corresponding schema instead of deleting unused fields - Use Sensitive: true for password fields --- ...lectel_dbaas_configuration_parameter_v1.go | 23 +- ...l_dbaas_configuration_parameter_v1_test.go | 2 + .../data_source_selectel_dbaas_flavor_v1.go | 31 ++ ...ta_source_selectel_dbaas_flavor_v1_test.go | 2 + selectel/dbaas.go | 379 +----------------- selectel/dbaas_base_schemas.go | 154 +++++++ selectel/dbaas_postgresql_utils.go | 3 +- selectel/dbaas_redis_utils.go | 5 +- .../resource_selectel_dbaas_database_v1.go | 84 +--- .../resource_selectel_dbaas_datastore_v1.go | 201 +--------- .../resource_selectel_dbaas_extension_v1.go | 120 +----- selectel/resource_selectel_dbaas_grant_v1.go | 128 +----- .../resource_selectel_dbaas_kafka_acl_v1.go | 64 +-- ...ource_selectel_dbaas_kafka_datastore_v1.go | 118 +----- .../resource_selectel_dbaas_kafka_topic_v1.go | 38 +- ...source_selectel_dbaas_mysql_database_v1.go | 53 +-- ...ource_selectel_dbaas_mysql_datastore_v1.go | 171 +------- ...e_selectel_dbaas_postgresql_database_v1.go | 84 +--- ..._selectel_dbaas_postgresql_datastore_v1.go | 196 +-------- ..._selectel_dbaas_postgresql_extension_v1.go | 63 +-- ..._postgresql_logical_replication_slot_v1.go | 63 +-- ...lectel_dbaas_prometheus_metric_token_v1.go | 26 +- ...ource_selectel_dbaas_redis_datastore_v1.go | 168 +------- selectel/resource_selectel_dbaas_user_v1.go | 61 +-- .../schema_selectel_dbaas_datastore_v1.go | 76 ++++ selectel/schema_selectel_dbaas_grant_v1.go | 37 ++ .../schema_selectel_dbaas_kafka_acl_v1.go | 58 +++ ...chema_selectel_dbaas_kafka_datastore_v1.go | 7 + .../schema_selectel_dbaas_kafka_topic_v1.go | 36 ++ ...schema_selectel_dbaas_mysql_database_v1.go | 7 + ...chema_selectel_dbaas_mysql_datastore_v1.go | 47 +++ ...a_selectel_dbaas_postgresql_database_v1.go | 36 ++ ..._selectel_dbaas_postgresql_datastore_v1.go | 71 ++++ ..._selectel_dbaas_postgresql_extension_v1.go | 37 ++ ..._postgresql_logical_replication_slot_v1.go | 37 ++ ...lectel_dbaas_prometheus_metric_token_v1.go | 24 ++ ...chema_selectel_dbaas_redis_datastore_v1.go | 76 ++++ selectel/schema_selectel_dbaas_user_v1.go | 37 ++ selectel/waiters/dbaas/acl.go | 70 ++++ selectel/waiters/dbaas/database.go | 70 ++++ selectel/waiters/dbaas/datastore.go | 71 ++++ selectel/waiters/dbaas/extension.go | 69 ++++ selectel/waiters/dbaas/grant.go | 69 ++++ .../waiters/dbaas/logical_replication_slot.go | 70 ++++ selectel/waiters/dbaas/topic.go | 70 ++++ selectel/waiters/dbaas/user.go | 70 ++++ ...s_configuration_parameter_v1.html.markdown | 3 + website/docs/d/dbaas_flavor_v1.html.markdown | 4 + 48 files changed, 1470 insertions(+), 1919 deletions(-) create mode 100644 selectel/dbaas_base_schemas.go create mode 100644 selectel/schema_selectel_dbaas_datastore_v1.go create mode 100644 selectel/schema_selectel_dbaas_grant_v1.go create mode 100644 selectel/schema_selectel_dbaas_kafka_acl_v1.go create mode 100644 selectel/schema_selectel_dbaas_kafka_datastore_v1.go create mode 100644 selectel/schema_selectel_dbaas_kafka_topic_v1.go create mode 100644 selectel/schema_selectel_dbaas_mysql_database_v1.go create mode 100644 selectel/schema_selectel_dbaas_mysql_datastore_v1.go create mode 100644 selectel/schema_selectel_dbaas_postgresql_database_v1.go create mode 100644 selectel/schema_selectel_dbaas_postgresql_datastore_v1.go create mode 100644 selectel/schema_selectel_dbaas_postgresql_extension_v1.go create mode 100644 selectel/schema_selectel_dbaas_postgresql_logical_replication_slot_v1.go create mode 100644 selectel/schema_selectel_dbaas_prometheus_metric_token_v1.go create mode 100644 selectel/schema_selectel_dbaas_redis_datastore_v1.go create mode 100644 selectel/schema_selectel_dbaas_user_v1.go create mode 100644 selectel/waiters/dbaas/acl.go create mode 100644 selectel/waiters/dbaas/database.go create mode 100644 selectel/waiters/dbaas/datastore.go create mode 100644 selectel/waiters/dbaas/extension.go create mode 100644 selectel/waiters/dbaas/grant.go create mode 100644 selectel/waiters/dbaas/logical_replication_slot.go create mode 100644 selectel/waiters/dbaas/topic.go create mode 100644 selectel/waiters/dbaas/user.go diff --git a/selectel/data_source_selectel_dbaas_configuration_parameter_v1.go b/selectel/data_source_selectel_dbaas_configuration_parameter_v1.go index b1953d19..7af16775 100644 --- a/selectel/data_source_selectel_dbaas_configuration_parameter_v1.go +++ b/selectel/data_source_selectel_dbaas_configuration_parameter_v1.go @@ -85,6 +85,13 @@ func dataSourceDBaaSConfigurationParameterV1() *schema.Resource { Type: schema.TypeString, }, }, + "invalid_values": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, "is_restart_required": { Type: schema.TypeBool, Computed: true, @@ -188,6 +195,15 @@ func filterConfigurationParametersByName(configurationParameters []dbaas.Configu return filteredConfigurationParameters } +func convertListParametersTypes(parameters []interface{}) []string { + parameterList := make([]string, len(parameters)) + for i, value := range parameters { + parameterList[i] = convertFieldToStringByType(value) + } + + return parameterList +} + func flattenDBaaSConfigurationParameters(configurationParameters []dbaas.ConfigurationParameter) []interface{} { configurationParametersList := make([]interface{}, len(configurationParameters)) for i, param := range configurationParameters { @@ -200,11 +216,8 @@ func flattenDBaaSConfigurationParameters(configurationParameters []dbaas.Configu configurationParametersMap["min"] = convertFieldToStringByType(param.Min) configurationParametersMap["max"] = convertFieldToStringByType(param.Max) configurationParametersMap["default_value"] = convertFieldToStringByType(param.DefaultValue) - choicesList := make([]string, len(param.Choices)) - for i, choice := range param.Choices { - choicesList[i] = convertFieldToStringByType(choice) - } - configurationParametersMap["choices"] = choicesList + configurationParametersMap["choices"] = convertListParametersTypes(param.Choices) + configurationParametersMap["invalid_values"] = convertListParametersTypes(param.InvalidValues) configurationParametersMap["is_restart_required"] = param.IsRestartRequired configurationParametersMap["is_changeable"] = param.IsChangeable diff --git a/selectel/data_source_selectel_dbaas_configuration_parameter_v1_test.go b/selectel/data_source_selectel_dbaas_configuration_parameter_v1_test.go index ad0431d6..fd74c395 100644 --- a/selectel/data_source_selectel_dbaas_configuration_parameter_v1_test.go +++ b/selectel/data_source_selectel_dbaas_configuration_parameter_v1_test.go @@ -41,6 +41,7 @@ func TestAccDBaaSConfigurationParametersV1Basic(t *testing.T) { resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.max", "2147483647"), resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.default_value", "32768"), resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.choices.#", "0"), + resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.invalid_values.#", "0"), resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.is_restart_required", "false"), resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.is_changeable", "true"), ), @@ -60,6 +61,7 @@ func TestAccDBaaSConfigurationParametersV1Basic(t *testing.T) { resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.choices.0", "origin"), resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.choices.1", "replica"), resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.choices.2", "local"), + resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.invalid_values.#", "0"), resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.is_restart_required", "false"), resource.TestCheckResourceAttr("data.selectel_dbaas_configuration_parameter_v1.configuration_param_tf_acc_test_1", "configuration_parameters.0.is_changeable", "true"), ), diff --git a/selectel/data_source_selectel_dbaas_flavor_v1.go b/selectel/data_source_selectel_dbaas_flavor_v1.go index 7f582094..3cc63e9b 100644 --- a/selectel/data_source_selectel_dbaas_flavor_v1.go +++ b/selectel/data_source_selectel_dbaas_flavor_v1.go @@ -12,6 +12,7 @@ type flavorSearchFilter struct { vcpus int ram int disk int + flSize string datastoreTypeID string } @@ -56,6 +57,10 @@ func dataSourceDBaaSFlavorV1() *schema.Resource { Type: schema.TypeInt, Computed: true, }, + "fl_size": { + Type: schema.TypeString, + Computed: true, + }, "datastore_type_ids": { Type: schema.TypeList, Computed: true, @@ -83,6 +88,10 @@ func dataSourceDBaaSFlavorV1() *schema.Resource { Type: schema.TypeInt, Optional: true, }, + "fl_size": { + Type: schema.TypeString, + Optional: true, + }, "datastore_type_id": { Type: schema.TypeString, Optional: true, @@ -118,6 +127,7 @@ func dataSourceDBaaSFlavorV1Read(ctx context.Context, d *schema.ResourceData, me flavors = filterFlavorByVcpus(flavors, filter.vcpus) flavors = filterFlavorByRAM(flavors, filter.ram) flavors = filterFlavorByDisk(flavors, filter.disk) + flavors = filterFlavorByFlSize(flavors, filter.flSize) flavors = filterFlavorByDatastoreTypeID(flavors, filter.datastoreTypeID) flavorsFlatten := flattenDBaaSFlavors(flavors) @@ -156,6 +166,11 @@ func expandFlavorSearchFilter(filterSet *schema.Set) (flavorSearchFilter, error) filter.disk = disk.(int) } + flSize, ok := resourceFilterMap["fl_size"] + if ok { + filter.flSize = flSize.(string) + } + datastoreTypeID, ok := resourceFilterMap["datastore_type_id"] if ok { filter.datastoreTypeID = datastoreTypeID.(string) @@ -209,6 +224,21 @@ func filterFlavorByDisk(flavors []dbaas.FlavorResponse, disk int) []dbaas.Flavor return filteredFlavors } +func filterFlavorByFlSize(flavors []dbaas.FlavorResponse, flSize string) []dbaas.FlavorResponse { + if flSize == "" { + return flavors + } + + var filteredFlavors []dbaas.FlavorResponse + for _, f := range flavors { + if f.FlSize == flSize { + filteredFlavors = append(filteredFlavors, f) + } + } + + return filteredFlavors +} + func filterFlavorByDatastoreTypeID(flavors []dbaas.FlavorResponse, datastoreTypeID string) []dbaas.FlavorResponse { if datastoreTypeID == "" { return flavors @@ -236,6 +266,7 @@ func flattenDBaaSFlavors(flavors []dbaas.FlavorResponse) []interface{} { flavorMap["vcpus"] = flavor.Vcpus flavorMap["ram"] = flavor.RAM flavorMap["disk"] = flavor.Disk + flavorMap["fl_size"] = flavor.FlSize flavorMap["datastore_type_ids"] = flavor.DatastoreTypeIDs flavorsList[i] = flavorMap diff --git a/selectel/data_source_selectel_dbaas_flavor_v1_test.go b/selectel/data_source_selectel_dbaas_flavor_v1_test.go index 93888283..5000f4c7 100644 --- a/selectel/data_source_selectel_dbaas_flavor_v1_test.go +++ b/selectel/data_source_selectel_dbaas_flavor_v1_test.go @@ -34,6 +34,7 @@ func TestAccDBaaSFlavorsV1Basic(t *testing.T) { resource.TestCheckResourceAttrSet("data.selectel_dbaas_flavor_v1.flavor_tf_acc_test_1", "flavors.0.vcpus"), resource.TestCheckResourceAttrSet("data.selectel_dbaas_flavor_v1.flavor_tf_acc_test_1", "flavors.0.ram"), resource.TestCheckResourceAttrSet("data.selectel_dbaas_flavor_v1.flavor_tf_acc_test_1", "flavors.0.disk"), + resource.TestCheckResourceAttrSet("data.selectel_dbaas_flavor_v1.flavor_tf_acc_test_1", "flavors.0.fl_size"), ), }, { @@ -46,6 +47,7 @@ func TestAccDBaaSFlavorsV1Basic(t *testing.T) { resource.TestCheckResourceAttrSet("data.selectel_dbaas_flavor_v1.flavor_tf_acc_test_1", "flavors.0.vcpus"), resource.TestCheckResourceAttrSet("data.selectel_dbaas_flavor_v1.flavor_tf_acc_test_1", "flavors.0.ram"), resource.TestCheckResourceAttrSet("data.selectel_dbaas_flavor_v1.flavor_tf_acc_test_1", "flavors.0.disk"), + resource.TestCheckResourceAttrSet("data.selectel_dbaas_flavor_v1.flavor_tf_acc_test_1", "flavors.0.fl_size"), resource.TestCheckResourceAttr("data.selectel_dbaas_flavor_v1.flavor_tf_acc_test_1", "flavors.0.datastore_type_ids.#", "1"), ), }, diff --git a/selectel/dbaas.go b/selectel/dbaas.go index 8ed03030..cdd6f14b 100644 --- a/selectel/dbaas.go +++ b/selectel/dbaas.go @@ -8,16 +8,15 @@ import ( "log" "math" "math/rand" - "net/http" "sort" "strconv" "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) const ( @@ -108,64 +107,6 @@ func flavorHashSetFunc() schema.SchemaSetFunc { return schema.HashResource(flavorSchema()) } -func waitForDBaaSDatastoreV1ActiveState( - ctx context.Context, client *dbaas.API, datastoreID string, timeout time.Duration, -) error { - pending := []string{ - string(dbaas.StatusPendingCreate), - string(dbaas.StatusPendingUpdate), - string(dbaas.StatusResizing), - } - target := []string{ - string(dbaas.StatusActive), - } - - stateConf := &resource.StateChangeConf{ - Pending: pending, - Target: target, - Refresh: dbaasDatastoreV1StateRefreshFunc(ctx, client, datastoreID), - Timeout: timeout, - Delay: 10 * time.Second, - MinTimeout: 20 * time.Second, - } - - _, err := stateConf.WaitForState() - if err != nil { - return fmt.Errorf( - "error waiting for the datastore %s to become 'ACTIVE': %s", - datastoreID, err) - } - - return nil -} - -func dbaasDatastoreV1StateRefreshFunc(ctx context.Context, client *dbaas.API, datastoreID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.Datastore(ctx, datastoreID) - if err != nil { - return nil, "", err - } - - return d, string(d.Status), nil - } -} - -func dbaasDatastoreV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, datastoreID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.Datastore(ctx, datastoreID) - if err != nil { - var dbaasError *dbaas.DBaaSAPIError - if errors.As(err, &dbaasError) { - return d, strconv.Itoa(dbaasError.StatusCode()), nil - } - - return nil, "", err - } - - return d, strconv.Itoa(http.StatusOK), err - } -} - func resourceDBaaSDatastoreV1FlavorFromSet(flavorSet *schema.Set) (*dbaas.Flavor, error) { if flavorSet.Len() == 0 { return nil, nil @@ -316,7 +257,7 @@ func updateDatastoreName(ctx context.Context, d *schema.ResourceData, client *db log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutUpdate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) if err != nil { return errUpdatingObject(objectDatastore, d.Id(), err) } @@ -339,7 +280,7 @@ func updateDatastoreFirewall(ctx context.Context, d *schema.ResourceData, client log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutUpdate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) if err != nil { return errUpdatingObject(objectDatastore, d.Id(), err) } @@ -371,7 +312,7 @@ func updateDatastoreConfig(ctx context.Context, d *schema.ResourceData, client * log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutUpdate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) if err != nil { return errUpdatingObject(objectDatastore, d.Id(), err) } @@ -391,7 +332,7 @@ func updateDatastoreBackups(ctx context.Context, d *schema.ResourceData, client log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutUpdate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) if err != nil { return errUpdatingObject(objectDatastore, d.Id(), err) } @@ -434,7 +375,7 @@ func resizeDatastore(ctx context.Context, d *schema.ResourceData, client *dbaas. log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) if err != nil { return errUpdatingObject(objectDatastore, d.Id(), err) } @@ -506,310 +447,6 @@ func getDatastoreReplicasInstancesIDsWithoutFloatings(datastore dbaas.Datastore) return replicasIDs } -// Databases - -func waitForDBaaSDatabaseV1ActiveState( - ctx context.Context, client *dbaas.API, databaseID string, timeout time.Duration, -) error { - pending := []string{ - string(dbaas.StatusPendingCreate), - string(dbaas.StatusPendingUpdate), - } - target := []string{ - string(dbaas.StatusActive), - } - - stateConf := &resource.StateChangeConf{ - Pending: pending, - Target: target, - Refresh: dbaasDatabaseV1StateRefreshFunc(ctx, client, databaseID), - Timeout: timeout, - Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, - } - - _, err := stateConf.WaitForState() - if err != nil { - return fmt.Errorf( - "error waiting for the database %s to become 'ACTIVE': %s", - databaseID, err) - } - - return nil -} - -func dbaasDatabaseV1StateRefreshFunc(ctx context.Context, client *dbaas.API, databaseID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.Database(ctx, databaseID) - if err != nil { - return nil, "", err - } - - return d, string(d.Status), nil - } -} - -func dbaasDatabaseV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, datastoreID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.Database(ctx, datastoreID) - if err != nil { - var dbaasError *dbaas.DBaaSAPIError - if errors.As(err, &dbaasError) { - return d, strconv.Itoa(dbaasError.StatusCode()), nil - } - - return nil, "", err - } - - return d, strconv.Itoa(http.StatusOK), err - } -} - -func dbaasDatabaseV1LocaleDiffSuppressFunc(_, old, new string, _ *schema.ResourceData) bool { - // The default locale value - C is the same as null value, so we need to suppress - if old == "C" && new == "" { - return true - } - - return false -} - -// Users - -func waitForDBaaSUserV1ActiveState( - ctx context.Context, client *dbaas.API, userID string, timeout time.Duration, -) error { - pending := []string{ - string(dbaas.StatusPendingCreate), - string(dbaas.StatusPendingUpdate), - } - target := []string{ - string(dbaas.StatusActive), - } - - stateConf := &resource.StateChangeConf{ - Pending: pending, - Target: target, - Refresh: dbaasUserV1StateRefreshFunc(ctx, client, userID), - Timeout: timeout, - Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, - } - - _, err := stateConf.WaitForState() - if err != nil { - return fmt.Errorf( - "error waiting for the user %s to become 'ACTIVE': %s", - userID, err) - } - - return nil -} - -func dbaasUserV1StateRefreshFunc(ctx context.Context, client *dbaas.API, userID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.User(ctx, userID) - if err != nil { - return nil, "", err - } - - return d, string(d.Status), nil - } -} - -func dbaasUserV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, userID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.User(ctx, userID) - if err != nil { - var dbaasError *dbaas.DBaaSAPIError - if errors.As(err, &dbaasError) { - return d, strconv.Itoa(dbaasError.StatusCode()), nil - } - - return nil, "", err - } - - return d, strconv.Itoa(http.StatusOK), err - } -} - -// Slots - -func waitForDBaaSLogicalReplicationSlotV1ActiveState( - ctx context.Context, client *dbaas.API, slotID string, timeout time.Duration, -) error { - pending := []string{ - string(dbaas.StatusPendingCreate), - string(dbaas.StatusPendingUpdate), - } - target := []string{ - string(dbaas.StatusActive), - } - - stateConf := &resource.StateChangeConf{ - Pending: pending, - Target: target, - Refresh: dbaasLogicalReplicationSlotV1StateRefreshFunc(ctx, client, slotID), - Timeout: timeout, - Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, - } - - _, err := stateConf.WaitForState() - if err != nil { - return fmt.Errorf( - "error waiting for the slot %s to become 'ACTIVE': %s", - slotID, err) - } - - return nil -} - -func dbaasLogicalReplicationSlotV1StateRefreshFunc(ctx context.Context, client *dbaas.API, slotID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.LogicalReplicationSlot(ctx, slotID) - if err != nil { - return nil, "", err - } - - return d, string(d.Status), nil - } -} - -func dbaasLogicalReplicationSlotV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, slotID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.LogicalReplicationSlot(ctx, slotID) - if err != nil { - var dbaasError *dbaas.DBaaSAPIError - if errors.As(err, &dbaasError) { - return d, strconv.Itoa(dbaasError.StatusCode()), nil - } - - return nil, "", err - } - - return d, strconv.Itoa(http.StatusOK), err - } -} - -// Topics - -func waitForDBaaSTopicV1ActiveState( - ctx context.Context, client *dbaas.API, topicID string, timeout time.Duration, -) error { - pending := []string{ - string(dbaas.StatusPendingCreate), - string(dbaas.StatusPendingUpdate), - } - target := []string{ - string(dbaas.StatusActive), - } - - stateConf := &resource.StateChangeConf{ - Pending: pending, - Target: target, - Refresh: dbaasTopicV1StateRefreshFunc(ctx, client, topicID), - Timeout: timeout, - Delay: 10 * time.Second, - MinTimeout: 20 * time.Second, - } - - _, err := stateConf.WaitForState() - if err != nil { - return fmt.Errorf( - "error waiting for the topic %s to become 'ACTIVE': %s", - topicID, err) - } - - return nil -} - -func dbaasTopicV1StateRefreshFunc(ctx context.Context, client *dbaas.API, topicID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.Topic(ctx, topicID) - if err != nil { - return nil, "", err - } - - return d, string(d.Status), nil - } -} - -func dbaasTopicV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, topicID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.Topic(ctx, topicID) - if err != nil { - var dbaasError *dbaas.DBaaSAPIError - if errors.As(err, &dbaasError) { - return d, strconv.Itoa(dbaasError.StatusCode()), nil - } - - return nil, "", err - } - - return d, strconv.Itoa(http.StatusOK), err - } -} - -// ACLs - -func waitForDBaaSACLV1ActiveState( - ctx context.Context, client *dbaas.API, aclID string, timeout time.Duration, -) error { - pending := []string{ - string(dbaas.StatusPendingCreate), - string(dbaas.StatusPendingUpdate), - } - target := []string{ - string(dbaas.StatusActive), - } - - stateConf := &resource.StateChangeConf{ - Pending: pending, - Target: target, - Refresh: dbaasACLV1StateRefreshFunc(ctx, client, aclID), - Timeout: timeout, - Delay: 10 * time.Second, - MinTimeout: 15 * time.Second, - } - - _, err := stateConf.WaitForState() - if err != nil { - return fmt.Errorf( - "error waiting for the acl %s to become 'ACTIVE': %s", - aclID, err) - } - - return nil -} - -func dbaasACLV1StateRefreshFunc(ctx context.Context, client *dbaas.API, aclID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.ACL(ctx, aclID) - if err != nil { - return nil, "", err - } - - return d, string(d.Status), nil - } -} - -func dbaasACLV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, aclID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.ACL(ctx, aclID) - if err != nil { - var dbaasError *dbaas.DBaaSAPIError - if errors.As(err, &dbaasError) { - return d, strconv.Itoa(dbaasError.StatusCode()), nil - } - - return nil, "", err - } - - return d, strconv.Itoa(http.StatusOK), err - } -} - // Floating IPs func refreshDatastoreInstancesOutputsDiff(_ context.Context, diff *schema.ResourceDiff, _ interface{}) error { @@ -835,7 +472,7 @@ func dbaasFloatingIPCreate(ctx context.Context, d *schema.ResourceData, client * } log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutUpdate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) if err != nil { return errUpdatingObject(objectDatastore, d.Id(), err) } @@ -857,7 +494,7 @@ func dbaasFloatingIPDelete(ctx context.Context, d *schema.ResourceData, client * log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutUpdate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) if err != nil { return errUpdatingObject(objectDatastore, d.Id(), err) } diff --git a/selectel/dbaas_base_schemas.go b/selectel/dbaas_base_schemas.go new file mode 100644 index 00000000..dff3f57c --- /dev/null +++ b/selectel/dbaas_base_schemas.go @@ -0,0 +1,154 @@ +package selectel + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func resourceDBaaSDatastoreV1BaseSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "project_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "region": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "subnet_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "type_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "flavor_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: false, + ConflictsWith: []string{"flavor"}, + }, + "node_count": { + Type: schema.TypeInt, + Required: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "backup_retention_days": { + Type: schema.TypeInt, + Optional: true, + Description: "Number of days to retain backups.", + }, + "connections": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "flavor": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + ForceNew: false, + ConflictsWith: []string{"flavor_id"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "vcpus": { + Type: schema.TypeInt, + Required: true, + }, + "ram": { + Type: schema.TypeInt, + Required: true, + }, + "disk": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + "firewall": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ips": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "config": { + Type: schema.TypeMap, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "instances": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "role": { + Type: schema.TypeString, + Computed: true, + }, + "floating_ip": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + } +} + +func resourceDBaaSDatabaseV1BaseSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "project_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "region": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "datastore_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + } +} diff --git a/selectel/dbaas_postgresql_utils.go b/selectel/dbaas_postgresql_utils.go index 6f853e31..ae4b4c09 100644 --- a/selectel/dbaas_postgresql_utils.go +++ b/selectel/dbaas_postgresql_utils.go @@ -7,6 +7,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func parsePoolerSet(poolerSet *schema.Set) (string, int, error) { @@ -73,7 +74,7 @@ func updatePostgreSQLDatastorePooler(ctx context.Context, d *schema.ResourceData log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutUpdate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) if err != nil { return errUpdatingObject(objectDatastore, d.Id(), err) } diff --git a/selectel/dbaas_redis_utils.go b/selectel/dbaas_redis_utils.go index 3791ee45..c8fc8bda 100644 --- a/selectel/dbaas_redis_utils.go +++ b/selectel/dbaas_redis_utils.go @@ -6,6 +6,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func updateRedisDatastorePassword(ctx context.Context, d *schema.ResourceData, client *dbaas.API) error { @@ -21,7 +22,7 @@ func updateRedisDatastorePassword(ctx context.Context, d *schema.ResourceData, c log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutUpdate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) if err != nil { return errUpdatingObject(objectDatastore, d.Id(), err) } @@ -47,7 +48,7 @@ func resizeRedisDatastore(ctx context.Context, d *schema.ResourceData, client *d log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, client, d.Id(), timeout) if err != nil { return errUpdatingObject(objectDatastore, d.Id(), err) } diff --git a/selectel/resource_selectel_dbaas_database_v1.go b/selectel/resource_selectel_dbaas_database_v1.go index 4bcf1f9e..d68a694c 100644 --- a/selectel/resource_selectel_dbaas_database_v1.go +++ b/selectel/resource_selectel_dbaas_database_v1.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSDatabaseV1() *schema.Resource { @@ -29,65 +30,18 @@ func resourceDBaaSDatabaseV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "owner_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: false, - }, - "lc_collate": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - DiffSuppressFunc: dbaasDatabaseV1LocaleDiffSuppressFunc, - }, - "lc_ctype": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - DiffSuppressFunc: dbaasDatabaseV1LocaleDiffSuppressFunc, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - }, + Schema: resourceDBaaSPostgreSQLDatabaseV1Schema(), } } func resourceDBaaSDatabaseV1Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr } databaseCreateOpts := dbaas.DatabaseCreateOpts{ - DatastoreID: datastoreID, + DatastoreID: d.Get("datastore_id").(string), Name: d.Get("name").(string), OwnerID: d.Get("owner_id").(string), LcCollate: d.Get("lc_collate").(string), @@ -102,7 +56,7 @@ func resourceDBaaSDatabaseV1Create(ctx context.Context, d *schema.ResourceData, log.Printf("[DEBUG] waiting for database %s to become 'ACTIVE'", database.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatabaseV1ActiveState(ctx, dbaasClient, database.ID, timeout) + err = waiters.WaitForDBaaSDatabaseV1ActiveState(ctx, dbaasClient, database.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectDatabase, err)) } @@ -140,24 +94,14 @@ func resourceDBaaSDatabaseV1Read(ctx context.Context, d *schema.ResourceData, me } func resourceDBaaSDatabaseV1Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr } if d.HasChange("owner_id") { - ownerID := d.Get("owner_id").(string) - - selMutexKV.Lock(ownerID) - defer selMutexKV.Unlock(ownerID) - updateOpts := dbaas.DatabaseUpdateOpts{ - OwnerID: ownerID, + OwnerID: d.Get("owner_id").(string), } log.Print(msgUpdate(objectDatastore, d.Id(), updateOpts)) @@ -168,7 +112,7 @@ func resourceDBaaSDatabaseV1Update(ctx context.Context, d *schema.ResourceData, log.Printf("[DEBUG] waiting for database %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatabaseV1ActiveState(ctx, dbaasClient, d.Id(), timeout) + err = waiters.WaitForDBaaSDatabaseV1ActiveState(ctx, dbaasClient, d.Id(), timeout) if err != nil { return diag.FromErr(errUpdatingObject(objectDatabase, d.Id(), err)) } @@ -178,18 +122,6 @@ func resourceDBaaSDatabaseV1Update(ctx context.Context, d *schema.ResourceData, } func resourceDBaaSDatabaseV1Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - - ownerIDRaw, ownerIDOk := d.GetOk("owner_id") - if ownerIDOk { - ownerID := ownerIDRaw.(string) - selMutexKV.Lock(ownerID) - defer selMutexKV.Unlock(ownerID) - } - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr @@ -204,10 +136,10 @@ func resourceDBaaSDatabaseV1Delete(ctx context.Context, d *schema.ResourceData, stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasDatabaseV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSDatabaseV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 15 * time.Second, } log.Printf("[DEBUG] waiting for database %s to become deleted", d.Id()) diff --git a/selectel/resource_selectel_dbaas_datastore_v1.go b/selectel/resource_selectel_dbaas_datastore_v1.go index 6bad5a2f..89ec4ea6 100644 --- a/selectel/resource_selectel_dbaas_datastore_v1.go +++ b/selectel/resource_selectel_dbaas_datastore_v1.go @@ -13,8 +13,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSDatastoreV1() *schema.Resource { @@ -34,198 +34,7 @@ func resourceDBaaSDatastoreV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "subnet_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "type_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "flavor_id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: false, - ConflictsWith: []string{"flavor"}, - }, - "node_count": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - "enabled": { - Type: schema.TypeBool, - Computed: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - "backup_retention_days": { - Type: schema.TypeInt, - Optional: true, - Computed: true, - Description: "Number of days to retain backups.", - }, - "connections": { - Type: schema.TypeMap, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "floating_ips": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "master": { - Type: schema.TypeInt, - Required: true, - }, - "replica": { - Type: schema.TypeInt, - Required: true, - }, - }, - }, - }, - "flavor": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - ForceNew: false, - ConflictsWith: []string{"flavor_id"}, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "vcpus": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - "ram": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - "disk": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - }, - }, - }, - "pooler": { - Type: schema.TypeSet, - Optional: true, - ForceNew: false, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "mode": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - ValidateFunc: validation.StringInSlice([]string{ - "session", - "transaction", - "statement", - }, false), - }, - "size": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - }, - }, - }, - "firewall": { - Type: schema.TypeSet, - Optional: true, - ForceNew: false, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "ips": { - Type: schema.TypeList, - Required: true, - ForceNew: false, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "restore": { - Type: schema.TypeSet, - Optional: true, - ForceNew: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "datastore_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: false, - }, - "target_time": { - Type: schema.TypeString, - Optional: true, - ForceNew: false, - }, - }, - }, - }, - "config": { - Type: schema.TypeMap, - Optional: true, - Computed: true, - ForceNew: false, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "redis_password": { - Type: schema.TypeString, - Optional: true, - ForceNew: false, - }, - "instances": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "role": { - Type: schema.TypeString, - Computed: true, - }, - "floating_ip": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - }, + Schema: resourceDBaaSDatastoreV1Schema(), } } @@ -303,7 +112,7 @@ func resourceDBaaSDatastoreV1Create(ctx context.Context, d *schema.ResourceData, log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", datastore.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastore.ID, timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastore.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectDatastore, err)) } @@ -432,10 +241,10 @@ func resourceDBaaSDatastoreV1Delete(ctx context.Context, d *schema.ResourceData, stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasDatastoreV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSDatastoreV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 20 * time.Second, } log.Printf("[DEBUG] waiting for datastore %s to become deleted", d.Id()) diff --git a/selectel/resource_selectel_dbaas_extension_v1.go b/selectel/resource_selectel_dbaas_extension_v1.go index 859154d3..d6ce0db0 100644 --- a/selectel/resource_selectel_dbaas_extension_v1.go +++ b/selectel/resource_selectel_dbaas_extension_v1.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSExtensionV1() *schema.Resource { @@ -28,51 +29,11 @@ func resourceDBaaSExtensionV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "available_extension_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "database_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - }, + Schema: resourceDBaaSPostgreSQLExtensionV1Schema(), } } func resourceDBaaSExtensionV1Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - - databaseID := d.Get("database_id").(string) - - selMutexKV.Lock(databaseID) - defer selMutexKV.Unlock(databaseID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr @@ -80,8 +41,8 @@ func resourceDBaaSExtensionV1Create(ctx context.Context, d *schema.ResourceData, extensionCreateOpts := dbaas.ExtensionCreateOpts{ AvailableExtensionID: d.Get("available_extension_id").(string), - DatastoreID: datastoreID, - DatabaseID: databaseID, + DatastoreID: d.Get("datastore_id").(string), + DatabaseID: d.Get("database_id").(string), } log.Print(msgCreate(objectExtension, extensionCreateOpts)) @@ -92,7 +53,7 @@ func resourceDBaaSExtensionV1Create(ctx context.Context, d *schema.ResourceData, log.Printf("[DEBUG] waiting for extension %s to become 'ACTIVE'", extension.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSExtensionV1ActiveState(ctx, dbaasClient, extension.ID, timeout) + err = waiters.WaitForDBaaSExtensionV1ActiveState(ctx, dbaasClient, extension.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectExtension, err)) } @@ -122,16 +83,6 @@ func resourceDBaaSExtensionV1Read(ctx context.Context, d *schema.ResourceData, m } func resourceDBaaSExtensionV1Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - - databaseID := d.Get("database_id").(string) - - selMutexKV.Lock(databaseID) - defer selMutexKV.Unlock(databaseID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr @@ -146,10 +97,10 @@ func resourceDBaaSExtensionV1Delete(ctx context.Context, d *schema.ResourceData, stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasExtensionV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSExtensionV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 20 * time.Second, } log.Printf("[DEBUG] waiting for extension %s to become deleted", d.Id()) @@ -175,60 +126,3 @@ func resourceDBaaSExtensionV1ImportState(_ context.Context, d *schema.ResourceDa return []*schema.ResourceData{d}, nil } - -func waitForDBaaSExtensionV1ActiveState( - ctx context.Context, client *dbaas.API, extensionID string, timeout time.Duration, -) error { - pending := []string{ - string(dbaas.StatusPendingCreate), - string(dbaas.StatusPendingUpdate), - } - target := []string{ - string(dbaas.StatusActive), - } - - stateConf := &resource.StateChangeConf{ - Pending: pending, - Target: target, - Refresh: dbaasExtensionV1StateRefreshFunc(ctx, client, extensionID), - Timeout: timeout, - Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, - } - - _, err := stateConf.WaitForState() - if err != nil { - return fmt.Errorf( - "error waiting for the extension %s to become 'ACTIVE': %s", - extensionID, err) - } - - return nil -} - -func dbaasExtensionV1StateRefreshFunc(ctx context.Context, client *dbaas.API, extensionID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.Extension(ctx, extensionID) - if err != nil { - return nil, "", err - } - - return d, string(d.Status), nil - } -} - -func dbaasExtensionV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, extensionID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.Extension(ctx, extensionID) - if err != nil { - var dbaasError *dbaas.DBaaSAPIError - if errors.As(err, &dbaasError) { - return d, strconv.Itoa(dbaasError.StatusCode()), nil - } - - return nil, "", err - } - - return d, strconv.Itoa(200), err - } -} diff --git a/selectel/resource_selectel_dbaas_grant_v1.go b/selectel/resource_selectel_dbaas_grant_v1.go index 0568e807..ea750c46 100644 --- a/selectel/resource_selectel_dbaas_grant_v1.go +++ b/selectel/resource_selectel_dbaas_grant_v1.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSGrantV1() *schema.Resource { @@ -28,63 +29,20 @@ func resourceDBaaSGrantV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "database_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "user_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - }, + Schema: resourceDBaaSGrantV1Schema(), } } func resourceDBaaSGrantV1Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - - databaseID := d.Get("database_id").(string) - selMutexKV.Lock(databaseID) - defer selMutexKV.Unlock(databaseID) - - userID := d.Get("user_id").(string) - selMutexKV.Lock(userID) - defer selMutexKV.Unlock(userID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr } grantCreateOpts := dbaas.GrantCreateOpts{ - DatastoreID: datastoreID, - DatabaseID: databaseID, - UserID: userID, + DatastoreID: d.Get("datastore_id").(string), + DatabaseID: d.Get("database_id").(string), + UserID: d.Get("user_id").(string), } log.Print(msgCreate(objectGrant, grantCreateOpts)) @@ -95,7 +53,7 @@ func resourceDBaaSGrantV1Create(ctx context.Context, d *schema.ResourceData, met log.Printf("[DEBUG] waiting for grant %s to become 'ACTIVE'", grant.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSGrantV1ActiveState(ctx, dbaasClient, grant.ID, timeout) + err = waiters.WaitForDBaaSGrantV1ActiveState(ctx, dbaasClient, grant.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectGrant, err)) } @@ -125,19 +83,6 @@ func resourceDBaaSGrantV1Read(ctx context.Context, d *schema.ResourceData, meta } func resourceDBaaSGrantV1Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - - databaseID := d.Get("database_id").(string) - selMutexKV.Lock(databaseID) - defer selMutexKV.Unlock(databaseID) - - userID := d.Get("user_id").(string) - selMutexKV.Lock(userID) - defer selMutexKV.Unlock(userID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr @@ -152,10 +97,10 @@ func resourceDBaaSGrantV1Delete(ctx context.Context, d *schema.ResourceData, met stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasGrantV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSGrantV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 20 * time.Second, } log.Printf("[DEBUG] waiting for grant %s to become deleted", d.Id()) @@ -181,60 +126,3 @@ func resourceDBaaSGrantV1ImportState(_ context.Context, d *schema.ResourceData, return []*schema.ResourceData{d}, nil } - -func waitForDBaaSGrantV1ActiveState( - ctx context.Context, client *dbaas.API, grantID string, timeout time.Duration, -) error { - pending := []string{ - string(dbaas.StatusPendingCreate), - string(dbaas.StatusPendingUpdate), - } - target := []string{ - string(dbaas.StatusActive), - } - - stateConf := &resource.StateChangeConf{ - Pending: pending, - Target: target, - Refresh: dbaasGrantV1StateRefreshFunc(ctx, client, grantID), - Timeout: timeout, - Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, - } - - _, err := stateConf.WaitForState() - if err != nil { - return fmt.Errorf( - "error waiting for the grant %s to become 'ACTIVE': %s", - grantID, err) - } - - return nil -} - -func dbaasGrantV1StateRefreshFunc(ctx context.Context, client *dbaas.API, grantID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.Grant(ctx, grantID) - if err != nil { - return nil, "", err - } - - return d, string(d.Status), nil - } -} - -func dbaasGrantV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, grantID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - d, err := client.Grant(ctx, grantID) - if err != nil { - var dbaasError *dbaas.DBaaSAPIError - if errors.As(err, &dbaasError) { - return d, strconv.Itoa(dbaasError.StatusCode()), nil - } - - return nil, "", err - } - - return d, strconv.Itoa(200), err - } -} diff --git a/selectel/resource_selectel_dbaas_kafka_acl_v1.go b/selectel/resource_selectel_dbaas_kafka_acl_v1.go index 5a7160e5..bffda456 100644 --- a/selectel/resource_selectel_dbaas_kafka_acl_v1.go +++ b/selectel/resource_selectel_dbaas_kafka_acl_v1.go @@ -12,8 +12,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSKafkaACLV1() *schema.Resource { @@ -30,55 +30,7 @@ func resourceDBaaSKafkaACLV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "pattern": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - "pattern_type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - "literal", - "prefixed", - "all", - }, false), - }, - "user_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "allow_read": { - Type: schema.TypeBool, - Required: true, - }, - "allow_write": { - Type: schema.TypeBool, - Required: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - }, + Schema: resourceDBaaSKafkaACKV1Schema(), } } @@ -105,7 +57,7 @@ func resourceDBaaSACLV1Create(ctx context.Context, d *schema.ResourceData, meta log.Printf("[DEBUG] waiting for acl %s to become 'ACTIVE'", acl.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSACLV1ActiveState(ctx, dbaasClient, acl.ID, timeout) + err = waiters.WaitForDBaaSACLV1ActiveState(ctx, dbaasClient, acl.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectACL, err)) } @@ -145,11 +97,9 @@ func resourceDBaaSACLV1Update(ctx context.Context, d *schema.ResourceData, meta } if d.HasChange("allow_read") || d.HasChange("allow_write") { - allowRead := d.Get("allow_read").(bool) - allowWrite := d.Get("allow_write").(bool) updateOpts := dbaas.ACLUpdateOpts{ - AllowRead: allowRead, - AllowWrite: allowWrite, + AllowRead: d.Get("allow_read").(bool), + AllowWrite: d.Get("allow_write").(bool), } log.Print(msgUpdate(objectACL, d.Id(), updateOpts)) @@ -160,7 +110,7 @@ func resourceDBaaSACLV1Update(ctx context.Context, d *schema.ResourceData, meta log.Printf("[DEBUG] waiting for acl %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSACLV1ActiveState(ctx, dbaasClient, d.Id(), timeout) + err = waiters.WaitForDBaaSACLV1ActiveState(ctx, dbaasClient, d.Id(), timeout) if err != nil { return diag.FromErr(errUpdatingObject(objectACL, d.Id(), err)) } @@ -184,7 +134,7 @@ func resourceDBaaSACLV1Delete(ctx context.Context, d *schema.ResourceData, meta stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasACLV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSACLV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, MinTimeout: 20 * time.Second, diff --git a/selectel/resource_selectel_dbaas_kafka_datastore_v1.go b/selectel/resource_selectel_dbaas_kafka_datastore_v1.go index 2371ec2d..a4ac8978 100644 --- a/selectel/resource_selectel_dbaas_kafka_datastore_v1.go +++ b/selectel/resource_selectel_dbaas_kafka_datastore_v1.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSKafkaDatastoreV1() *schema.Resource { @@ -29,118 +30,7 @@ func resourceDBaaSKafkaDatastoreV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "subnet_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "type_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "flavor_id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ConflictsWith: []string{"flavor"}, - }, - "node_count": { - Type: schema.TypeInt, - Required: true, - }, - "enabled": { - Type: schema.TypeBool, - Computed: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - "connections": { - Type: schema.TypeMap, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "flavor": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - ConflictsWith: []string{"flavor_id"}, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "vcpus": { - Type: schema.TypeInt, - Required: true, - }, - "ram": { - Type: schema.TypeInt, - Required: true, - }, - "disk": { - Type: schema.TypeInt, - Required: true, - }, - }, - }, - }, - "firewall": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "ips": { - Type: schema.TypeList, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "config": { - Type: schema.TypeMap, - Optional: true, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "instances": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "role": { - Type: schema.TypeString, - Computed: true, - }, - "floating_ip": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - }, + Schema: resourceDBaaSKafkaDatastoreV1Schema(), } } @@ -193,7 +83,7 @@ func resourceDBaaSKafkaDatastoreV1Create(ctx context.Context, d *schema.Resource log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", datastore.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastore.ID, timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastore.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectDatastore, err)) } @@ -297,7 +187,7 @@ func resourceDBaaSKafkaDatastoreV1Delete(ctx context.Context, d *schema.Resource stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasDatastoreV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSDatastoreV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, MinTimeout: 15 * time.Second, diff --git a/selectel/resource_selectel_dbaas_kafka_topic_v1.go b/selectel/resource_selectel_dbaas_kafka_topic_v1.go index d37d7d95..75f0d224 100644 --- a/selectel/resource_selectel_dbaas_kafka_topic_v1.go +++ b/selectel/resource_selectel_dbaas_kafka_topic_v1.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSKafkaTopicV1() *schema.Resource { @@ -29,36 +30,7 @@ func resourceDBaaSKafkaTopicV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "partitions": { - Type: schema.TypeInt, - Required: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - }, + Schema: resourceDBaaSKafkaTopicV1Schema(), } } @@ -82,7 +54,7 @@ func resourceDBaaSTopicV1Create(ctx context.Context, d *schema.ResourceData, met log.Printf("[DEBUG] waiting for topic %s to become 'ACTIVE'", topic.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSTopicV1ActiveState(ctx, dbaasClient, topic.ID, timeout) + err = waiters.WaitForDBaaSTopicV1ActiveState(ctx, dbaasClient, topic.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectTopic, err)) } @@ -131,7 +103,7 @@ func resourceDBaaSTopicV1Update(ctx context.Context, d *schema.ResourceData, met log.Printf("[DEBUG] waiting for topic %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSTopicV1ActiveState(ctx, dbaasClient, d.Id(), timeout) + err = waiters.WaitForDBaaSTopicV1ActiveState(ctx, dbaasClient, d.Id(), timeout) if err != nil { return diag.FromErr(errUpdatingObject(objectTopic, d.Id(), err)) } @@ -155,7 +127,7 @@ func resourceDBaaSTopicV1Delete(ctx context.Context, d *schema.ResourceData, met stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasTopicV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSTopicV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, MinTimeout: 20 * time.Second, diff --git a/selectel/resource_selectel_dbaas_mysql_database_v1.go b/selectel/resource_selectel_dbaas_mysql_database_v1.go index 3243e0b2..9d1e617e 100644 --- a/selectel/resource_selectel_dbaas_mysql_database_v1.go +++ b/selectel/resource_selectel_dbaas_mysql_database_v1.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSMySQLDatabaseV1() *schema.Resource { @@ -28,48 +29,18 @@ func resourceDBaaSMySQLDatabaseV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - }, + Schema: resourceDBaaSMySQLDatabaseV1Schema(), } } func resourceDBaaSMySQLDatabaseV1Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr } databaseCreateOpts := dbaas.DatabaseCreateOpts{ - DatastoreID: datastoreID, + DatastoreID: d.Get("datastore_id").(string), Name: d.Get("name").(string), } @@ -81,7 +52,7 @@ func resourceDBaaSMySQLDatabaseV1Create(ctx context.Context, d *schema.ResourceD log.Printf("[DEBUG] waiting for database %s to become 'ACTIVE'", database.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatabaseV1ActiveState(ctx, dbaasClient, database.ID, timeout) + err = waiters.WaitForDBaaSDatabaseV1ActiveState(ctx, dbaasClient, database.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectDatabase, err)) } @@ -110,18 +81,6 @@ func resourceDBaaSMySQLDatabaseV1Read(ctx context.Context, d *schema.ResourceDat } func resourceDBaaSMySQLDatabaseV1Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - - ownerIDRaw, ownerIDOk := d.GetOk("owner_id") - if ownerIDOk { - ownerID := ownerIDRaw.(string) - selMutexKV.Lock(ownerID) - defer selMutexKV.Unlock(ownerID) - } - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr @@ -136,10 +95,10 @@ func resourceDBaaSMySQLDatabaseV1Delete(ctx context.Context, d *schema.ResourceD stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasDatabaseV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSDatabaseV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 15 * time.Second, } log.Printf("[DEBUG] waiting for database %s to become deleted", d.Id()) diff --git a/selectel/resource_selectel_dbaas_mysql_datastore_v1.go b/selectel/resource_selectel_dbaas_mysql_datastore_v1.go index a93f7d61..fd25e1a0 100644 --- a/selectel/resource_selectel_dbaas_mysql_datastore_v1.go +++ b/selectel/resource_selectel_dbaas_mysql_datastore_v1.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSMySQLDatastoreV1() *schema.Resource { @@ -33,169 +34,7 @@ func resourceDBaaSMySQLDatastoreV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "subnet_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "type_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "flavor_id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: false, - ConflictsWith: []string{"flavor"}, - }, - "node_count": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - "enabled": { - Type: schema.TypeBool, - Computed: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - "backup_retention_days": { - Type: schema.TypeInt, - Optional: true, - Computed: true, - Description: "Number of days to retain backups.", - }, - "connections": { - Type: schema.TypeMap, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "floating_ips": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "master": { - Type: schema.TypeInt, - Required: true, - }, - "replica": { - Type: schema.TypeInt, - Required: true, - }, - }, - }, - }, - "flavor": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - ForceNew: false, - ConflictsWith: []string{"flavor_id"}, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "vcpus": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - "ram": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - "disk": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - }, - }, - }, - "firewall": { - Type: schema.TypeSet, - Optional: true, - ForceNew: false, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "ips": { - Type: schema.TypeList, - Required: true, - ForceNew: false, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "restore": { - Type: schema.TypeSet, - Optional: true, - ForceNew: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "target_time": { - Type: schema.TypeString, - Optional: true, - ForceNew: false, - }, - }, - }, - }, - "config": { - Type: schema.TypeMap, - Optional: true, - Computed: true, - ForceNew: false, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "instances": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "role": { - Type: schema.TypeString, - Computed: true, - }, - "floating_ip": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - }, + Schema: resourceDBaaSMySQLDatastoreV1Schema(), } } @@ -266,7 +105,7 @@ func resourceDBaaSMySQLDatastoreV1Create(ctx context.Context, d *schema.Resource log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", datastore.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastore.ID, timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastore.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectDatastore, err)) } @@ -383,10 +222,10 @@ func resourceDBaaSMySQLDatastoreV1Delete(ctx context.Context, d *schema.Resource stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasDatastoreV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSDatastoreV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 20 * time.Second, } log.Printf("[DEBUG] waiting for datastore %s to become deleted", d.Id()) diff --git a/selectel/resource_selectel_dbaas_postgresql_database_v1.go b/selectel/resource_selectel_dbaas_postgresql_database_v1.go index 16bb8eb5..2e3db6c5 100644 --- a/selectel/resource_selectel_dbaas_postgresql_database_v1.go +++ b/selectel/resource_selectel_dbaas_postgresql_database_v1.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSPostgreSQLDatabaseV1() *schema.Resource { @@ -29,65 +30,18 @@ func resourceDBaaSPostgreSQLDatabaseV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "owner_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: false, - }, - "lc_collate": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - DiffSuppressFunc: dbaasDatabaseV1LocaleDiffSuppressFunc, - }, - "lc_ctype": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - DiffSuppressFunc: dbaasDatabaseV1LocaleDiffSuppressFunc, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - }, + Schema: resourceDBaaSPostgreSQLDatabaseV1Schema(), } } func resourceDBaaSPostgreSQLDatabaseV1Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr } databaseCreateOpts := dbaas.DatabaseCreateOpts{ - DatastoreID: datastoreID, + DatastoreID: d.Get("datastore_id").(string), Name: d.Get("name").(string), OwnerID: d.Get("owner_id").(string), LcCollate: d.Get("lc_collate").(string), @@ -102,7 +56,7 @@ func resourceDBaaSPostgreSQLDatabaseV1Create(ctx context.Context, d *schema.Reso log.Printf("[DEBUG] waiting for database %s to become 'ACTIVE'", database.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatabaseV1ActiveState(ctx, dbaasClient, database.ID, timeout) + err = waiters.WaitForDBaaSDatabaseV1ActiveState(ctx, dbaasClient, database.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectDatabase, err)) } @@ -140,24 +94,14 @@ func resourceDBaaSPostgreSQLDatabaseV1Read(ctx context.Context, d *schema.Resour } func resourceDBaaSPostgreSQLDatabaseV1Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr } if d.HasChange("owner_id") { - ownerID := d.Get("owner_id").(string) - - selMutexKV.Lock(ownerID) - defer selMutexKV.Unlock(ownerID) - updateOpts := dbaas.DatabaseUpdateOpts{ - OwnerID: ownerID, + OwnerID: d.Get("owner_id").(string), } log.Print(msgUpdate(objectDatastore, d.Id(), updateOpts)) @@ -168,7 +112,7 @@ func resourceDBaaSPostgreSQLDatabaseV1Update(ctx context.Context, d *schema.Reso log.Printf("[DEBUG] waiting for database %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatabaseV1ActiveState(ctx, dbaasClient, d.Id(), timeout) + err = waiters.WaitForDBaaSDatabaseV1ActiveState(ctx, dbaasClient, d.Id(), timeout) if err != nil { return diag.FromErr(errUpdatingObject(objectDatabase, d.Id(), err)) } @@ -178,18 +122,6 @@ func resourceDBaaSPostgreSQLDatabaseV1Update(ctx context.Context, d *schema.Reso } func resourceDBaaSPostgreSQLDatabaseV1Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - - ownerIDRaw, ownerIDOk := d.GetOk("owner_id") - if ownerIDOk { - ownerID := ownerIDRaw.(string) - selMutexKV.Lock(ownerID) - defer selMutexKV.Unlock(ownerID) - } - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr @@ -204,10 +136,10 @@ func resourceDBaaSPostgreSQLDatabaseV1Delete(ctx context.Context, d *schema.Reso stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasDatabaseV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSDatabaseV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 15 * time.Second, } log.Printf("[DEBUG] waiting for database %s to become deleted", d.Id()) diff --git a/selectel/resource_selectel_dbaas_postgresql_datastore_v1.go b/selectel/resource_selectel_dbaas_postgresql_datastore_v1.go index 449cee49..0770995f 100644 --- a/selectel/resource_selectel_dbaas_postgresql_datastore_v1.go +++ b/selectel/resource_selectel_dbaas_postgresql_datastore_v1.go @@ -13,8 +13,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSPostgreSQLDatastoreV1() *schema.Resource { @@ -34,193 +34,7 @@ func resourceDBaaSPostgreSQLDatastoreV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "subnet_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "type_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "flavor_id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: false, - ConflictsWith: []string{"flavor"}, - }, - "node_count": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - "enabled": { - Type: schema.TypeBool, - Computed: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - "backup_retention_days": { - Type: schema.TypeInt, - Optional: true, - Computed: true, - Description: "Number of days to retain backups.", - }, - "connections": { - Type: schema.TypeMap, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "floating_ips": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "master": { - Type: schema.TypeInt, - Required: true, - }, - "replica": { - Type: schema.TypeInt, - Required: true, - }, - }, - }, - }, - "flavor": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - ForceNew: false, - ConflictsWith: []string{"flavor_id"}, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "vcpus": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - "ram": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - "disk": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - }, - }, - }, - "pooler": { - Type: schema.TypeSet, - Optional: true, - ForceNew: false, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "mode": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - ValidateFunc: validation.StringInSlice([]string{ - "session", - "transaction", - "statement", - }, false), - }, - "size": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - }, - }, - }, - "firewall": { - Type: schema.TypeSet, - Optional: true, - ForceNew: false, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "ips": { - Type: schema.TypeList, - Required: true, - ForceNew: false, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "restore": { - Type: schema.TypeSet, - Optional: true, - ForceNew: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "target_time": { - Type: schema.TypeString, - Optional: true, - ForceNew: false, - }, - }, - }, - }, - "config": { - Type: schema.TypeMap, - Optional: true, - Computed: true, - ForceNew: false, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "instances": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "role": { - Type: schema.TypeString, - Computed: true, - }, - "floating_ip": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - }, + Schema: resourceDBaaSPostgreSQLDatastoreV1Schema(), } } @@ -299,7 +113,7 @@ func resourceDBaaSPostgreSQLDatastoreV1Create(ctx context.Context, d *schema.Res log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", datastore.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastore.ID, timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastore.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectDatastore, err)) } @@ -422,10 +236,10 @@ func resourceDBaaSPostgreSQLDatastoreV1Delete(ctx context.Context, d *schema.Res stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasDatastoreV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSDatastoreV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 20 * time.Second, } log.Printf("[DEBUG] waiting for datastore %s to become deleted", d.Id()) diff --git a/selectel/resource_selectel_dbaas_postgresql_extension_v1.go b/selectel/resource_selectel_dbaas_postgresql_extension_v1.go index 3deec5c7..5d1d0722 100644 --- a/selectel/resource_selectel_dbaas_postgresql_extension_v1.go +++ b/selectel/resource_selectel_dbaas_postgresql_extension_v1.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSPostgreSQLExtensionV1() *schema.Resource { @@ -28,51 +29,11 @@ func resourceDBaaSPostgreSQLExtensionV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "available_extension_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "database_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - }, + Schema: resourceDBaaSPostgreSQLExtensionV1Schema(), } } func resourceDBaaSPostgreSQLExtensionV1Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - - databaseID := d.Get("database_id").(string) - - selMutexKV.Lock(databaseID) - defer selMutexKV.Unlock(databaseID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr @@ -80,8 +41,8 @@ func resourceDBaaSPostgreSQLExtensionV1Create(ctx context.Context, d *schema.Res extensionCreateOpts := dbaas.ExtensionCreateOpts{ AvailableExtensionID: d.Get("available_extension_id").(string), - DatastoreID: datastoreID, - DatabaseID: databaseID, + DatastoreID: d.Get("datastore_id").(string), + DatabaseID: d.Get("database_id").(string), } log.Print(msgCreate(objectExtension, extensionCreateOpts)) @@ -92,7 +53,7 @@ func resourceDBaaSPostgreSQLExtensionV1Create(ctx context.Context, d *schema.Res log.Printf("[DEBUG] waiting for extension %s to become 'ACTIVE'", extension.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSExtensionV1ActiveState(ctx, dbaasClient, extension.ID, timeout) + err = waiters.WaitForDBaaSExtensionV1ActiveState(ctx, dbaasClient, extension.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectExtension, err)) } @@ -122,16 +83,6 @@ func resourceDBaaSPostgreSQLExtensionV1Read(ctx context.Context, d *schema.Resou } func resourceDBaaSPostgreSQLExtensionV1Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - - databaseID := d.Get("database_id").(string) - - selMutexKV.Lock(databaseID) - defer selMutexKV.Unlock(databaseID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr @@ -146,10 +97,10 @@ func resourceDBaaSPostgreSQLExtensionV1Delete(ctx context.Context, d *schema.Res stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasExtensionV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSExtensionV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 20 * time.Second, } log.Printf("[DEBUG] waiting for extension %s to become deleted", d.Id()) diff --git a/selectel/resource_selectel_dbaas_postgresql_logical_replication_slot_v1.go b/selectel/resource_selectel_dbaas_postgresql_logical_replication_slot_v1.go index a59ebb17..4eca60e2 100644 --- a/selectel/resource_selectel_dbaas_postgresql_logical_replication_slot_v1.go +++ b/selectel/resource_selectel_dbaas_postgresql_logical_replication_slot_v1.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSPostgreSQLLogicalReplicationSlotV1() *schema.Resource { @@ -28,51 +29,11 @@ func resourceDBaaSPostgreSQLLogicalReplicationSlotV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "database_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - }, + Schema: resourceDBaaSPostgreSQLLogicalReplicationSlotV1Schema(), } } func resourceDBaaSPostgreSQLLogicalReplicationSlotV1Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - - databaseID := d.Get("database_id").(string) - - selMutexKV.Lock(databaseID) - defer selMutexKV.Unlock(databaseID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr @@ -80,8 +41,8 @@ func resourceDBaaSPostgreSQLLogicalReplicationSlotV1Create(ctx context.Context, slotCreateOpts := dbaas.LogicalReplicationSlotCreateOpts{ Name: d.Get("name").(string), - DatastoreID: datastoreID, - DatabaseID: databaseID, + DatastoreID: d.Get("datastore_id").(string), + DatabaseID: d.Get("database_id").(string), } log.Print(msgCreate(objectLogicalReplicationSlot, slotCreateOpts)) @@ -92,7 +53,7 @@ func resourceDBaaSPostgreSQLLogicalReplicationSlotV1Create(ctx context.Context, log.Printf("[DEBUG] waiting for slot %s to become 'ACTIVE'", slot.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSLogicalReplicationSlotV1ActiveState(ctx, dbaasClient, slot.ID, timeout) + err = waiters.WaitForDBaaSLogicalReplicationSlotV1ActiveState(ctx, dbaasClient, slot.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectLogicalReplicationSlot, err)) } @@ -122,16 +83,6 @@ func resourceDBaaSPostgreSQLLogicalReplicationSlotV1Read(ctx context.Context, d } func resourceDBaaSPostgreSQLLogicalReplicationSlotV1Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - - databaseID := d.Get("database_id").(string) - - selMutexKV.Lock(databaseID) - defer selMutexKV.Unlock(databaseID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr @@ -146,10 +97,10 @@ func resourceDBaaSPostgreSQLLogicalReplicationSlotV1Delete(ctx context.Context, stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasLogicalReplicationSlotV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSLogicalReplicationSlotV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 20 * time.Second, } log.Printf("[DEBUG] waiting for slot %s to become deleted", d.Id()) diff --git a/selectel/resource_selectel_dbaas_prometheus_metric_token_v1.go b/selectel/resource_selectel_dbaas_prometheus_metric_token_v1.go index dbc62c54..7c2babe0 100644 --- a/selectel/resource_selectel_dbaas_prometheus_metric_token_v1.go +++ b/selectel/resource_selectel_dbaas_prometheus_metric_token_v1.go @@ -29,25 +29,7 @@ func resourceDBaaSPrometheusMetricTokenV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "project_id": { - Type: schema.TypeString, - Required: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - }, - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "value": { - Type: schema.TypeString, - Computed: true, - }, - }, + Schema: resourceDBaaSPostgreSQLPrometheusMetricTokenV1Schema(), } } @@ -96,10 +78,8 @@ func resourceDBaaSPrometheusMetricTokenV1Update(ctx context.Context, d *schema.R } if d.HasChange("name") { - name := d.Get("name").(string) - updateOpts := dbaas.PrometheusMetricTokenUpdateOpts{ - Name: name, + Name: d.Get("name").(string), } log.Print(msgUpdate(objectPrometheusMetricToken, d.Id(), updateOpts)) @@ -130,7 +110,7 @@ func resourceDBaaSPrometheusMetricTokenV1Delete(ctx context.Context, d *schema.R Refresh: dbaasPrometheusMetricTokenV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 10 * time.Second, } log.Printf("[DEBUG] waiting for token %s to become deleted", d.Id()) diff --git a/selectel/resource_selectel_dbaas_redis_datastore_v1.go b/selectel/resource_selectel_dbaas_redis_datastore_v1.go index c2e23150..b6c5c264 100644 --- a/selectel/resource_selectel_dbaas_redis_datastore_v1.go +++ b/selectel/resource_selectel_dbaas_redis_datastore_v1.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSRedisDatastoreV1() *schema.Resource { @@ -33,166 +34,7 @@ func resourceDBaaSRedisDatastoreV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "subnet_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "type_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "flavor_id": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "node_count": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - }, - "enabled": { - Type: schema.TypeBool, - Computed: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - "backup_retention_days": { - Type: schema.TypeInt, - Optional: true, - Computed: true, - Description: "Number of days to retain backups.", - }, - "connections": { - Type: schema.TypeMap, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "floating_ips": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "master": { - Type: schema.TypeInt, - Required: true, - }, - "replica": { - Type: schema.TypeInt, - Required: true, - }, - }, - }, - }, - "flavor": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "vcpus": { - Type: schema.TypeInt, - Computed: true, - }, - "ram": { - Type: schema.TypeInt, - Computed: true, - }, - "disk": { - Type: schema.TypeInt, - Computed: true, - }, - }, - }, - }, - "firewall": { - Type: schema.TypeSet, - Optional: true, - ForceNew: false, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "ips": { - Type: schema.TypeList, - Required: true, - ForceNew: false, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "restore": { - Type: schema.TypeSet, - Optional: true, - ForceNew: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "target_time": { - Type: schema.TypeString, - Optional: true, - ForceNew: false, - }, - }, - }, - }, - "config": { - Type: schema.TypeMap, - Optional: true, - Computed: true, - ForceNew: false, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "redis_password": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "instances": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "role": { - Type: schema.TypeString, - Computed: true, - }, - "floating_ip": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - }, + Schema: resourceDBaaSRedisDatastoreV1Schema(), } } @@ -254,7 +96,7 @@ func resourceDBaaSRedisDatastoreV1Create(ctx context.Context, d *schema.Resource log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", datastore.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastore.ID, timeout) + err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastore.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectDatastore, err)) } @@ -377,10 +219,10 @@ func resourceDBaaSRedisDatastoreV1Delete(ctx context.Context, d *schema.Resource stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasDatastoreV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSDatastoreV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 15 * time.Second, } log.Printf("[DEBUG] waiting for datastore %s to become deleted", d.Id()) diff --git a/selectel/resource_selectel_dbaas_user_v1.go b/selectel/resource_selectel_dbaas_user_v1.go index 362e0738..38453b09 100644 --- a/selectel/resource_selectel_dbaas_user_v1.go +++ b/selectel/resource_selectel_dbaas_user_v1.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/selectel/dbaas-go" + waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" ) func resourceDBaaSUserV1() *schema.Resource { @@ -29,53 +30,18 @@ func resourceDBaaSUserV1() *schema.Resource { Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, - Schema: map[string]*schema.Schema{ - "datastore_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "region": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "password": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - "project_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - }, + Schema: resourceDBaaSUserV1Schema(), } } func resourceDBaaSUserV1Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr } userCreateOpts := dbaas.UserCreateOpts{ - DatastoreID: datastoreID, + DatastoreID: d.Get("datastore_id").(string), Name: d.Get("name").(string), Password: d.Get("password").(string), } @@ -88,7 +54,7 @@ func resourceDBaaSUserV1Create(ctx context.Context, d *schema.ResourceData, meta log.Printf("[DEBUG] waiting for user %s to become 'ACTIVE'", user.ID) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSUserV1ActiveState(ctx, dbaasClient, user.ID, timeout) + err = waiters.WaitForDBaaSUserV1ActiveState(ctx, dbaasClient, user.ID, timeout) if err != nil { return diag.FromErr(errCreatingObject(objectUser, err)) } @@ -117,20 +83,14 @@ func resourceDBaaSUserV1Read(ctx context.Context, d *schema.ResourceData, meta i } func resourceDBaaSUserV1Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr } if d.HasChange("password") { - password := d.Get("password").(string) updateOpts := dbaas.UserUpdateOpts{ - Password: password, + Password: d.Get("password").(string), } log.Print(msgUpdate(objectUser, d.Id(), updateOpts)) @@ -141,7 +101,7 @@ func resourceDBaaSUserV1Update(ctx context.Context, d *schema.ResourceData, meta log.Printf("[DEBUG] waiting for user %s to become 'ACTIVE'", d.Id()) timeout := d.Timeout(schema.TimeoutCreate) - err = waitForDBaaSUserV1ActiveState(ctx, dbaasClient, d.Id(), timeout) + err = waiters.WaitForDBaaSUserV1ActiveState(ctx, dbaasClient, d.Id(), timeout) if err != nil { return diag.FromErr(errUpdatingObject(objectUser, d.Id(), err)) } @@ -151,11 +111,6 @@ func resourceDBaaSUserV1Update(ctx context.Context, d *schema.ResourceData, meta } func resourceDBaaSUserV1Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - datastoreID := d.Get("datastore_id").(string) - - selMutexKV.Lock(datastoreID) - defer selMutexKV.Unlock(datastoreID) - dbaasClient, diagErr := getDBaaSClient(d, meta) if diagErr != nil { return diagErr @@ -170,10 +125,10 @@ func resourceDBaaSUserV1Delete(ctx context.Context, d *schema.ResourceData, meta stateConf := &resource.StateChangeConf{ Pending: []string{strconv.Itoa(http.StatusOK)}, Target: []string{strconv.Itoa(http.StatusNotFound)}, - Refresh: dbaasUserV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), + Refresh: waiters.DBaaSUserV1DeleteStateRefreshFunc(ctx, dbaasClient, d.Id()), Timeout: d.Timeout(schema.TimeoutDelete), Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, + MinTimeout: 15 * time.Second, } log.Printf("[DEBUG] waiting for user %s to become deleted", d.Id()) diff --git a/selectel/schema_selectel_dbaas_datastore_v1.go b/selectel/schema_selectel_dbaas_datastore_v1.go new file mode 100644 index 00000000..95e06ae7 --- /dev/null +++ b/selectel/schema_selectel_dbaas_datastore_v1.go @@ -0,0 +1,76 @@ +package selectel + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceDBaaSDatastoreV1Schema() map[string]*schema.Schema { + datastoreSchema := resourceDBaaSDatastoreV1BaseSchema() + datastoreSchema["backup_retention_days"] = &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Description: "Number of days to retain backups.", + } + datastoreSchema["pooler"] = &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "session", + "transaction", + "statement", + }, false), + }, + "size": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + } + datastoreSchema["restore"] = &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "datastore_id": { + Type: schema.TypeString, + Optional: true, + }, + "target_time": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + } + datastoreSchema["redis_password"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Sensitive: true, + } + datastoreSchema["floating_ips"] = &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "master": { + Type: schema.TypeInt, + Required: true, + }, + "replica": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + } + + return datastoreSchema +} diff --git a/selectel/schema_selectel_dbaas_grant_v1.go b/selectel/schema_selectel_dbaas_grant_v1.go new file mode 100644 index 00000000..f5537248 --- /dev/null +++ b/selectel/schema_selectel_dbaas_grant_v1.go @@ -0,0 +1,37 @@ +package selectel + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func resourceDBaaSGrantV1Schema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "project_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "region": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "datastore_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "database_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "user_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + } +} diff --git a/selectel/schema_selectel_dbaas_kafka_acl_v1.go b/selectel/schema_selectel_dbaas_kafka_acl_v1.go new file mode 100644 index 00000000..abb10c83 --- /dev/null +++ b/selectel/schema_selectel_dbaas_kafka_acl_v1.go @@ -0,0 +1,58 @@ +package selectel + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceDBaaSKafkaACKV1Schema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "datastore_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "region": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "pattern": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "pattern_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + "literal", + "prefixed", + "all", + }, false), + }, + "user_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "allow_read": { + Type: schema.TypeBool, + Required: true, + }, + "allow_write": { + Type: schema.TypeBool, + Required: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "project_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + } +} diff --git a/selectel/schema_selectel_dbaas_kafka_datastore_v1.go b/selectel/schema_selectel_dbaas_kafka_datastore_v1.go new file mode 100644 index 00000000..5bac6306 --- /dev/null +++ b/selectel/schema_selectel_dbaas_kafka_datastore_v1.go @@ -0,0 +1,7 @@ +package selectel + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func resourceDBaaSKafkaDatastoreV1Schema() map[string]*schema.Schema { + return resourceDBaaSDatastoreV1BaseSchema() +} diff --git a/selectel/schema_selectel_dbaas_kafka_topic_v1.go b/selectel/schema_selectel_dbaas_kafka_topic_v1.go new file mode 100644 index 00000000..82d57dca --- /dev/null +++ b/selectel/schema_selectel_dbaas_kafka_topic_v1.go @@ -0,0 +1,36 @@ +package selectel + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func resourceDBaaSKafkaTopicV1Schema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "datastore_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "region": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "partitions": { + Type: schema.TypeInt, + Required: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "project_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + } +} diff --git a/selectel/schema_selectel_dbaas_mysql_database_v1.go b/selectel/schema_selectel_dbaas_mysql_database_v1.go new file mode 100644 index 00000000..15c558d0 --- /dev/null +++ b/selectel/schema_selectel_dbaas_mysql_database_v1.go @@ -0,0 +1,7 @@ +package selectel + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func resourceDBaaSMySQLDatabaseV1Schema() map[string]*schema.Schema { + return resourceDBaaSDatabaseV1BaseSchema() +} diff --git a/selectel/schema_selectel_dbaas_mysql_datastore_v1.go b/selectel/schema_selectel_dbaas_mysql_datastore_v1.go new file mode 100644 index 00000000..253ecb58 --- /dev/null +++ b/selectel/schema_selectel_dbaas_mysql_datastore_v1.go @@ -0,0 +1,47 @@ +package selectel + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func resourceDBaaSMySQLDatastoreV1Schema() map[string]*schema.Schema { + datastoreSchema := resourceDBaaSDatastoreV1BaseSchema() + datastoreSchema["backup_retention_days"] = &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Description: "Number of days to retain backups.", + } + datastoreSchema["restore"] = &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "datastore_id": { + Type: schema.TypeString, + Optional: true, + }, + "target_time": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + } + datastoreSchema["floating_ips"] = &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "master": { + Type: schema.TypeInt, + Required: true, + }, + "replica": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + } + + return datastoreSchema +} diff --git a/selectel/schema_selectel_dbaas_postgresql_database_v1.go b/selectel/schema_selectel_dbaas_postgresql_database_v1.go new file mode 100644 index 00000000..175a6202 --- /dev/null +++ b/selectel/schema_selectel_dbaas_postgresql_database_v1.go @@ -0,0 +1,36 @@ +package selectel + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceDBaaSPostgreSQLDatabaseV1Schema() map[string]*schema.Schema { + databaseSchema := resourceDBaaSDatabaseV1BaseSchema() + databaseSchema["owner"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + } + databaseSchema["lc_collate"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: dbaasDatabaseV1LocaleDiffSuppressFunc, + } + databaseSchema["lc_ctype"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: dbaasDatabaseV1LocaleDiffSuppressFunc, + } + + return databaseSchema +} + +func dbaasDatabaseV1LocaleDiffSuppressFunc(_, old, new string, _ *schema.ResourceData) bool { + // The default locale value - C is the same as null value, so we need to suppress + if old == "C" && new == "" { + return true + } + + return false +} diff --git a/selectel/schema_selectel_dbaas_postgresql_datastore_v1.go b/selectel/schema_selectel_dbaas_postgresql_datastore_v1.go new file mode 100644 index 00000000..60bb67c9 --- /dev/null +++ b/selectel/schema_selectel_dbaas_postgresql_datastore_v1.go @@ -0,0 +1,71 @@ +package selectel + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceDBaaSPostgreSQLDatastoreV1Schema() map[string]*schema.Schema { + datastoreSchema := resourceDBaaSDatastoreV1BaseSchema() + datastoreSchema["backup_retention_days"] = &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Description: "Number of days to retain backups.", + } + datastoreSchema["pooler"] = &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "session", + "transaction", + "statement", + }, false), + }, + "size": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + } + datastoreSchema["restore"] = &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "datastore_id": { + Type: schema.TypeString, + Optional: true, + }, + "target_time": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + } + datastoreSchema["floating_ips"] = &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "master": { + Type: schema.TypeInt, + Required: true, + }, + "replica": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + } + + return datastoreSchema +} diff --git a/selectel/schema_selectel_dbaas_postgresql_extension_v1.go b/selectel/schema_selectel_dbaas_postgresql_extension_v1.go new file mode 100644 index 00000000..5d5ca184 --- /dev/null +++ b/selectel/schema_selectel_dbaas_postgresql_extension_v1.go @@ -0,0 +1,37 @@ +package selectel + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func resourceDBaaSPostgreSQLExtensionV1Schema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "project_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "region": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "available_extension_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "datastore_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "database_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + } +} diff --git a/selectel/schema_selectel_dbaas_postgresql_logical_replication_slot_v1.go b/selectel/schema_selectel_dbaas_postgresql_logical_replication_slot_v1.go new file mode 100644 index 00000000..1ec03790 --- /dev/null +++ b/selectel/schema_selectel_dbaas_postgresql_logical_replication_slot_v1.go @@ -0,0 +1,37 @@ +package selectel + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func resourceDBaaSPostgreSQLLogicalReplicationSlotV1Schema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "project_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "region": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "datastore_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "database_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + } +} diff --git a/selectel/schema_selectel_dbaas_prometheus_metric_token_v1.go b/selectel/schema_selectel_dbaas_prometheus_metric_token_v1.go new file mode 100644 index 00000000..48e9837d --- /dev/null +++ b/selectel/schema_selectel_dbaas_prometheus_metric_token_v1.go @@ -0,0 +1,24 @@ +package selectel + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func resourceDBaaSPostgreSQLPrometheusMetricTokenV1Schema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "project_id": { + Type: schema.TypeString, + Required: true, + }, + "region": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Computed: true, + }, + } +} diff --git a/selectel/schema_selectel_dbaas_redis_datastore_v1.go b/selectel/schema_selectel_dbaas_redis_datastore_v1.go new file mode 100644 index 00000000..c21b1412 --- /dev/null +++ b/selectel/schema_selectel_dbaas_redis_datastore_v1.go @@ -0,0 +1,76 @@ +package selectel + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func resourceDBaaSRedisDatastoreV1Schema() map[string]*schema.Schema { + datastoreSchema := resourceDBaaSDatastoreV1BaseSchema() + datastoreSchema["backup_retention_days"] = &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Description: "Number of days to retain backups.", + } + datastoreSchema["restore"] = &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "datastore_id": { + Type: schema.TypeString, + Optional: true, + }, + "target_time": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + } + datastoreSchema["flavor"] = &schema.Schema{ + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "vcpus": { + Type: schema.TypeInt, + Computed: true, + }, + "ram": { + Type: schema.TypeInt, + Computed: true, + }, + "disk": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + } + datastoreSchema["flavor_id"] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + } + datastoreSchema["redis_password"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Sensitive: true, + } + datastoreSchema["floating_ips"] = &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "master": { + Type: schema.TypeInt, + Required: true, + }, + "replica": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + } + + return datastoreSchema +} diff --git a/selectel/schema_selectel_dbaas_user_v1.go b/selectel/schema_selectel_dbaas_user_v1.go new file mode 100644 index 00000000..20796427 --- /dev/null +++ b/selectel/schema_selectel_dbaas_user_v1.go @@ -0,0 +1,37 @@ +package selectel + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func resourceDBaaSUserV1Schema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "datastore_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "region": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "password": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "project_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + } +} diff --git a/selectel/waiters/dbaas/acl.go b/selectel/waiters/dbaas/acl.go new file mode 100644 index 00000000..ac3137e2 --- /dev/null +++ b/selectel/waiters/dbaas/acl.go @@ -0,0 +1,70 @@ +package waiters + +import ( + "context" + "errors" + "fmt" + "net/http" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/selectel/dbaas-go" +) + +func WaitForDBaaSACLV1ActiveState( + ctx context.Context, client *dbaas.API, aclID string, timeout time.Duration, +) error { + pending := []string{ + string(dbaas.StatusPendingCreate), + string(dbaas.StatusPendingUpdate), + } + target := []string{ + string(dbaas.StatusActive), + } + + stateConf := &resource.StateChangeConf{ + Pending: pending, + Target: target, + Refresh: dbaasACLV1StateRefreshFunc(ctx, client, aclID), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 15 * time.Second, + } + + _, err := stateConf.WaitForStateContext(ctx) + if err != nil { + return fmt.Errorf( + "error waiting for the acl %s to become 'ACTIVE': %s", + aclID, err) + } + + return nil +} + +func DBaaSACLV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, aclID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.ACL(ctx, aclID) + if err != nil { + var dbaasError *dbaas.DBaaSAPIError + if errors.As(err, &dbaasError) { + return d, strconv.Itoa(dbaasError.StatusCode()), nil + } + + return nil, "", err + } + + return d, strconv.Itoa(http.StatusOK), err + } +} + +func dbaasACLV1StateRefreshFunc(ctx context.Context, client *dbaas.API, aclID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.ACL(ctx, aclID) + if err != nil { + return nil, "", err + } + + return d, string(d.Status), nil + } +} diff --git a/selectel/waiters/dbaas/database.go b/selectel/waiters/dbaas/database.go new file mode 100644 index 00000000..1ff454fe --- /dev/null +++ b/selectel/waiters/dbaas/database.go @@ -0,0 +1,70 @@ +package waiters + +import ( + "context" + "errors" + "fmt" + "net/http" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/selectel/dbaas-go" +) + +func WaitForDBaaSDatabaseV1ActiveState( + ctx context.Context, client *dbaas.API, databaseID string, timeout time.Duration, +) error { + pending := []string{ + string(dbaas.StatusPendingCreate), + string(dbaas.StatusPendingUpdate), + } + target := []string{ + string(dbaas.StatusActive), + } + + stateConf := &resource.StateChangeConf{ + Pending: pending, + Target: target, + Refresh: dbaasDatabaseV1StateRefreshFunc(ctx, client, databaseID), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + + _, err := stateConf.WaitForStateContext(ctx) + if err != nil { + return fmt.Errorf( + "error waiting for the database %s to become 'ACTIVE': %s", + databaseID, err) + } + + return nil +} + +func DBaaSDatabaseV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, datastoreID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.Database(ctx, datastoreID) + if err != nil { + var dbaasError *dbaas.DBaaSAPIError + if errors.As(err, &dbaasError) { + return d, strconv.Itoa(dbaasError.StatusCode()), nil + } + + return nil, "", err + } + + return d, strconv.Itoa(http.StatusOK), err + } +} + +func dbaasDatabaseV1StateRefreshFunc(ctx context.Context, client *dbaas.API, databaseID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.Database(ctx, databaseID) + if err != nil { + return nil, "", err + } + + return d, string(d.Status), nil + } +} diff --git a/selectel/waiters/dbaas/datastore.go b/selectel/waiters/dbaas/datastore.go new file mode 100644 index 00000000..6cf0af26 --- /dev/null +++ b/selectel/waiters/dbaas/datastore.go @@ -0,0 +1,71 @@ +package waiters + +import ( + "context" + "errors" + "fmt" + "net/http" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/selectel/dbaas-go" +) + +func WaitForDBaaSDatastoreV1ActiveState( + ctx context.Context, client *dbaas.API, datastoreID string, timeout time.Duration, +) error { + pending := []string{ + string(dbaas.StatusPendingCreate), + string(dbaas.StatusPendingUpdate), + string(dbaas.StatusResizing), + } + target := []string{ + string(dbaas.StatusActive), + } + + stateConf := &resource.StateChangeConf{ + Pending: pending, + Target: target, + Refresh: dbaasDatastoreV1StateRefreshFunc(ctx, client, datastoreID), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 20 * time.Second, + } + + _, err := stateConf.WaitForState() + if err != nil { + return fmt.Errorf( + "error waiting for the datastore %s to become 'ACTIVE': %s", + datastoreID, err) + } + + return nil +} + +func DBaaSDatastoreV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, datastoreID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.Datastore(ctx, datastoreID) + if err != nil { + var dbaasError *dbaas.DBaaSAPIError + if errors.As(err, &dbaasError) { + return d, strconv.Itoa(dbaasError.StatusCode()), nil + } + + return nil, "", err + } + + return d, strconv.Itoa(http.StatusOK), err + } +} + +func dbaasDatastoreV1StateRefreshFunc(ctx context.Context, client *dbaas.API, datastoreID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.Datastore(ctx, datastoreID) + if err != nil { + return nil, "", err + } + + return d, string(d.Status), nil + } +} diff --git a/selectel/waiters/dbaas/extension.go b/selectel/waiters/dbaas/extension.go new file mode 100644 index 00000000..826fd0c1 --- /dev/null +++ b/selectel/waiters/dbaas/extension.go @@ -0,0 +1,69 @@ +package waiters + +import ( + "context" + "errors" + "fmt" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/selectel/dbaas-go" +) + +func WaitForDBaaSExtensionV1ActiveState( + ctx context.Context, client *dbaas.API, extensionID string, timeout time.Duration, +) error { + pending := []string{ + string(dbaas.StatusPendingCreate), + string(dbaas.StatusPendingUpdate), + } + target := []string{ + string(dbaas.StatusActive), + } + + stateConf := &resource.StateChangeConf{ + Pending: pending, + Target: target, + Refresh: dbaasExtensionV1StateRefreshFunc(ctx, client, extensionID), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 15 * time.Second, + } + + _, err := stateConf.WaitForStateContext(ctx) + if err != nil { + return fmt.Errorf( + "error waiting for the extension %s to become 'ACTIVE': %s", + extensionID, err) + } + + return nil +} + +func DBaaSExtensionV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, extensionID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.Extension(ctx, extensionID) + if err != nil { + var dbaasError *dbaas.DBaaSAPIError + if errors.As(err, &dbaasError) { + return d, strconv.Itoa(dbaasError.StatusCode()), nil + } + + return nil, "", err + } + + return d, strconv.Itoa(200), err + } +} + +func dbaasExtensionV1StateRefreshFunc(ctx context.Context, client *dbaas.API, extensionID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.Extension(ctx, extensionID) + if err != nil { + return nil, "", err + } + + return d, string(d.Status), nil + } +} diff --git a/selectel/waiters/dbaas/grant.go b/selectel/waiters/dbaas/grant.go new file mode 100644 index 00000000..a2b3c371 --- /dev/null +++ b/selectel/waiters/dbaas/grant.go @@ -0,0 +1,69 @@ +package waiters + +import ( + "context" + "errors" + "fmt" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/selectel/dbaas-go" +) + +func WaitForDBaaSGrantV1ActiveState( + ctx context.Context, client *dbaas.API, grantID string, timeout time.Duration, +) error { + pending := []string{ + string(dbaas.StatusPendingCreate), + string(dbaas.StatusPendingUpdate), + } + target := []string{ + string(dbaas.StatusActive), + } + + stateConf := &resource.StateChangeConf{ + Pending: pending, + Target: target, + Refresh: dbaasGrantV1StateRefreshFunc(ctx, client, grantID), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + + _, err := stateConf.WaitForStateContext(ctx) + if err != nil { + return fmt.Errorf( + "error waiting for the grant %s to become 'ACTIVE': %s", + grantID, err) + } + + return nil +} + +func DBaaSGrantV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, grantID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.Grant(ctx, grantID) + if err != nil { + var dbaasError *dbaas.DBaaSAPIError + if errors.As(err, &dbaasError) { + return d, strconv.Itoa(dbaasError.StatusCode()), nil + } + + return nil, "", err + } + + return d, strconv.Itoa(200), err + } +} + +func dbaasGrantV1StateRefreshFunc(ctx context.Context, client *dbaas.API, grantID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.Grant(ctx, grantID) + if err != nil { + return nil, "", err + } + + return d, string(d.Status), nil + } +} diff --git a/selectel/waiters/dbaas/logical_replication_slot.go b/selectel/waiters/dbaas/logical_replication_slot.go new file mode 100644 index 00000000..1960bd72 --- /dev/null +++ b/selectel/waiters/dbaas/logical_replication_slot.go @@ -0,0 +1,70 @@ +package waiters + +import ( + "context" + "errors" + "fmt" + "net/http" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/selectel/dbaas-go" +) + +func WaitForDBaaSLogicalReplicationSlotV1ActiveState( + ctx context.Context, client *dbaas.API, slotID string, timeout time.Duration, +) error { + pending := []string{ + string(dbaas.StatusPendingCreate), + string(dbaas.StatusPendingUpdate), + } + target := []string{ + string(dbaas.StatusActive), + } + + stateConf := &resource.StateChangeConf{ + Pending: pending, + Target: target, + Refresh: dbaasLogicalReplicationSlotV1StateRefreshFunc(ctx, client, slotID), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 15 * time.Second, + } + + _, err := stateConf.WaitForStateContext(ctx) + if err != nil { + return fmt.Errorf( + "error waiting for the slot %s to become 'ACTIVE': %s", + slotID, err) + } + + return nil +} + +func DBaaSLogicalReplicationSlotV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, slotID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.LogicalReplicationSlot(ctx, slotID) + if err != nil { + var dbaasError *dbaas.DBaaSAPIError + if errors.As(err, &dbaasError) { + return d, strconv.Itoa(dbaasError.StatusCode()), nil + } + + return nil, "", err + } + + return d, strconv.Itoa(http.StatusOK), err + } +} + +func dbaasLogicalReplicationSlotV1StateRefreshFunc(ctx context.Context, client *dbaas.API, slotID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.LogicalReplicationSlot(ctx, slotID) + if err != nil { + return nil, "", err + } + + return d, string(d.Status), nil + } +} diff --git a/selectel/waiters/dbaas/topic.go b/selectel/waiters/dbaas/topic.go new file mode 100644 index 00000000..e7dc219a --- /dev/null +++ b/selectel/waiters/dbaas/topic.go @@ -0,0 +1,70 @@ +package waiters + +import ( + "context" + "errors" + "fmt" + "net/http" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/selectel/dbaas-go" +) + +func WaitForDBaaSTopicV1ActiveState( + ctx context.Context, client *dbaas.API, topicID string, timeout time.Duration, +) error { + pending := []string{ + string(dbaas.StatusPendingCreate), + string(dbaas.StatusPendingUpdate), + } + target := []string{ + string(dbaas.StatusActive), + } + + stateConf := &resource.StateChangeConf{ + Pending: pending, + Target: target, + Refresh: dbaasTopicV1StateRefreshFunc(ctx, client, topicID), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 20 * time.Second, + } + + _, err := stateConf.WaitForStateContext(ctx) + if err != nil { + return fmt.Errorf( + "error waiting for the topic %s to become 'ACTIVE': %s", + topicID, err) + } + + return nil +} + +func DBaaSTopicV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, topicID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.Topic(ctx, topicID) + if err != nil { + var dbaasError *dbaas.DBaaSAPIError + if errors.As(err, &dbaasError) { + return d, strconv.Itoa(dbaasError.StatusCode()), nil + } + + return nil, "", err + } + + return d, strconv.Itoa(http.StatusOK), err + } +} + +func dbaasTopicV1StateRefreshFunc(ctx context.Context, client *dbaas.API, topicID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.Topic(ctx, topicID) + if err != nil { + return nil, "", err + } + + return d, string(d.Status), nil + } +} diff --git a/selectel/waiters/dbaas/user.go b/selectel/waiters/dbaas/user.go new file mode 100644 index 00000000..45e03bb1 --- /dev/null +++ b/selectel/waiters/dbaas/user.go @@ -0,0 +1,70 @@ +package waiters + +import ( + "context" + "errors" + "fmt" + "net/http" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/selectel/dbaas-go" +) + +func WaitForDBaaSUserV1ActiveState( + ctx context.Context, client *dbaas.API, userID string, timeout time.Duration, +) error { + pending := []string{ + string(dbaas.StatusPendingCreate), + string(dbaas.StatusPendingUpdate), + } + target := []string{ + string(dbaas.StatusActive), + } + + stateConf := &resource.StateChangeConf{ + Pending: pending, + Target: target, + Refresh: dbaasUserV1StateRefreshFunc(ctx, client, userID), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + + _, err := stateConf.WaitForStateContext(ctx) + if err != nil { + return fmt.Errorf( + "error waiting for the user %s to become 'ACTIVE': %s", + userID, err) + } + + return nil +} + +func DBaaSUserV1DeleteStateRefreshFunc(ctx context.Context, client *dbaas.API, userID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.User(ctx, userID) + if err != nil { + var dbaasError *dbaas.DBaaSAPIError + if errors.As(err, &dbaasError) { + return d, strconv.Itoa(dbaasError.StatusCode()), nil + } + + return nil, "", err + } + + return d, strconv.Itoa(http.StatusOK), err + } +} + +func dbaasUserV1StateRefreshFunc(ctx context.Context, client *dbaas.API, userID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + d, err := client.User(ctx, userID) + if err != nil { + return nil, "", err + } + + return d, string(d.Status), nil + } +} diff --git a/website/docs/d/dbaas_configuration_parameter_v1.html.markdown b/website/docs/d/dbaas_configuration_parameter_v1.html.markdown index 6b3a351d..33245d94 100644 --- a/website/docs/d/dbaas_configuration_parameter_v1.html.markdown +++ b/website/docs/d/dbaas_configuration_parameter_v1.html.markdown @@ -53,6 +53,9 @@ data "selectel_dbaas_configuration_parameter_v1" "configuration_parameter_1" { * `choices` - Available choices for the configuration parameter. Some parameters have list of available options. + * `invalid_values` - Invalid values for the configuration parameter. + Some parameters have list of values within a range that are not available for the parameter. + * `is_restart_required` - Shows if the database needs a restart to apply changes. * `is_changeable` - Shows if the parameter can be changed. \ No newline at end of file diff --git a/website/docs/d/dbaas_flavor_v1.html.markdown b/website/docs/d/dbaas_flavor_v1.html.markdown index 214e0a2e..2d95e15a 100644 --- a/website/docs/d/dbaas_flavor_v1.html.markdown +++ b/website/docs/d/dbaas_flavor_v1.html.markdown @@ -33,6 +33,8 @@ data "selectel_dbaas_flavor_v1" "flavor" { * `disk` - (Optional) Volume size in GB. + * `fl_size` - (Optional) Fl size of the flavor. + * `datastore_type_id` - (Optional) Unique identifier of the datastore type. ## Attributes Reference @@ -51,4 +53,6 @@ data "selectel_dbaas_flavor_v1" "flavor" { * `disk` - Volume size in GB. + * `fl_size` - Fl size of the flavor. + * `datastore_type_ids` - List of datastore types that support this flavor. \ No newline at end of file