From ed8c4e11019a5a8c58c347b9a3a274034845f097 Mon Sep 17 00:00:00 2001 From: Ludwig Patte Date: Thu, 12 Jan 2023 13:47:24 +0000 Subject: [PATCH] add advanced config and manage avnadmin user --- ovh/data_cloud_project_database.go | 17 ++ ovh/data_cloud_project_database_databases.go | 8 +- ovh/resource_cloud_project_database.go | 37 +++- ...source_cloud_project_database_m3db_user.go | 105 +---------- ...rce_cloud_project_database_mongodb_user.go | 22 +-- ..._cloud_project_database_opensearch_user.go | 105 +---------- ..._cloud_project_database_postgresql_user.go | 106 +---------- ...ource_cloud_project_database_redis_user.go | 106 +---------- ovh/resource_cloud_project_database_user.go | 58 +----- ovh/types_cloud_project_database.go | 176 ++++++++++++++++-- .../d/cloud_project_database.html.markdown | 1 + ...cloud_project_database_users.html.markdown | 5 - .../r/cloud_project_database.html.markdown | 9 + ...d_project_database_m3db_user.html.markdown | 2 +- ...ect_database_opensearch_user.html.markdown | 2 +- ...ect_database_postgresql_user.html.markdown | 2 +- ..._project_database_redis_user.html.markdown | 2 +- .../cloud_project_database_user.html.markdown | 2 +- 18 files changed, 274 insertions(+), 491 deletions(-) diff --git a/ovh/data_cloud_project_database.go b/ovh/data_cloud_project_database.go index ce8d83267..dbf4e16d1 100644 --- a/ovh/data_cloud_project_database.go +++ b/ovh/data_cloud_project_database.go @@ -167,6 +167,14 @@ func dataSourceCloudProjectDatabase() *schema.Resource { Description: "Disk type attributes of the cluster", Computed: true, }, + "advanced_configuration": { + Type: schema.TypeMap, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: "Advanced configuration key / value", + Computed: true, + }, }, } } @@ -206,6 +214,15 @@ func dataSourceCloudProjectDatabaseRead(d *schema.ResourceData, meta interface{} res.Region = node.Region + if engine != "mongodb" { + advancedConfigEndpoint := fmt.Sprintf("%s/advancedConfiguration", serviceEndpoint) + advancedConfigMap := &map[string]string{} + if err := config.OVHClient.Get(advancedConfigEndpoint, advancedConfigMap); err != nil { + return fmt.Errorf("unable to get database %s advanced configuration: %v", res.Id, err) + } + res.AdvancedConfiguration = *advancedConfigMap + } + for k, v := range res.ToMap() { if k != "id" { d.Set(k, v) diff --git a/ovh/data_cloud_project_database_databases.go b/ovh/data_cloud_project_database_databases.go index 7069f75b1..f20fdea19 100644 --- a/ovh/data_cloud_project_database_databases.go +++ b/ovh/data_cloud_project_database_databases.go @@ -7,6 +7,7 @@ import ( "sort" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/ovh/terraform-provider-ovh/ovh/helpers" "github.com/ovh/terraform-provider-ovh/ovh/helpers/hashcode" ) @@ -20,9 +21,10 @@ func dataSourceCloudProjectDatabaseDatabases() *schema.Resource { DefaultFunc: schema.EnvDefaultFunc("OVH_CLOUD_PROJECT_SERVICE", nil), }, "engine": { - Type: schema.TypeString, - Description: "Name of the engine of the service", - Required: true, + Type: schema.TypeString, + Description: "Name of the engine of the service", + Required: true, + ValidateFunc: helpers.ValidateEnum([]string{"mysql", "postgresql"}), }, "cluster_id": { Type: schema.TypeString, diff --git a/ovh/resource_cloud_project_database.go b/ovh/resource_cloud_project_database.go index c43456101..b1c34d058 100644 --- a/ovh/resource_cloud_project_database.go +++ b/ovh/resource_cloud_project_database.go @@ -113,6 +113,18 @@ func resourceCloudProjectDatabase() *schema.Resource { Computed: true, ValidateFunc: validateCloudProjectDatabaseDiskSize, }, + "advanced_configuration": { + Type: schema.TypeMap, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: "Advanced configuration key / value", + Optional: true, + Computed: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return d.Get("engine").(string) == "mongodb" || new == old + }, + }, //Computed "backup_time": { @@ -247,7 +259,9 @@ func resourceCloudProjectDatabaseCreate(d *schema.ResourceData, meta interface{} d.SetId(res.Id) - if (engine == "kafka" && d.Get("kafka_rest_api").(bool)) || (engine == "opensearch" && d.Get("opensearch_acls_enabled").(bool)) { + if (engine != "mongodb" && len(d.Get("advanced_configuration").(map[string]interface{})) > 0) || + (engine == "kafka" && d.Get("kafka_rest_api").(bool)) || + (engine == "opensearch" && d.Get("opensearch_acls_enabled").(bool)) { return resourceCloudProjectDatabaseUpdate(d, meta) } @@ -288,6 +302,15 @@ func resourceCloudProjectDatabaseRead(d *schema.ResourceData, meta interface{}) res.Region = node.Region + if engine != "mongodb" { + advancedConfigEndpoint := fmt.Sprintf("%s/advancedConfiguration", serviceEndpoint) + advancedConfigMap := &map[string]string{} + if err := config.OVHClient.Get(advancedConfigEndpoint, advancedConfigMap); err != nil { + return fmt.Errorf("unable to get database %s advanced configuration: %v", res.Id, err) + } + res.AdvancedConfiguration = *advancedConfigMap + } + for k, v := range res.ToMap() { if k != "id" { d.Set(k, v) @@ -325,6 +348,18 @@ func resourceCloudProjectDatabaseUpdate(d *schema.ResourceData, meta interface{} if err != nil { return fmt.Errorf("timeout while waiting database %s to be READY: %w", d.Id(), err) } + + if d.HasChanges("advanced_configuration") { + acParams := d.Get("advanced_configuration").(map[string]interface{}) + + advancedConfigEndpoint := fmt.Sprintf("%s/advancedConfiguration", endpoint) + + err = config.OVHClient.Put(advancedConfigEndpoint, acParams, nil) + if err != nil { + return fmt.Errorf("calling Put %s with params %v:\n\t %q", advancedConfigEndpoint, acParams, err) + } + } + log.Printf("[DEBUG] database %s is READY", d.Id()) return resourceCloudProjectDatabaseRead(d, meta) diff --git a/ovh/resource_cloud_project_database_m3db_user.go b/ovh/resource_cloud_project_database_m3db_user.go index 32871526e..e0f7d7194 100644 --- a/ovh/resource_cloud_project_database_m3db_user.go +++ b/ovh/resource_cloud_project_database_m3db_user.go @@ -4,7 +4,6 @@ import ( "fmt" "log" "net/url" - "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -80,43 +79,14 @@ func resourceCloudProjectDatabaseM3dbUser() *schema.Resource { } func resourceCloudProjectDatabaseM3dbUserImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - givenId := d.Id() - n := 3 - splitId := strings.SplitN(givenId, "/", n) - if len(splitId) != n { - return nil, fmt.Errorf("Import Id is not service_name/cluster_id/id formatted") - } - serviceName := splitId[0] - clusterId := splitId[1] - id := splitId[2] - d.SetId(id) - d.Set("cluster_id", clusterId) - d.Set("service_name", serviceName) - - results := make([]*schema.ResourceData, 1) - results[0] = d - return results, nil + return importCloudProjectDatabaseUser(d, meta) } func resourceCloudProjectDatabaseM3dbUserCreate(d *schema.ResourceData, meta interface{}) error { - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - - endpoint := fmt.Sprintf("/cloud/project/%s/database/m3db/%s/user", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - ) - params := (&CloudProjectDatabaseM3dbUserCreateOpts{}).FromResource(d) - res := &CloudProjectDatabaseUserResponse{} - - log.Printf("[DEBUG] Will create user: %+v for cluster %s from project %s", params, clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, "m3db", endpoint, params, res, schema.TimeoutCreate) - if err != nil { - return err + f := func() interface{} { + return (&CloudProjectDatabaseM3dbUserCreateOpts{}).FromResource(d) } - - d.SetId(res.Id) - return resourceCloudProjectDatabaseM3dbUserRead(d, meta) + return postCloudProjectDatabaseUser(d, meta, "m3db", dataSourceCloudProjectDatabaseM3dbUserRead, resourceCloudProjectDatabaseM3dbUserRead, resourceCloudProjectDatabaseM3dbUserUpdate, f) } func resourceCloudProjectDatabaseM3dbUserRead(d *schema.ResourceData, meta interface{}) error { @@ -150,71 +120,12 @@ func resourceCloudProjectDatabaseM3dbUserRead(d *schema.ResourceData, meta inter } func resourceCloudProjectDatabaseM3dbUserUpdate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - passwordReset := d.HasChange("password_reset") - id := d.Id() - - endpoint := fmt.Sprintf("/cloud/project/%s/database/m3db/%s/user/%s", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - url.PathEscape(id), - ) - params := (&CloudProjectDatabaseM3dbUserUpdateOpts{}).FromResource(d) - - log.Printf("[DEBUG] Will update user: %+v from cluster %s from project %s", params, clusterId, serviceName) - err := config.OVHClient.Put(endpoint, params, nil) - if err != nil { - return fmt.Errorf("calling Put %s with params %+v:\n\t %q", endpoint, params, err) - } - - log.Printf("[DEBUG] Waiting for user %s to be READY", id) - err = waitForCloudProjectDatabaseUserReady(config.OVHClient, serviceName, "m3db", clusterId, id, d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return fmt.Errorf("timeout while waiting user %s to be READY: %w", id, err) + f := func() interface{} { + return (&CloudProjectDatabaseM3dbUserUpdateOpts{}).FromResource(d) } - log.Printf("[DEBUG] user %s is READY", id) - - if passwordReset { - pwdResetEndpoint := endpoint + "/credentials/reset" - res := &CloudProjectDatabaseUserResponse{} - log.Printf("[DEBUG] Will update user password for cluster %s from project %s", clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, "m3db", pwdResetEndpoint, nil, res, schema.TimeoutUpdate) - if err != nil { - return err - } - } - - return resourceCloudProjectDatabaseM3dbUserRead(d, meta) + return updateCloudProjectDatabaseUser(d, meta, "m3db", resourceCloudProjectDatabaseM3dbUserRead, f) } func resourceCloudProjectDatabaseM3dbUserDelete(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - id := d.Id() - - endpoint := fmt.Sprintf("/cloud/project/%s/database/m3db/%s/user/%s", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - url.PathEscape(id), - ) - - log.Printf("[DEBUG] Will delete user %s from cluster %s from project %s", id, clusterId, serviceName) - err := config.OVHClient.Delete(endpoint, nil) - if err != nil { - return helpers.CheckDeleted(d, err, endpoint) - } - - log.Printf("[DEBUG] Waiting for user %s to be DELETED", id) - err = waitForCloudProjectDatabaseUserDeleted(config.OVHClient, serviceName, "m3db", clusterId, id, d.Timeout(schema.TimeoutDelete)) - if err != nil { - return fmt.Errorf("timeout while waiting user %s to be DELETED: %w", id, err) - } - log.Printf("[DEBUG] user %s is DELETED", id) - - d.SetId("") - - return nil + return deleteCloudProjectDatabaseUser(d, meta, "m3db") } diff --git a/ovh/resource_cloud_project_database_mongodb_user.go b/ovh/resource_cloud_project_database_mongodb_user.go index e05afa51d..930dfbda1 100644 --- a/ovh/resource_cloud_project_database_mongodb_user.go +++ b/ovh/resource_cloud_project_database_mongodb_user.go @@ -4,7 +4,6 @@ import ( "fmt" "log" "net/url" - "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -91,22 +90,7 @@ func resourceCloudProjectDatabaseMongodbUser() *schema.Resource { } func resourceCloudProjectDatabaseMongodbUserImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - givenId := d.Id() - n := 3 - splitId := strings.SplitN(givenId, "/", n) - if len(splitId) != n { - return nil, fmt.Errorf("Import Id is not service_name/cluster_id/id formatted") - } - serviceName := splitId[0] - clusterId := splitId[1] - id := splitId[2] - d.SetId(id) - d.Set("cluster_id", clusterId) - d.Set("service_name", serviceName) - - results := make([]*schema.ResourceData, 1) - results[0] = d - return results, nil + return importCloudProjectDatabaseUser(d, meta) } func resourceCloudProjectDatabaseMongodbUserCreate(d *schema.ResourceData, meta interface{}) error { @@ -122,7 +106,7 @@ func resourceCloudProjectDatabaseMongodbUserCreate(d *schema.ResourceData, meta return resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { log.Printf("[DEBUG] Will create user: %+v for cluster %s from project %s", params, clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, "mongodb", endpoint, params, res, schema.TimeoutCreate) + err := postFuncCloudProjectDatabaseUser(d, meta, "mongodb", endpoint, params, res, schema.TimeoutCreate) if err != nil { if errOvh, ok := err.(*ovh.APIError); ok && (errOvh.Code == 409) { return resource.RetryableError(err) @@ -204,7 +188,7 @@ func resourceCloudProjectDatabaseMongodbUserUpdate(d *schema.ResourceData, meta pwdResetEndpoint := endpoint + "/credentials/reset" res := &CloudProjectDatabaseUserResponse{} log.Printf("[DEBUG] Will update user password for cluster %s from project %s", clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, "mongodb", pwdResetEndpoint, nil, res, schema.TimeoutUpdate) + err := postFuncCloudProjectDatabaseUser(d, meta, "mongodb", pwdResetEndpoint, nil, res, schema.TimeoutUpdate) if err != nil { if errOvh, ok := err.(*ovh.APIError); ok && (errOvh.Code == 409) { return resource.RetryableError(err) diff --git a/ovh/resource_cloud_project_database_opensearch_user.go b/ovh/resource_cloud_project_database_opensearch_user.go index ec67b8a83..211a32638 100644 --- a/ovh/resource_cloud_project_database_opensearch_user.go +++ b/ovh/resource_cloud_project_database_opensearch_user.go @@ -4,7 +4,6 @@ import ( "fmt" "log" "net/url" - "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -94,43 +93,14 @@ func resourceCloudProjectDatabaseOpensearchUser() *schema.Resource { } func resourceCloudProjectDatabaseOpensearchUserImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - givenId := d.Id() - n := 3 - splitId := strings.SplitN(givenId, "/", n) - if len(splitId) != n { - return nil, fmt.Errorf("Import Id is not service_name/cluster_id/id formatted") - } - serviceName := splitId[0] - clusterId := splitId[1] - id := splitId[2] - d.SetId(id) - d.Set("cluster_id", clusterId) - d.Set("service_name", serviceName) - - results := make([]*schema.ResourceData, 1) - results[0] = d - return results, nil + return importCloudProjectDatabaseUser(d, meta) } func resourceCloudProjectDatabaseOpensearchUserCreate(d *schema.ResourceData, meta interface{}) error { - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - - endpoint := fmt.Sprintf("/cloud/project/%s/database/opensearch/%s/user", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - ) - params := (&CloudProjectDatabaseOpensearchUserCreateOpts{}).FromResource(d) - res := &CloudProjectDatabaseUserResponse{} - - log.Printf("[DEBUG] Will create user: %+v for cluster %s from project %s", params, clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, "opensearch", endpoint, params, res, schema.TimeoutCreate) - if err != nil { - return err + f := func() interface{} { + return (&CloudProjectDatabaseOpensearchUserCreateOpts{}).FromResource(d) } - - d.SetId(res.Id) - return resourceCloudProjectDatabaseOpensearchUserRead(d, meta) + return postCloudProjectDatabaseUser(d, meta, "opensearch", dataSourceCloudProjectDatabaseOpensearchUserRead, resourceCloudProjectDatabaseOpensearchUserRead, resourceCloudProjectDatabaseOpensearchUserUpdate, f) } func resourceCloudProjectDatabaseOpensearchUserRead(d *schema.ResourceData, meta interface{}) error { @@ -164,71 +134,12 @@ func resourceCloudProjectDatabaseOpensearchUserRead(d *schema.ResourceData, meta } func resourceCloudProjectDatabaseOpensearchUserUpdate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - passwordReset := d.HasChange("password_reset") - id := d.Id() - - endpoint := fmt.Sprintf("/cloud/project/%s/database/opensearch/%s/user/%s", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - url.PathEscape(id), - ) - params := (&CloudProjectDatabaseOpensearchUserUpdateOpts{}).FromResource(d) - - log.Printf("[DEBUG] Will update user: %+v from cluster %s from project %s", params, clusterId, serviceName) - err := config.OVHClient.Put(endpoint, params, nil) - if err != nil { - return fmt.Errorf("calling Put %s with params %+v:\n\t %q", endpoint, params, err) - } - - log.Printf("[DEBUG] Waiting for user %s to be READY", id) - err = waitForCloudProjectDatabaseUserReady(config.OVHClient, serviceName, "opensearch", clusterId, id, d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return fmt.Errorf("timeout while waiting user %s to be READY: %w", id, err) + f := func() interface{} { + return (&CloudProjectDatabaseOpensearchUserUpdateOpts{}).FromResource(d) } - log.Printf("[DEBUG] user %s is READY", id) - - if passwordReset { - pwdResetEndpoint := endpoint + "/credentials/reset" - res := &CloudProjectDatabaseUserResponse{} - log.Printf("[DEBUG] Will update user password for cluster %s from project %s", clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, "opensearch", pwdResetEndpoint, nil, res, schema.TimeoutUpdate) - if err != nil { - return err - } - } - - return resourceCloudProjectDatabaseOpensearchUserRead(d, meta) + return updateCloudProjectDatabaseUser(d, meta, "opensearch", resourceCloudProjectDatabaseOpensearchUserRead, f) } func resourceCloudProjectDatabaseOpensearchUserDelete(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - id := d.Id() - - endpoint := fmt.Sprintf("/cloud/project/%s/database/opensearch/%s/user/%s", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - url.PathEscape(id), - ) - - log.Printf("[DEBUG] Will delete user %s from cluster %s from project %s", id, clusterId, serviceName) - err := config.OVHClient.Delete(endpoint, nil) - if err != nil { - return helpers.CheckDeleted(d, err, endpoint) - } - - log.Printf("[DEBUG] Waiting for user %s to be DELETED", id) - err = waitForCloudProjectDatabaseUserDeleted(config.OVHClient, serviceName, "opensearch", clusterId, id, d.Timeout(schema.TimeoutDelete)) - if err != nil { - return fmt.Errorf("timeout while waiting user %s to be DELETED: %w", id, err) - } - log.Printf("[DEBUG] user %s is DELETED", id) - - d.SetId("") - - return nil + return deleteCloudProjectDatabaseUser(d, meta, "opensearch") } diff --git a/ovh/resource_cloud_project_database_postgresql_user.go b/ovh/resource_cloud_project_database_postgresql_user.go index 6611a5720..10c5a9773 100644 --- a/ovh/resource_cloud_project_database_postgresql_user.go +++ b/ovh/resource_cloud_project_database_postgresql_user.go @@ -4,7 +4,6 @@ import ( "fmt" "log" "net/url" - "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -51,6 +50,7 @@ func resourceCloudProjectDatabasePostgresqlUser() *schema.Resource { Type: schema.TypeSet, Description: "Roles the user belongs to", Optional: true, + Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, "password_reset": { @@ -81,43 +81,14 @@ func resourceCloudProjectDatabasePostgresqlUser() *schema.Resource { } func resourceCloudProjectDatabasePostgresqlUserImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - givenId := d.Id() - n := 3 - splitId := strings.SplitN(givenId, "/", n) - if len(splitId) != n { - return nil, fmt.Errorf("Import Id is not service_name/cluster_id/id formatted") - } - serviceName := splitId[0] - clusterId := splitId[1] - id := splitId[2] - d.SetId(id) - d.Set("cluster_id", clusterId) - d.Set("service_name", serviceName) - - results := make([]*schema.ResourceData, 1) - results[0] = d - return results, nil + return importCloudProjectDatabaseUser(d, meta) } func resourceCloudProjectDatabasePostgresqlUserCreate(d *schema.ResourceData, meta interface{}) error { - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - - endpoint := fmt.Sprintf("/cloud/project/%s/database/postgresql/%s/user", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - ) - params := (&CloudProjectDatabasePostgresqlUserCreateOpts{}).FromResource(d) - res := &CloudProjectDatabaseUserResponse{} - - log.Printf("[DEBUG] Will create user: %+v for cluster %s from project %s", params, clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, "postgresql", endpoint, params, res, schema.TimeoutCreate) - if err != nil { - return err + f := func() interface{} { + return (&CloudProjectDatabasePostgresqlUserCreateOpts{}).FromResource(d) } - - d.SetId(res.Id) - return resourceCloudProjectDatabasePostgresqlUserRead(d, meta) + return postCloudProjectDatabaseUser(d, meta, "postgresql", dataSourceCloudProjectDatabasePostgresqlUserRead, resourceCloudProjectDatabasePostgresqlUserRead, resourceCloudProjectDatabasePostgresqlUserUpdate, f) } func resourceCloudProjectDatabasePostgresqlUserRead(d *schema.ResourceData, meta interface{}) error { @@ -151,71 +122,12 @@ func resourceCloudProjectDatabasePostgresqlUserRead(d *schema.ResourceData, meta } func resourceCloudProjectDatabasePostgresqlUserUpdate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - passwordReset := d.HasChange("password_reset") - id := d.Id() - - endpoint := fmt.Sprintf("/cloud/project/%s/database/postgresql/%s/user/%s", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - url.PathEscape(id), - ) - params := (&CloudProjectDatabasePostgresqlUserUpdateOpts{}).FromResource(d) - - log.Printf("[DEBUG] Will update user: %+v from cluster %s from project %s", params, clusterId, serviceName) - err := config.OVHClient.Put(endpoint, params, nil) - if err != nil { - return fmt.Errorf("calling Put %s with params %+v:\n\t %q", endpoint, params, err) - } - - log.Printf("[DEBUG] Waiting for user %s to be READY", id) - err = waitForCloudProjectDatabaseUserReady(config.OVHClient, serviceName, "postgresql", clusterId, id, d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return fmt.Errorf("timeout while waiting user %s to be READY: %w", id, err) - } - log.Printf("[DEBUG] user %s is READY", id) - - if passwordReset { - pwdResetEndpoint := endpoint + "/credentials/reset" - res := &CloudProjectDatabaseUserResponse{} - log.Printf("[DEBUG] Will update user password for cluster %s from project %s", clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, "postgresql", pwdResetEndpoint, nil, res, schema.TimeoutUpdate) - if err != nil { - return err - } + f := func() interface{} { + return (&CloudProjectDatabasePostgresqlUserUpdateOpts{}).FromResource(d) } - - return resourceCloudProjectDatabasePostgresqlUserRead(d, meta) + return updateCloudProjectDatabaseUser(d, meta, "postgresql", resourceCloudProjectDatabasePostgresqlUserRead, f) } func resourceCloudProjectDatabasePostgresqlUserDelete(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - id := d.Id() - - endpoint := fmt.Sprintf("/cloud/project/%s/database/postgresql/%s/user/%s", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - url.PathEscape(id), - ) - - log.Printf("[DEBUG] Will delete user %s from cluster %s from project %s", id, clusterId, serviceName) - err := config.OVHClient.Delete(endpoint, nil) - if err != nil { - return helpers.CheckDeleted(d, err, endpoint) - } - - log.Printf("[DEBUG] Waiting for user %s to be DELETED", id) - err = waitForCloudProjectDatabaseUserDeleted(config.OVHClient, serviceName, "postgresql", clusterId, id, d.Timeout(schema.TimeoutDelete)) - if err != nil { - return fmt.Errorf("timeout while waiting user %s to be DELETED: %w", id, err) - } - log.Printf("[DEBUG] user %s is DELETED", id) - - d.SetId("") - - return nil + return deleteCloudProjectDatabaseUser(d, meta, "postgresql") } diff --git a/ovh/resource_cloud_project_database_redis_user.go b/ovh/resource_cloud_project_database_redis_user.go index 91644c5ee..1c3ed02e5 100644 --- a/ovh/resource_cloud_project_database_redis_user.go +++ b/ovh/resource_cloud_project_database_redis_user.go @@ -4,7 +4,6 @@ import ( "fmt" "log" "net/url" - "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -103,43 +102,14 @@ func resourceCloudProjectDatabaseRedisUser() *schema.Resource { } func resourceCloudProjectDatabaseRedisUserImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - givenId := d.Id() - n := 3 - splitId := strings.SplitN(givenId, "/", n) - if len(splitId) != n { - return nil, fmt.Errorf("Import Id is not service_name/cluster_id/id formatted") - } - serviceName := splitId[0] - clusterId := splitId[1] - id := splitId[2] - d.SetId(id) - d.Set("cluster_id", clusterId) - d.Set("service_name", serviceName) - - results := make([]*schema.ResourceData, 1) - results[0] = d - return results, nil + return importCloudProjectDatabaseUser(d, meta) } func resourceCloudProjectDatabaseRedisUserCreate(d *schema.ResourceData, meta interface{}) error { - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - - endpoint := fmt.Sprintf("/cloud/project/%s/database/redis/%s/user", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - ) - params := (&CloudProjectDatabaseRedisUserCreateOpts{}).FromResource(d) - res := &CloudProjectDatabaseUserResponse{} - - log.Printf("[DEBUG] Will create user: %+v for cluster %s from project %s", params, clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, "redis", endpoint, params, res, schema.TimeoutCreate) - if err != nil { - return err + f := func() interface{} { + return (&CloudProjectDatabaseRedisUserCreateOpts{}).FromResource(d) } - - d.SetId(res.Id) - return resourceCloudProjectDatabaseRedisUserRead(d, meta) + return postCloudProjectDatabaseUser(d, meta, "redis", dataSourceCloudProjectDatabaseRedisUserRead, resourceCloudProjectDatabaseRedisUserRead, resourceCloudProjectDatabaseRedisUserUpdate, f) } func resourceCloudProjectDatabaseRedisUserRead(d *schema.ResourceData, meta interface{}) error { @@ -173,72 +143,12 @@ func resourceCloudProjectDatabaseRedisUserRead(d *schema.ResourceData, meta inte } func resourceCloudProjectDatabaseRedisUserUpdate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - passwordReset := d.HasChange("password_reset") - id := d.Id() - - endpoint := fmt.Sprintf("/cloud/project/%s/database/redis/%s/user/%s", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - url.PathEscape(id), - ) - params := (&CloudProjectDatabaseRedisUserUpdateOpts{}).FromResource(d) - - log.Printf("[DEBUG] Will update user: %+v from cluster %s from project %s", params, clusterId, serviceName) - err := config.OVHClient.Put(endpoint, params, nil) - if err != nil { - return fmt.Errorf("calling Put %s with params %+v:\n\t %q", endpoint, params, err) + f := func() interface{} { + return (&CloudProjectDatabaseRedisUserUpdateOpts{}).FromResource(d) } - - log.Printf("[DEBUG] Waiting for user %s to be READY", id) - err = waitForCloudProjectDatabaseUserReady(config.OVHClient, serviceName, "redis", clusterId, id, d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return fmt.Errorf("timeout while waiting user %s to be READY: %w", id, err) - } - log.Printf("[DEBUG] user %s is READY", id) - - if passwordReset { - pwdResetEndpoint := endpoint + "/credentials/reset" - res := &CloudProjectDatabaseUserResponse{} - - log.Printf("[DEBUG] Will update user password for cluster %s from project %s", clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, "redis", pwdResetEndpoint, nil, res, schema.TimeoutUpdate) - if err != nil { - return err - } - } - - return resourceCloudProjectDatabaseRedisUserRead(d, meta) + return updateCloudProjectDatabaseUser(d, meta, "redis", resourceCloudProjectDatabaseRedisUserRead, f) } func resourceCloudProjectDatabaseRedisUserDelete(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - serviceName := d.Get("service_name").(string) - clusterId := d.Get("cluster_id").(string) - id := d.Id() - - endpoint := fmt.Sprintf("/cloud/project/%s/database/redis/%s/user/%s", - url.PathEscape(serviceName), - url.PathEscape(clusterId), - url.PathEscape(id), - ) - - log.Printf("[DEBUG] Will delete user %s from cluster %s from project %s", id, clusterId, serviceName) - err := config.OVHClient.Delete(endpoint, nil) - if err != nil { - return helpers.CheckDeleted(d, err, endpoint) - } - - log.Printf("[DEBUG] Waiting for user %s to be DELETED", id) - err = waitForCloudProjectDatabaseUserDeleted(config.OVHClient, serviceName, "redis", clusterId, id, d.Timeout(schema.TimeoutDelete)) - if err != nil { - return fmt.Errorf("timeout while waiting user %s to be DELETED: %w", id, err) - } - log.Printf("[DEBUG] user %s is DELETED", id) - - d.SetId("") - - return nil + return deleteCloudProjectDatabaseUser(d, meta, "redis") } diff --git a/ovh/resource_cloud_project_database_user.go b/ovh/resource_cloud_project_database_user.go index bed1b2e9a..93b8417be 100644 --- a/ovh/resource_cloud_project_database_user.go +++ b/ovh/resource_cloud_project_database_user.go @@ -103,27 +103,11 @@ func resourceCloudProjectDatabaseUserImportState(d *schema.ResourceData, meta in } func resourceCloudProjectDatabaseUserCreate(d *schema.ResourceData, meta interface{}) error { - serviceName := d.Get("service_name").(string) engine := d.Get("engine").(string) - clusterId := d.Get("cluster_id").(string) - - endpoint := fmt.Sprintf("/cloud/project/%s/database/%s/%s/user", - url.PathEscape(serviceName), - url.PathEscape(engine), - url.PathEscape(clusterId), - ) - - params := (&CloudProjectDatabaseUserCreateOpts{}).FromResource(d) - res := &CloudProjectDatabaseUserResponse{} - - log.Printf("[DEBUG] Will create user: %+v for cluster %s from project %s", params, clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, engine, endpoint, params, res, schema.TimeoutCreate) - if err != nil { - return err + f := func() interface{} { + return (&CloudProjectDatabaseUserCreateOpts{}).FromResource(d) } - - d.SetId(res.Id) - return resourceCloudProjectDatabaseUserRead(d, meta) + return postCloudProjectDatabaseUser(d, meta, engine, dataSourceCloudProjectDatabaseUserRead, resourceCloudProjectDatabaseUserRead, resourceCloudProjectDatabaseUserUpdate, f) } func resourceCloudProjectDatabaseUserRead(d *schema.ResourceData, meta interface{}) error { @@ -164,49 +148,23 @@ func resourceCloudProjectDatabaseUserUpdate(d *schema.ResourceData, meta interfa clusterId := d.Get("cluster_id").(string) id := d.Id() - endpoint := fmt.Sprintf("/cloud/project/%s/database/postgresql/%s/user/%s/credentials/reset", + endpoint := fmt.Sprintf("/cloud/project/%s/database/%s/%s/user/%s/credentials/reset", url.PathEscape(serviceName), + url.PathEscape(engine), url.PathEscape(clusterId), url.PathEscape(id), ) res := &CloudProjectDatabaseUserResponse{} log.Printf("[DEBUG] Will update user password for cluster %s from project %s", clusterId, serviceName) - err := postCloudProjectDatabaseUser(d, meta, engine, endpoint, nil, res, schema.TimeoutUpdate) + err := postFuncCloudProjectDatabaseUser(d, meta, engine, endpoint, nil, res, schema.TimeoutUpdate) if err != nil { return err } - return resourceCloudProjectDatabasePostgresqlUserRead(d, meta) + return resourceCloudProjectDatabaseUserRead(d, meta) } func resourceCloudProjectDatabaseUserDelete(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - serviceName := d.Get("service_name").(string) engine := d.Get("engine").(string) - clusterId := d.Get("cluster_id").(string) - id := d.Id() - - endpoint := fmt.Sprintf("/cloud/project/%s/database/%s/%s/user/%s", - url.PathEscape(serviceName), - url.PathEscape(engine), - url.PathEscape(clusterId), - url.PathEscape(id), - ) - - log.Printf("[DEBUG] Will delete user %s from cluster %s from project %s", id, clusterId, serviceName) - err := config.OVHClient.Delete(endpoint, nil) - if err != nil { - return helpers.CheckDeleted(d, err, endpoint) - } - - log.Printf("[DEBUG] Waiting for user %s to be DELETED", id) - err = waitForCloudProjectDatabaseUserDeleted(config.OVHClient, serviceName, engine, clusterId, id, d.Timeout(schema.TimeoutDelete)) - if err != nil { - return fmt.Errorf("timeout while waiting user %s to be DELETED: %w", id, err) - } - log.Printf("[DEBUG] user %s is DELETED", id) - - d.SetId("") - - return nil + return deleteCloudProjectDatabaseUser(d, meta, engine) } diff --git a/ovh/types_cloud_project_database.go b/ovh/types_cloud_project_database.go index 805b166a7..1ff44b031 100644 --- a/ovh/types_cloud_project_database.go +++ b/ovh/types_cloud_project_database.go @@ -11,28 +11,30 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/ovh/go-ovh/ovh" + "github.com/ovh/terraform-provider-ovh/ovh/helpers" "github.com/ybriffa/rfc3339" ) type CloudProjectDatabaseResponse struct { - AclsEnabled bool `json:"aclsEnabled"` - BackupTime string `json:"backupTime"` - CreatedAt string `json:"createdAt"` - Description string `json:"description"` - Endpoints []CloudProjectDatabaseEndpoint `json:"endpoints"` - Flavor string `json:"flavor"` - Id string `json:"id"` - MaintenanceTime string `json:"maintenanceTime"` - NetworkId string `json:"networkId"` - NetworkType string `json:"networkType"` - Plan string `json:"plan"` - NodeNumber int `json:"nodeNumber"` - Region string `json:"region"` - RestApi bool `json:"restApi"` - Status string `json:"status"` - SubnetId string `json:"subnetId"` - Version string `json:"version"` - Disk CloudProjectDatabaseDisk `json:"disk"` + AclsEnabled bool `json:"aclsEnabled"` + BackupTime string `json:"backupTime"` + CreatedAt string `json:"createdAt"` + Description string `json:"description"` + Endpoints []CloudProjectDatabaseEndpoint `json:"endpoints"` + Flavor string `json:"flavor"` + Id string `json:"id"` + MaintenanceTime string `json:"maintenanceTime"` + NetworkId string `json:"networkId"` + NetworkType string `json:"networkType"` + Plan string `json:"plan"` + NodeNumber int `json:"nodeNumber"` + Region string `json:"region"` + RestApi bool `json:"restApi"` + Status string `json:"status"` + SubnetId string `json:"subnetId"` + Version string `json:"version"` + Disk CloudProjectDatabaseDisk `json:"disk"` + AdvancedConfiguration map[string]string `json:"advancedConfiguration"` } func (s *CloudProjectDatabaseResponse) String() string { @@ -74,6 +76,7 @@ func (v CloudProjectDatabaseResponse) ToMap() map[string]interface{} { obj["version"] = v.Version obj["disk_size"] = v.Disk.Size obj["disk_type"] = v.Disk.Type + obj["advanced_configuration"] = v.AdvancedConfiguration return obj } @@ -538,7 +541,59 @@ func (opts *CloudProjectDatabaseUserCreateOpts) FromResource(d *schema.ResourceD return opts } -func postCloudProjectDatabaseUser(d *schema.ResourceData, meta interface{}, engine string, endpoint string, params interface{}, res *CloudProjectDatabaseUserResponse, timeout string) error { +func importCloudProjectDatabaseUser(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + givenId := d.Id() + n := 3 + splitId := strings.SplitN(givenId, "/", n) + if len(splitId) != n { + return nil, fmt.Errorf("Import Id is not service_name/cluster_id/id formatted") + } + serviceName := splitId[0] + clusterId := splitId[1] + id := splitId[2] + d.SetId(id) + d.Set("cluster_id", clusterId) + d.Set("service_name", serviceName) + + results := make([]*schema.ResourceData, 1) + results[0] = d + return results, nil +} + +func postCloudProjectDatabaseUser(d *schema.ResourceData, meta interface{}, engine string, dsReadFunc, readFunc schema.ReadFunc, updateFunc schema.UpdateFunc, f func() interface{}) error { + name := d.Get("name").(string) + if name == "avnadmin" && engine != "redis" { + err := dsReadFunc(d, meta) + if err != nil { + return err + } + return updateFunc(d, meta) + } + + serviceName := d.Get("service_name").(string) + clusterId := d.Get("cluster_id").(string) + + endpoint := fmt.Sprintf("/cloud/project/%s/database/%s/%s/user", + url.PathEscape(serviceName), + url.PathEscape(engine), + url.PathEscape(clusterId), + ) + + params := f() + res := &CloudProjectDatabaseUserResponse{} + + log.Printf("[DEBUG] Will create user: %+v for cluster %s from project %s", params, clusterId, serviceName) + err := postFuncCloudProjectDatabaseUser(d, meta, engine, endpoint, params, res, schema.TimeoutCreate) + if err != nil { + return err + } + + d.SetId(res.Id) + return readFunc(d, meta) + +} + +func postFuncCloudProjectDatabaseUser(d *schema.ResourceData, meta interface{}, engine string, endpoint string, params interface{}, res *CloudProjectDatabaseUserResponse, timeout string) error { config := meta.(*Config) serviceName := d.Get("service_name").(string) clusterId := d.Get("cluster_id").(string) @@ -561,6 +616,89 @@ func postCloudProjectDatabaseUser(d *schema.ResourceData, meta interface{}, engi return nil } +func updateCloudProjectDatabaseUser(d *schema.ResourceData, meta interface{}, engine string, readFunc schema.ReadFunc, f func() interface{}) error { + config := meta.(*Config) + serviceName := d.Get("service_name").(string) + clusterId := d.Get("cluster_id").(string) + isAvnAdmin := d.Get("name").(string) == "avnadmin" + // The M3DB condition must be remove when avnadmin password reset will be possible on this engine + passwordReset := d.HasChange("password_reset") || (d.IsNewResource() && isAvnAdmin && engine != "m3db") + id := d.Id() + + endpoint := fmt.Sprintf("/cloud/project/%s/database/%s/%s/user/%s", + url.PathEscape(serviceName), + url.PathEscape(engine), + url.PathEscape(clusterId), + url.PathEscape(id), + ) + + if !(isAvnAdmin && engine == "postgresql") { + params := f() + + log.Printf("[DEBUG] Will update user: %+v from cluster %s from project %s", params, clusterId, serviceName) + err := config.OVHClient.Put(endpoint, params, nil) + if err != nil { + return fmt.Errorf("calling Put %s with params %+v:\n\t %q", endpoint, params, err) + } + + log.Printf("[DEBUG] Waiting for user %s to be READY", id) + err = waitForCloudProjectDatabaseUserReady(config.OVHClient, serviceName, engine, clusterId, id, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return fmt.Errorf("timeout while waiting user %s to be READY: %w", id, err) + } + log.Printf("[DEBUG] user %s is READY", id) + } + + if passwordReset { + pwdResetEndpoint := endpoint + "/credentials/reset" + res := &CloudProjectDatabaseUserResponse{} + log.Printf("[DEBUG] Will update user password for cluster %s from project %s", clusterId, serviceName) + err := postFuncCloudProjectDatabaseUser(d, meta, engine, pwdResetEndpoint, nil, res, schema.TimeoutUpdate) + if err != nil { + return err + } + } + + return readFunc(d, meta) +} + +func deleteCloudProjectDatabaseUser(d *schema.ResourceData, meta interface{}, engine string) error { + name := d.Get("name").(string) + if name == "avnadmin" && engine != "redis" { + d.SetId("") + return nil + } + + config := meta.(*Config) + serviceName := d.Get("service_name").(string) + clusterId := d.Get("cluster_id").(string) + id := d.Id() + + endpoint := fmt.Sprintf("/cloud/project/%s/database/%s/%s/user/%s", + url.PathEscape(serviceName), + url.PathEscape(engine), + url.PathEscape(clusterId), + url.PathEscape(id), + ) + + log.Printf("[DEBUG] Will delete user %s from cluster %s from project %s", id, clusterId, serviceName) + err := config.OVHClient.Delete(endpoint, nil) + if err != nil { + return helpers.CheckDeleted(d, err, endpoint) + } + + log.Printf("[DEBUG] Waiting for user %s to be DELETED", id) + err = waitForCloudProjectDatabaseUserDeleted(config.OVHClient, serviceName, engine, clusterId, id, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return fmt.Errorf("timeout while waiting user %s to be DELETED: %w", id, err) + } + log.Printf("[DEBUG] user %s is DELETED", id) + + d.SetId("") + + return nil +} + func waitForCloudProjectDatabaseUserReady(client *ovh.Client, serviceName, engine string, databaseId string, userId string, timeOut time.Duration) error { stateConf := &resource.StateChangeConf{ Pending: []string{"PENDING", "CREATING", "UPDATING"}, diff --git a/website/docs/d/cloud_project_database.html.markdown b/website/docs/d/cloud_project_database.html.markdown index 74a7a4e76..65af7ff4a 100644 --- a/website/docs/d/cloud_project_database.html.markdown +++ b/website/docs/d/cloud_project_database.html.markdown @@ -70,3 +70,4 @@ The following attributes are exported: * `version` - The version of the engine in which the service should be deployed * `disk_size` - The disk size (in GB) of the database service. * `disk_type` - The disk type of the database service. +* `advanced_configuration` - Advanced configuration key / value. diff --git a/website/docs/d/cloud_project_database_users.html.markdown b/website/docs/d/cloud_project_database_users.html.markdown index 6e7531767..a1ec29b27 100644 --- a/website/docs/d/cloud_project_database_users.html.markdown +++ b/website/docs/d/cloud_project_database_users.html.markdown @@ -31,11 +31,6 @@ output "user_ids" { * `engine` - (Required) The engine of the database cluster you want to list users. To get a full list of available engine visit: [public documentation](https://docs.ovh.com/gb/en/publiccloud/databases). -Available engines: - * `cassandra` - * `kafka` - * `kafkaConnect` - * `mysql` * `cluster_id` - (Required) Cluster ID diff --git a/website/docs/r/cloud_project_database.html.markdown b/website/docs/r/cloud_project_database.html.markdown index 92ff239f1..497ffce22 100644 --- a/website/docs/r/cloud_project_database.html.markdown +++ b/website/docs/r/cloud_project_database.html.markdown @@ -94,6 +94,10 @@ resource "ovh_cloud_project_database" "mysqldb" { region = "SBG" } flavor = "db1-4" + advanced_configuration = { + "mysql.sql_mode": "ANSI,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,STRICT_ALL_TABLES", + "mysql.sql_require_primary_key": "true" + } } resource "ovh_cloud_project_database" "opensearchdb" { @@ -209,6 +213,8 @@ The following arguments are supported: * `disk_size` - (Optional) The disk size (in GB) of the database service. +* `advanced_configuration` - (Optional) Advanced configuration key / value. + * `plan` - (Required) Plan of the cluster. Enum: "essential", "business", "enterprise". @@ -247,6 +253,9 @@ The following attributes are exported: * `version` - See Argument Reference above. * `disk_size` - See Argument Reference above. * `disk_type` - Defines the disk type of the database service. +* `advanced_configuration` - Advanced configuration key / value. + + ## Timeouts diff --git a/website/docs/r/cloud_project_database_m3db_user.html.markdown b/website/docs/r/cloud_project_database_m3db_user.html.markdown index 2b79bb312..cf5d38691 100644 --- a/website/docs/r/cloud_project_database_m3db_user.html.markdown +++ b/website/docs/r/cloud_project_database_m3db_user.html.markdown @@ -69,7 +69,7 @@ The following arguments are supported: * `group` - (Optional) Group of the user: -* `name` - (Required, Forces new resource) Name of the user. +* `name` - (Required, Forces new resource) Name of the user. A user named "avnadmin" is map with already created admin user instead of create a new user. * `password_reset` - (Optional) Arbitrary string to change to trigger a password update. Use the `terraform refresh` command after executing `terraform apply` to update the output with the new password. diff --git a/website/docs/r/cloud_project_database_opensearch_user.html.markdown b/website/docs/r/cloud_project_database_opensearch_user.html.markdown index 4ddecb8d2..3073e85ec 100644 --- a/website/docs/r/cloud_project_database_opensearch_user.html.markdown +++ b/website/docs/r/cloud_project_database_opensearch_user.html.markdown @@ -90,7 +90,7 @@ The following arguments are supported: * `readwrite` * `deny` -* `name` - (Required, Forces new resource) Username affected by this acl. +* `name` - (Required, Forces new resource) Username affected by this acl. A user named "avnadmin" is map with already created admin user and reset his password instead of create a new user. * `password_reset` - (Optional) Arbitrary string to change to trigger a password update. Use the `terraform refresh` command after executing `terraform apply` to update the output with the new password. diff --git a/website/docs/r/cloud_project_database_postgresql_user.html.markdown b/website/docs/r/cloud_project_database_postgresql_user.html.markdown index 19229620f..5ce0f7dd5 100644 --- a/website/docs/r/cloud_project_database_postgresql_user.html.markdown +++ b/website/docs/r/cloud_project_database_postgresql_user.html.markdown @@ -66,7 +66,7 @@ The following arguments are supported: * `cluster_id` - (Required, Forces new resource) Cluster ID. -* `name` - (Required, Forces new resource) Name of the user. +* `name` - (Required, Forces new resource) Name of the user. A user named "avnadmin" is map with already created admin user and reset his password instead of create a new user. * `roles` - (Optional: if omit, default role) Roles the user belongs to. Available roles: diff --git a/website/docs/r/cloud_project_database_redis_user.html.markdown b/website/docs/r/cloud_project_database_redis_user.html.markdown index 6c9b4792f..a001f0240 100644 --- a/website/docs/r/cloud_project_database_redis_user.html.markdown +++ b/website/docs/r/cloud_project_database_redis_user.html.markdown @@ -80,7 +80,7 @@ The following arguments are supported: * `keys` - (Optional) Keys of the user. -* `name` - (Required, Forces new resource) Name of the user. +* `name` - (Required, Forces new resource) Name of the user. A user named "avnadmin" is map with already created admin user and reset his password instead of create a new user. * `password_reset` - (Optional) Arbitrary string to change to trigger a password update. Use the `terraform refresh` command after executing `terraform apply` to update the output with the new password. diff --git a/website/docs/r/cloud_project_database_user.html.markdown b/website/docs/r/cloud_project_database_user.html.markdown index c4b5e5ea3..f5a8f41c6 100644 --- a/website/docs/r/cloud_project_database_user.html.markdown +++ b/website/docs/r/cloud_project_database_user.html.markdown @@ -80,7 +80,7 @@ Available engines: * `cluster_id` - (Required, Forces new resource) Cluster ID. -* `name` - (Required, Forces new resource) Name of the user. +* `name` - (Required, Forces new resource) Name of the user. A user named "avnadmin" is map with already created admin user and reset his password instead of create a new user. * `password_reset` - (Optional) Arbitrary string to change to trigger a password update. Use the `terraform refresh` command after executing `terraform apply` to update the output with the new password.