From 974ffdbc3ae6887f1efb1df795809e5e5501ff8a Mon Sep 17 00:00:00 2001 From: Andrea Quintino Date: Tue, 31 Oct 2023 08:50:12 +0100 Subject: [PATCH 01/17] wip - added postgre-sql-settings --- internal/service/dms/endpoint.go | 76 ++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/internal/service/dms/endpoint.go b/internal/service/dms/endpoint.go index c79a0a76656..38da2b9addc 100644 --- a/internal/service/dms/endpoint.go +++ b/internal/service/dms/endpoint.go @@ -348,6 +348,82 @@ func ResourceEndpoint() *schema.Resource { Optional: true, ConflictsWith: []string{"secrets_manager_access_role_arn", "secrets_manager_arn"}, }, + "postgres_settings": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + DiffSuppressFunc: verify.SuppressMissingOptionalConfigurationBlock, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "after_connect_script": { + Type: schema.TypeString, + Optional: true, + }, + "capture_ddls": { + Type: schema.TypeBool, + Optional: true, + }, + "max_file_size": { + Type: schema.TypeInt, + Optional: true, + //Default: encryptionModeSseS3, + //ValidateFunc: validation.StringInSlice(encryptionMode_Values(), false), + }, + "ddl_artifacts_schema": { + Type: schema.TypeString, + Optional: true, + //DiffSuppressFunc: tfkms.DiffSuppressKey, + //ValidateFunc: tfkms.ValidateKey, + }, + "execute_timeout": { + Type: schema.TypeInt, + Optional: true, + // ValidateFunc: verify.ValidARN, + }, + "fail_tasks_on_lob_truncation": { + Type: schema.TypeBool, + Optional: true, + // ValidateFunc: verify.ValidARN, + }, + "heartbeat_enable": { + Type: schema.TypeBool, + Optional: true, + // ValidateFunc: verify.ValidARN, + }, + "heartbeat_schema": { + Type: schema.TypeString, + Optional: true, + // ValidateFunc: verify.ValidARN, + }, + "heartbeat_frequency": { + Type: schema.TypeInt, + Optional: true, + // ValidateFunc: verify.ValidARN, + }, + "slot_name": { + Type: schema.TypeString, + Optional: true, + // ValidateFunc: verify.ValidARN, + }, + "plugin_name": { // add validation function + Type: schema.TypeString, + Optional: true, + // ValidateFunc: verify.ValidARN, + }, + "trim_space_in_char": { + Type: schema.TypeBool, + Optional: true, + // ValidateFunc: verify.ValidARN, + }, + "map_boolean_as_boolean": { + Type: schema.TypeBool, + Optional: true, + // ValidateFunc: verify.ValidARN, + }, + }, + }, + }, "redis_settings": { Type: schema.TypeList, Optional: true, From 50ec6c3f7c6bc3b00dbd1caa01a5dacdbaff5e19 Mon Sep 17 00:00:00 2001 From: Andrea Quintino Date: Sat, 25 Nov 2023 15:32:50 +0100 Subject: [PATCH 02/17] wip - little changes --- internal/service/dms/endpoint.go | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/internal/service/dms/endpoint.go b/internal/service/dms/endpoint.go index 38da2b9addc..3523cc232d1 100644 --- a/internal/service/dms/endpoint.go +++ b/internal/service/dms/endpoint.go @@ -828,24 +828,22 @@ func resourceEndpointCreate(ctx context.Context, d *schema.ResourceData, meta in expandTopLevelConnectionInfo(d, input) } case engineNameAuroraPostgresql, engineNamePostgres: + postgres_settings := expandPostgreSQLSettings() if _, ok := d.GetOk("secrets_manager_arn"); ok { - input.PostgreSQLSettings = &dms.PostgreSQLSettings{ - SecretsManagerAccessRoleArn: aws.String(d.Get("secrets_manager_access_role_arn").(string)), - SecretsManagerSecretId: aws.String(d.Get("secrets_manager_arn").(string)), - DatabaseName: aws.String(d.Get("database_name").(string)), - } + postgres_settings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string)) + postgres_settings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string)) + postgres_settings.DatabaseName = aws.String(d.Get("database_name").(string)) } else { - input.PostgreSQLSettings = &dms.PostgreSQLSettings{ - Username: aws.String(d.Get("username").(string)), - Password: aws.String(d.Get("password").(string)), - ServerName: aws.String(d.Get("server_name").(string)), - Port: aws.Int64(int64(d.Get("port").(int))), - DatabaseName: aws.String(d.Get("database_name").(string)), - } + postgres_settings.Username = aws.String(d.Get("username").(string)) + postgres_settings.Password = aws.String(d.Get("password").(string)) + postgres_settings.ServerName = aws.String(d.Get("server_name").(string)) + postgres_settings.Port = aws.Int64(int64(d.Get("port").(int))) + postgres_settings.DatabaseName = aws.String(d.Get("database_name").(string)) // Set connection info in top-level namespace as well expandTopLevelConnectionInfo(d, input) } + input.PostgreSQLSettings = postgres_settings case engineNameDynamoDB: input.DynamoDbSettings = &dms.DynamoDbSettings{ ServiceAccessRoleArn: aws.String(d.Get("service_access_role").(string)), @@ -2140,6 +2138,12 @@ func flattenRedshiftSettings(settings *dms.RedshiftSettings) []map[string]interf return []map[string]interface{}{m} } +func expandPostgreSQLSettings() *dms.PostgreSQLSettings { + settings := &dms.PostgreSQLSettings{} + + return settings +} + func expandS3Settings(tfMap map[string]interface{}) *dms.S3Settings { if tfMap == nil { return nil From 5fd667c357a93b1c57607b5b76a72d0d6fbbea58 Mon Sep 17 00:00:00 2001 From: Andrea Quintino Date: Sat, 25 Nov 2023 17:24:46 +0100 Subject: [PATCH 03/17] added postgres_settings support --- internal/service/dms/endpoint.go | 48 ++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/internal/service/dms/endpoint.go b/internal/service/dms/endpoint.go index 3523cc232d1..7aeeb341bc0 100644 --- a/internal/service/dms/endpoint.go +++ b/internal/service/dms/endpoint.go @@ -828,7 +828,11 @@ func resourceEndpointCreate(ctx context.Context, d *schema.ResourceData, meta in expandTopLevelConnectionInfo(d, input) } case engineNameAuroraPostgresql, engineNamePostgres: - postgres_settings := expandPostgreSQLSettings() + postgres_settings := &dms.PostgreSQLSettings{} + if _, ok := d.GetOk("postgres_settings"); ok { + postgres_settings = expandPostgreSQLSettings(d.Get("postgres_settings").([]interface{})[0].(map[string]interface{})) + } + if _, ok := d.GetOk("secrets_manager_arn"); ok { postgres_settings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string)) postgres_settings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string)) @@ -2138,9 +2142,49 @@ func flattenRedshiftSettings(settings *dms.RedshiftSettings) []map[string]interf return []map[string]interface{}{m} } -func expandPostgreSQLSettings() *dms.PostgreSQLSettings { +func expandPostgreSQLSettings(tfMap map[string]interface{}) *dms.PostgreSQLSettings { settings := &dms.PostgreSQLSettings{} + if v, ok := tfMap["after_connect_script"].(string); ok && v != "" { + settings.AfterConnectScript = aws.String(v) + } + if v, ok := tfMap["capture_ddls"].(bool); ok { + settings.CaptureDdls = aws.Bool(v) + } + if v, ok := tfMap["max_file_size"].(int); ok { + settings.MaxFileSize = aws.Int64(int64(v)) + } + if v, ok := tfMap["ddl_artifacts_schema"].(string); ok && v != "" { + settings.DdlArtifactsSchema = aws.String(v) + } + if v, ok := tfMap["execute_timeout"].(int); ok { + settings.ExecuteTimeout = aws.Int64(int64(v)) + } + if v, ok := tfMap["fail_tasks_on_lob_truncation"].(bool); ok { + settings.FailTasksOnLobTruncation = aws.Bool(v) + } + if v, ok := tfMap["heartbeat_enable"].(bool); ok { + settings.HeartbeatEnable = aws.Bool(v) + } + if v, ok := tfMap["heartbeat_schema"].(string); ok && v != "" { + settings.HeartbeatSchema = aws.String(v) + } + if v, ok := tfMap["heartbeat_frequency"].(int); ok { + settings.HeartbeatFrequency = aws.Int64(int64(v)) + } + if v, ok := tfMap["slot_name"].(string); ok && v != "" { + settings.SlotName = aws.String(v) + } + if v, ok := tfMap["plugin_name"].(string); ok && v != "" { + settings.PluginName = aws.String(v) + } + if v, ok := tfMap["trim_space_in_char"].(bool); ok { + settings.TrimSpaceInChar = aws.Bool(v) + } + if v, ok := tfMap["map_boolean_as_boolean"].(bool); ok { + settings.MapBooleanAsBoolean = aws.Bool(v) + } + return settings } From 4be6318c9e5e6cad9aae1c18d44ec5c5bc42f203 Mon Sep 17 00:00:00 2001 From: Andrea Quintino Date: Mon, 27 Nov 2023 16:42:28 +0100 Subject: [PATCH 04/17] test passed. waiting missing ones --- internal/service/dms/endpoint.go | 16 +-------- internal/service/dms/endpoint_test.go | 49 +++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/internal/service/dms/endpoint.go b/internal/service/dms/endpoint.go index 7aeeb341bc0..1f62af64ad3 100644 --- a/internal/service/dms/endpoint.go +++ b/internal/service/dms/endpoint.go @@ -351,7 +351,6 @@ func ResourceEndpoint() *schema.Resource { "postgres_settings": { Type: schema.TypeList, Optional: true, - Computed: true, MaxItems: 1, DiffSuppressFunc: verify.SuppressMissingOptionalConfigurationBlock, Elem: &schema.Resource{ @@ -367,59 +366,46 @@ func ResourceEndpoint() *schema.Resource { "max_file_size": { Type: schema.TypeInt, Optional: true, - //Default: encryptionModeSseS3, - //ValidateFunc: validation.StringInSlice(encryptionMode_Values(), false), }, "ddl_artifacts_schema": { Type: schema.TypeString, Optional: true, - //DiffSuppressFunc: tfkms.DiffSuppressKey, - //ValidateFunc: tfkms.ValidateKey, }, "execute_timeout": { Type: schema.TypeInt, Optional: true, - // ValidateFunc: verify.ValidARN, }, "fail_tasks_on_lob_truncation": { Type: schema.TypeBool, Optional: true, - // ValidateFunc: verify.ValidARN, }, "heartbeat_enable": { Type: schema.TypeBool, Optional: true, - // ValidateFunc: verify.ValidARN, }, "heartbeat_schema": { Type: schema.TypeString, Optional: true, - // ValidateFunc: verify.ValidARN, }, "heartbeat_frequency": { Type: schema.TypeInt, Optional: true, - // ValidateFunc: verify.ValidARN, }, "slot_name": { Type: schema.TypeString, Optional: true, - // ValidateFunc: verify.ValidARN, }, - "plugin_name": { // add validation function + "plugin_name": { Type: schema.TypeString, Optional: true, - // ValidateFunc: verify.ValidARN, }, "trim_space_in_char": { Type: schema.TypeBool, Optional: true, - // ValidateFunc: verify.ValidARN, }, "map_boolean_as_boolean": { Type: schema.TypeBool, Optional: true, - // ValidateFunc: verify.ValidARN, }, }, }, diff --git a/internal/service/dms/endpoint_test.go b/internal/service/dms/endpoint_test.go index 2401e7f01c4..a37415ef14a 100644 --- a/internal/service/dms/endpoint_test.go +++ b/internal/service/dms/endpoint_test.go @@ -1349,6 +1349,32 @@ func TestAccDMSEndpoint_PostgreSQL_kmsKey(t *testing.T) { }) } +func TestAccDMSEndpoint_PostgreSQL_settings(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_dms_endpoint.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, dms.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEndpointDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEndpointConfig_postgreSQLSettings(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.#", "1"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.after_connect_script", "SET search_path TO pg_catalog,public;"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.capture_ddls", "true"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.max_file_size", "1024"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.execute_timeout", "100"), + ), + }, + }, + }) +} + func TestAccDMSEndpoint_SQLServer_basic(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_dms_endpoint.test" @@ -3800,6 +3826,29 @@ resource "aws_dms_endpoint" "test" { `, rName) } +func testAccEndpointConfig_postgreSQLSettings(rName string) string { + return fmt.Sprintf(` +resource "aws_dms_endpoint" "test" { + endpoint_id = %[1]q + endpoint_type = "source" + engine_name = "postgres" + server_name = "tftest" + port = 27017 + username = "tftest" + password = "tftest" + database_name = "tftest" + ssl_mode = "require" + extra_connection_attributes = "" + postgres_settings { + after_connect_script = "SET search_path TO pg_catalog,public;" + capture_ddls = true + max_file_size = 1024 + execute_timeout = 100 + } +} +`, rName) +} + func testAccEndpointConfig_sqlServer(rName string) string { return fmt.Sprintf(` resource "aws_dms_endpoint" "test" { From 1ccf9d9249a149424acdc889559f2e692f938273 Mon Sep 17 00:00:00 2001 From: Andrea Quintino Date: Sat, 2 Dec 2023 09:59:02 +0100 Subject: [PATCH 05/17] update tests --- internal/service/dms/endpoint_test.go | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/internal/service/dms/endpoint_test.go b/internal/service/dms/endpoint_test.go index a37415ef14a..1372464ec55 100644 --- a/internal/service/dms/endpoint_test.go +++ b/internal/service/dms/endpoint_test.go @@ -1368,7 +1368,15 @@ func TestAccDMSEndpoint_PostgreSQL_settings(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.after_connect_script", "SET search_path TO pg_catalog,public;"), resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.capture_ddls", "true"), resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.max_file_size", "1024"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.ddl_artifacts_schema", "true"), resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.execute_timeout", "100"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.fail_tasks_on_lob_truncation", "false"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.heartbeat_enable", "true"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.heartbeat_schema", "test"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.slot_name", "test"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.plugin_name", "pglogical"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.trim_space_in_char", "true"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.map_boolean_as_boolean", "true"), ), }, }, @@ -3841,9 +3849,17 @@ resource "aws_dms_endpoint" "test" { extra_connection_attributes = "" postgres_settings { after_connect_script = "SET search_path TO pg_catalog,public;" - capture_ddls = true - max_file_size = 1024 - execute_timeout = 100 + capture_ddls = true + max_file_size = 1024 + execute_timeout = 100 + ddl_artifacts_schema = true + fail_tasks_on_lob_truncation = false + heartbeat_enable = true + heartbeat_schema = "test" + slot_name = "test" + plugin_name = "pglogical" + trim_space_in_char = true + map_boolean_as_boolean = true } } `, rName) From 40e9d3b067c6f46f1e73232ab2652c0a623aca74 Mon Sep 17 00:00:00 2001 From: Andrea Quintino Date: Mon, 4 Dec 2023 18:53:33 +0100 Subject: [PATCH 06/17] should be ok --- internal/service/dms/endpoint.go | 65 ++++++++++++------ internal/service/dms/endpoint_test.go | 81 +++++++++++++++++++---- website/docs/r/dms_endpoint.html.markdown | 21 ++++++ 3 files changed, 132 insertions(+), 35 deletions(-) diff --git a/internal/service/dms/endpoint.go b/internal/service/dms/endpoint.go index 1f62af64ad3..47d38d9f560 100644 --- a/internal/service/dms/endpoint.go +++ b/internal/service/dms/endpoint.go @@ -359,12 +359,16 @@ func ResourceEndpoint() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "babelfish_database_name": { + Type: schema.TypeString, + Optional: true, + }, "capture_ddls": { Type: schema.TypeBool, Optional: true, }, - "max_file_size": { - Type: schema.TypeInt, + "database_mode": { + Type: schema.TypeString, Optional: true, }, "ddl_artifacts_schema": { @@ -383,28 +387,36 @@ func ResourceEndpoint() *schema.Resource { Type: schema.TypeBool, Optional: true, }, + "heartbeat_frequency": { + Type: schema.TypeInt, + Optional: true, + }, "heartbeat_schema": { Type: schema.TypeString, Optional: true, }, - "heartbeat_frequency": { - Type: schema.TypeInt, + "map_boolean_as_boolean": { + Type: schema.TypeBool, Optional: true, }, - "slot_name": { - Type: schema.TypeString, + "map_jsonb_as_clob": { + Type: schema.TypeBool, Optional: true, }, - "plugin_name": { + "map_long_varchar_as": { Type: schema.TypeString, Optional: true, }, - "trim_space_in_char": { - Type: schema.TypeBool, + "max_file_size": { + Type: schema.TypeInt, Optional: true, }, - "map_boolean_as_boolean": { - Type: schema.TypeBool, + "plugin_name": { + Type: schema.TypeString, + Optional: true, + }, + "slot_name": { + Type: schema.TypeString, Optional: true, }, }, @@ -2134,11 +2146,14 @@ func expandPostgreSQLSettings(tfMap map[string]interface{}) *dms.PostgreSQLSetti if v, ok := tfMap["after_connect_script"].(string); ok && v != "" { settings.AfterConnectScript = aws.String(v) } + if v, ok := tfMap["babelfish_database_name"].(string); ok && v != "" { + settings.BabelfishDatabaseName = aws.String(v) + } if v, ok := tfMap["capture_ddls"].(bool); ok { settings.CaptureDdls = aws.Bool(v) } - if v, ok := tfMap["max_file_size"].(int); ok { - settings.MaxFileSize = aws.Int64(int64(v)) + if v, ok := tfMap["database_mode"].(string); ok && v != "" { + settings.DatabaseMode = aws.String(v) } if v, ok := tfMap["ddl_artifacts_schema"].(string); ok && v != "" { settings.DdlArtifactsSchema = aws.String(v) @@ -2152,23 +2167,29 @@ func expandPostgreSQLSettings(tfMap map[string]interface{}) *dms.PostgreSQLSetti if v, ok := tfMap["heartbeat_enable"].(bool); ok { settings.HeartbeatEnable = aws.Bool(v) } + if v, ok := tfMap["heartbeat_frequency"].(int); ok { + settings.HeartbeatFrequency = aws.Int64(int64(v)) + } if v, ok := tfMap["heartbeat_schema"].(string); ok && v != "" { settings.HeartbeatSchema = aws.String(v) } - if v, ok := tfMap["heartbeat_frequency"].(int); ok { - settings.HeartbeatFrequency = aws.Int64(int64(v)) + if v, ok := tfMap["map_boolean_as_boolean"].(bool); ok { + settings.MapBooleanAsBoolean = aws.Bool(v) } - if v, ok := tfMap["slot_name"].(string); ok && v != "" { - settings.SlotName = aws.String(v) + if v, ok := tfMap["map_jsonb_as_clob"].(bool); ok { + settings.MapJsonbAsClob = aws.Bool(v) + } + if v, ok := tfMap["map_long_varchar_as"].(string); ok && v != "" { + settings.MapLongVarcharAs = aws.String(v) + } + if v, ok := tfMap["max_file_size"].(int); ok { + settings.MaxFileSize = aws.Int64(int64(v)) } if v, ok := tfMap["plugin_name"].(string); ok && v != "" { settings.PluginName = aws.String(v) } - if v, ok := tfMap["trim_space_in_char"].(bool); ok { - settings.TrimSpaceInChar = aws.Bool(v) - } - if v, ok := tfMap["map_boolean_as_boolean"].(bool); ok { - settings.MapBooleanAsBoolean = aws.Bool(v) + if v, ok := tfMap["slot_name"].(string); ok && v != "" { + settings.SlotName = aws.String(v) } return settings diff --git a/internal/service/dms/endpoint_test.go b/internal/service/dms/endpoint_test.go index 1372464ec55..9b223b91f93 100644 --- a/internal/service/dms/endpoint_test.go +++ b/internal/service/dms/endpoint_test.go @@ -1349,7 +1349,7 @@ func TestAccDMSEndpoint_PostgreSQL_kmsKey(t *testing.T) { }) } -func TestAccDMSEndpoint_PostgreSQL_settings(t *testing.T) { +func TestAccDMSEndpoint_PostgreSQL_settings_source(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_dms_endpoint.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -1361,22 +1361,51 @@ func TestAccDMSEndpoint_PostgreSQL_settings(t *testing.T) { CheckDestroy: testAccCheckEndpointDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccEndpointConfig_postgreSQLSettings(rName), + Config: testAccEndpointConfig_postgreSQLSourceSettings(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckEndpointExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "postgres_settings.#", "1"), resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.after_connect_script", "SET search_path TO pg_catalog,public;"), resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.capture_ddls", "true"), - resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.max_file_size", "1024"), resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.ddl_artifacts_schema", "true"), resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.execute_timeout", "100"), resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.fail_tasks_on_lob_truncation", "false"), resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.heartbeat_enable", "true"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.heartbeat_frequency", "5"), resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.heartbeat_schema", "test"), - resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.slot_name", "test"), - resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.plugin_name", "pglogical"), - resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.trim_space_in_char", "true"), resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.map_boolean_as_boolean", "true"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.map_jsonb_as_clob", "true"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.map_long_varchar_as", "wstring"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.max_file_size", "1024"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.plugin_name", "pglogical"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.slot_name", "test"), + ), + }, + }, + }) +} + +func TestAccDMSEndpoint_PostgreSQL_settings_target(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_dms_endpoint.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, dms.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEndpointDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEndpointConfig_postgreSQLTargetSettings(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.#", "1"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.after_connect_script", "SET search_path TO pg_catalog,public;"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.babelfish_database_name", "babelfish"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.database_mode", "babelfish"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.execute_timeout", "100"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.max_file_size", "1024"), ), }, }, @@ -3834,14 +3863,14 @@ resource "aws_dms_endpoint" "test" { `, rName) } -func testAccEndpointConfig_postgreSQLSettings(rName string) string { +func testAccEndpointConfig_postgreSQLSourceSettings(rName string) string { return fmt.Sprintf(` resource "aws_dms_endpoint" "test" { endpoint_id = %[1]q endpoint_type = "source" engine_name = "postgres" server_name = "tftest" - port = 27017 + port = 5432 username = "tftest" password = "tftest" database_name = "tftest" @@ -3850,16 +3879,42 @@ resource "aws_dms_endpoint" "test" { postgres_settings { after_connect_script = "SET search_path TO pg_catalog,public;" capture_ddls = true - max_file_size = 1024 - execute_timeout = 100 ddl_artifacts_schema = true + execute_timeout = 100 fail_tasks_on_lob_truncation = false heartbeat_enable = true + heartbeat_frequency = 5 heartbeat_schema = "test" - slot_name = "test" - plugin_name = "pglogical" - trim_space_in_char = true map_boolean_as_boolean = true + map_jsonb_as_clob = true + map_long_varchar_as = "wstring" + max_file_size = 1024 + plugin_name = "pglogical" + slot_name = "test" + } +} +`, rName) +} + +func testAccEndpointConfig_postgreSQLTargetSettings(rName string) string { + return fmt.Sprintf(` +resource "aws_dms_endpoint" "test" { + endpoint_id = %[1]q + endpoint_type = "target" + engine_name = "postgres" + server_name = "tftest" + port = 5432 + username = "tftest" + password = "tftest" + database_name = "tftest" + ssl_mode = "require" + extra_connection_attributes = "" + postgres_settings { + after_connect_script = "SET search_path TO pg_catalog,public;" + babelfish_database_name = "babelfish" + database_mode = "babelfish" + execute_timeout = 100 + max_file_size = 1024 } } `, rName) diff --git a/website/docs/r/dms_endpoint.html.markdown b/website/docs/r/dms_endpoint.html.markdown index 77903a417a4..898ea5c391b 100644 --- a/website/docs/r/dms_endpoint.html.markdown +++ b/website/docs/r/dms_endpoint.html.markdown @@ -58,6 +58,7 @@ The following arguments are optional: * `kinesis_settings` - (Optional) Configuration block for Kinesis settings. See below. * `mongodb_settings` - (Optional) Configuration block for MongoDB settings. See below. * `password` - (Optional) Password to be used to login to the endpoint database. +* `postgres_settings` - (Optional) Configuration block for Postgres settings. See below. * `pause_replication_tasks` - (Optional) Whether to pause associated running replication tasks, regardless if they are managed by Terraform, prior to modifying the endpoint. Only tasks paused by the resource will be restarted after the modification completes. Default is `false`. * `port` - (Optional) Port used by the endpoint database. * `redshift_settings` - (Optional) Configuration block for Redshift settings. See below. @@ -127,6 +128,26 @@ The following arguments are optional: * `extract_doc_id` - (Optional) Document ID. Use this setting when `nesting_level` is set to `none`. Default is `false`. * `nesting_level` - (Optional) Specifies either document or table mode. Default is `none`. Valid values are `one` (table mode) and `none` (document mode). +### postgres_settings +-> Additional information can be found in the [Using PostgreSQL as a Source for AWS DMS documentation](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.PostgreSQL.html). + +* `after_connect_script` - (Optional) For use with change data capture (CDC) only, this attribute has AWS DMS bypass foreign keys and user triggers to reduce the time it takes to bulk load data. +* `babelfish_database_name` - (Optional) The Babelfish for Aurora PostgreSQL database name for the endpoint. +* `capture_ddls` - (Optional) To capture DDL events, AWS DMS creates various artifacts in the PostgreSQL database when the task starts. +* `database_mode` - (Optional) Specifies the default behavior of the replication's handling of PostgreSQL- compatible endpoints that require some additional configuration, such as Babelfish endpoints. +* `ddl_artifacts_schema` - (Optional) Sets the schema in which the operational DDL database artifacts are created. Default is `public`. +* `execute_timeout` - (Optional) Sets the client statement timeout for the PostgreSQL instance, in seconds. Default value is `60`. +* `fail_tasks_on_lob_truncation` - (Optional) When set to `true`, this value causes a task to fail if the actual size of a LOB column is greater than the specified `LobMaxSize`. Default is `false`. +* `heartbeat_enable` - (Optional) The write-ahead log (WAL) heartbeat feature mimics a dummy transaction. By doing this, it prevents idle logical replication slots from holding onto old WAL logs, which can result in storage full situations on the source. +* `heartbeat_frequency` - (Optional) Sets the WAL heartbeat frequency (in minutes). Default value is `5`. +* `heartbeat_schema` - (Optional) Sets the schema in which the heartbeat artifacts are created. Default value is `public`. +* `map_boolean_as_boolean` - (Optional) You can use PostgreSQL endpoint settings to map a boolean as a boolean from your PostgreSQL source to a Amazon Redshift target. Default value is `false`. +* `map_jsonb_as_clob` - Optional When true, DMS migrates JSONB values as CLOB. +* `map_long_varchar_as` - Optional When true, DMS migrates LONG values as VARCHAR. +* `max_file_size` - (Optional) Specifies the maximum size (in KB) of any .csv file used to transfer data to PostgreSQL. Default is `32,768 KB`. +* `plugin_name` - (Optional) Specifies the plugin to use to create a replication slot. Valid values: `pglogical`, `test_decoding`. +* `slot_name` - (Optional) Sets the name of a previously created logical replication slot for a CDC load of the PostgreSQL source instance. + ### redis_settings -> Additional information can be found in the [Using Redis as a target for AWS Database Migration Service](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Target.Redis.html). From 89a365706a907eebef72301e23e8a89bb5fe20c9 Mon Sep 17 00:00:00 2001 From: Andrea Quintino Date: Mon, 4 Dec 2023 21:55:20 +0100 Subject: [PATCH 07/17] fix markdown and terraform test code --- internal/service/dms/endpoint_test.go | 4 ++-- website/docs/r/dms_endpoint.html.markdown | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/service/dms/endpoint_test.go b/internal/service/dms/endpoint_test.go index 9b223b91f93..7fee7fbc6fd 100644 --- a/internal/service/dms/endpoint_test.go +++ b/internal/service/dms/endpoint_test.go @@ -3877,7 +3877,7 @@ resource "aws_dms_endpoint" "test" { ssl_mode = "require" extra_connection_attributes = "" postgres_settings { - after_connect_script = "SET search_path TO pg_catalog,public;" + after_connect_script = "SET search_path TO pg_catalog,public;" capture_ddls = true ddl_artifacts_schema = true execute_timeout = 100 @@ -3910,7 +3910,7 @@ resource "aws_dms_endpoint" "test" { ssl_mode = "require" extra_connection_attributes = "" postgres_settings { - after_connect_script = "SET search_path TO pg_catalog,public;" + after_connect_script = "SET search_path TO pg_catalog,public;" babelfish_database_name = "babelfish" database_mode = "babelfish" execute_timeout = 100 diff --git a/website/docs/r/dms_endpoint.html.markdown b/website/docs/r/dms_endpoint.html.markdown index 898ea5c391b..191b0af2070 100644 --- a/website/docs/r/dms_endpoint.html.markdown +++ b/website/docs/r/dms_endpoint.html.markdown @@ -129,6 +129,7 @@ The following arguments are optional: * `nesting_level` - (Optional) Specifies either document or table mode. Default is `none`. Valid values are `one` (table mode) and `none` (document mode). ### postgres_settings + -> Additional information can be found in the [Using PostgreSQL as a Source for AWS DMS documentation](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.PostgreSQL.html). * `after_connect_script` - (Optional) For use with change data capture (CDC) only, this attribute has AWS DMS bypass foreign keys and user triggers to reduce the time it takes to bulk load data. From f50d54d33a226b6ec577123d22965189b093570d Mon Sep 17 00:00:00 2001 From: Andrea Quintino Date: Tue, 5 Dec 2023 09:30:28 +0100 Subject: [PATCH 08/17] fixed terraform test code --- internal/service/dms/endpoint_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/service/dms/endpoint_test.go b/internal/service/dms/endpoint_test.go index 7fee7fbc6fd..7d479b933a9 100644 --- a/internal/service/dms/endpoint_test.go +++ b/internal/service/dms/endpoint_test.go @@ -3910,11 +3910,11 @@ resource "aws_dms_endpoint" "test" { ssl_mode = "require" extra_connection_attributes = "" postgres_settings { - after_connect_script = "SET search_path TO pg_catalog,public;" - babelfish_database_name = "babelfish" - database_mode = "babelfish" - execute_timeout = 100 - max_file_size = 1024 + after_connect_script = "SET search_path TO pg_catalog,public;" + babelfish_database_name = "babelfish" + database_mode = "babelfish" + execute_timeout = 100 + max_file_size = 1024 } } `, rName) From 5b3aa6dda1a42623f84263d3041aa09cf9db1149 Mon Sep 17 00:00:00 2001 From: Andrea Quintino Date: Tue, 5 Dec 2023 17:21:16 +0100 Subject: [PATCH 09/17] fixed terraform test code --- internal/service/dms/endpoint_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/dms/endpoint_test.go b/internal/service/dms/endpoint_test.go index 7d479b933a9..aa8d130a80b 100644 --- a/internal/service/dms/endpoint_test.go +++ b/internal/service/dms/endpoint_test.go @@ -3876,7 +3876,7 @@ resource "aws_dms_endpoint" "test" { database_name = "tftest" ssl_mode = "require" extra_connection_attributes = "" - postgres_settings { + postgres_settings { after_connect_script = "SET search_path TO pg_catalog,public;" capture_ddls = true ddl_artifacts_schema = true @@ -3909,7 +3909,7 @@ resource "aws_dms_endpoint" "test" { database_name = "tftest" ssl_mode = "require" extra_connection_attributes = "" - postgres_settings { + postgres_settings { after_connect_script = "SET search_path TO pg_catalog,public;" babelfish_database_name = "babelfish" database_mode = "babelfish" From b4eacaeebcb660e3cf283b77c2f4c836a8faafbf Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 13 Dec 2023 10:45:01 -0500 Subject: [PATCH 10/17] Add CHANGELOG entry. --- .changelog/34724.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/34724.txt diff --git a/.changelog/34724.txt b/.changelog/34724.txt new file mode 100644 index 00000000000..2f038716a38 --- /dev/null +++ b/.changelog/34724.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_dms_endpoint: Add `postgres_settings` configuration block +``` \ No newline at end of file From 4d6f6e394d0ebac90cf013be92807fcdf56899b4 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 13 Dec 2023 10:47:53 -0500 Subject: [PATCH 11/17] Fix terrafmt error. --- internal/service/dms/endpoint_test.go | 29 ++++++++++++++------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/internal/service/dms/endpoint_test.go b/internal/service/dms/endpoint_test.go index aa8d130a80b..93910c75b3e 100644 --- a/internal/service/dms/endpoint_test.go +++ b/internal/service/dms/endpoint_test.go @@ -3876,21 +3876,22 @@ resource "aws_dms_endpoint" "test" { database_name = "tftest" ssl_mode = "require" extra_connection_attributes = "" + postgres_settings { - after_connect_script = "SET search_path TO pg_catalog,public;" - capture_ddls = true - ddl_artifacts_schema = true - execute_timeout = 100 - fail_tasks_on_lob_truncation = false - heartbeat_enable = true - heartbeat_frequency = 5 - heartbeat_schema = "test" - map_boolean_as_boolean = true - map_jsonb_as_clob = true - map_long_varchar_as = "wstring" - max_file_size = 1024 - plugin_name = "pglogical" - slot_name = "test" + after_connect_script = "SET search_path TO pg_catalog,public;" + capture_ddls = true + ddl_artifacts_schema = true + execute_timeout = 100 + fail_tasks_on_lob_truncation = false + heartbeat_enable = true + heartbeat_frequency = 5 + heartbeat_schema = "test" + map_boolean_as_boolean = true + map_jsonb_as_clob = true + map_long_varchar_as = "wstring" + max_file_size = 1024 + plugin_name = "pglogical" + slot_name = "test" } } `, rName) From 2a7237b764291b58279813b7b1db741445dd5ce9 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 13 Dec 2023 10:52:51 -0500 Subject: [PATCH 12/17] r/aws_dms_endpoint: Cosmetics. --- internal/service/dms/endpoint.go | 63 +++++++++++++++++--------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/internal/service/dms/endpoint.go b/internal/service/dms/endpoint.go index 47d38d9f560..aaf6b2e6e47 100644 --- a/internal/service/dms/endpoint.go +++ b/internal/service/dms/endpoint.go @@ -826,26 +826,27 @@ func resourceEndpointCreate(ctx context.Context, d *schema.ResourceData, meta in expandTopLevelConnectionInfo(d, input) } case engineNameAuroraPostgresql, engineNamePostgres: - postgres_settings := &dms.PostgreSQLSettings{} + settings := &dms.PostgreSQLSettings{} if _, ok := d.GetOk("postgres_settings"); ok { - postgres_settings = expandPostgreSQLSettings(d.Get("postgres_settings").([]interface{})[0].(map[string]interface{})) + settings = expandPostgreSQLSettings(d.Get("postgres_settings").([]interface{})[0].(map[string]interface{})) } if _, ok := d.GetOk("secrets_manager_arn"); ok { - postgres_settings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string)) - postgres_settings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string)) - postgres_settings.DatabaseName = aws.String(d.Get("database_name").(string)) + settings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string)) + settings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string)) + settings.DatabaseName = aws.String(d.Get("database_name").(string)) } else { - postgres_settings.Username = aws.String(d.Get("username").(string)) - postgres_settings.Password = aws.String(d.Get("password").(string)) - postgres_settings.ServerName = aws.String(d.Get("server_name").(string)) - postgres_settings.Port = aws.Int64(int64(d.Get("port").(int))) - postgres_settings.DatabaseName = aws.String(d.Get("database_name").(string)) + settings.Username = aws.String(d.Get("username").(string)) + settings.Password = aws.String(d.Get("password").(string)) + settings.ServerName = aws.String(d.Get("server_name").(string)) + settings.Port = aws.Int64(int64(d.Get("port").(int))) + settings.DatabaseName = aws.String(d.Get("database_name").(string)) // Set connection info in top-level namespace as well expandTopLevelConnectionInfo(d, input) } - input.PostgreSQLSettings = postgres_settings + + input.PostgreSQLSettings = settings case engineNameDynamoDB: input.DynamoDbSettings = &dms.DynamoDbSettings{ ServiceAccessRoleArn: aws.String(d.Get("service_access_role").(string)), @@ -2141,58 +2142,62 @@ func flattenRedshiftSettings(settings *dms.RedshiftSettings) []map[string]interf } func expandPostgreSQLSettings(tfMap map[string]interface{}) *dms.PostgreSQLSettings { - settings := &dms.PostgreSQLSettings{} + if tfMap == nil { + return nil + } + + apiObject := &dms.PostgreSQLSettings{} if v, ok := tfMap["after_connect_script"].(string); ok && v != "" { - settings.AfterConnectScript = aws.String(v) + apiObject.AfterConnectScript = aws.String(v) } if v, ok := tfMap["babelfish_database_name"].(string); ok && v != "" { - settings.BabelfishDatabaseName = aws.String(v) + apiObject.BabelfishDatabaseName = aws.String(v) } if v, ok := tfMap["capture_ddls"].(bool); ok { - settings.CaptureDdls = aws.Bool(v) + apiObject.CaptureDdls = aws.Bool(v) } if v, ok := tfMap["database_mode"].(string); ok && v != "" { - settings.DatabaseMode = aws.String(v) + apiObject.DatabaseMode = aws.String(v) } if v, ok := tfMap["ddl_artifacts_schema"].(string); ok && v != "" { - settings.DdlArtifactsSchema = aws.String(v) + apiObject.DdlArtifactsSchema = aws.String(v) } if v, ok := tfMap["execute_timeout"].(int); ok { - settings.ExecuteTimeout = aws.Int64(int64(v)) + apiObject.ExecuteTimeout = aws.Int64(int64(v)) } if v, ok := tfMap["fail_tasks_on_lob_truncation"].(bool); ok { - settings.FailTasksOnLobTruncation = aws.Bool(v) + apiObject.FailTasksOnLobTruncation = aws.Bool(v) } if v, ok := tfMap["heartbeat_enable"].(bool); ok { - settings.HeartbeatEnable = aws.Bool(v) + apiObject.HeartbeatEnable = aws.Bool(v) } if v, ok := tfMap["heartbeat_frequency"].(int); ok { - settings.HeartbeatFrequency = aws.Int64(int64(v)) + apiObject.HeartbeatFrequency = aws.Int64(int64(v)) } if v, ok := tfMap["heartbeat_schema"].(string); ok && v != "" { - settings.HeartbeatSchema = aws.String(v) + apiObject.HeartbeatSchema = aws.String(v) } if v, ok := tfMap["map_boolean_as_boolean"].(bool); ok { - settings.MapBooleanAsBoolean = aws.Bool(v) + apiObject.MapBooleanAsBoolean = aws.Bool(v) } if v, ok := tfMap["map_jsonb_as_clob"].(bool); ok { - settings.MapJsonbAsClob = aws.Bool(v) + apiObject.MapJsonbAsClob = aws.Bool(v) } if v, ok := tfMap["map_long_varchar_as"].(string); ok && v != "" { - settings.MapLongVarcharAs = aws.String(v) + apiObject.MapLongVarcharAs = aws.String(v) } if v, ok := tfMap["max_file_size"].(int); ok { - settings.MaxFileSize = aws.Int64(int64(v)) + apiObject.MaxFileSize = aws.Int64(int64(v)) } if v, ok := tfMap["plugin_name"].(string); ok && v != "" { - settings.PluginName = aws.String(v) + apiObject.PluginName = aws.String(v) } if v, ok := tfMap["slot_name"].(string); ok && v != "" { - settings.SlotName = aws.String(v) + apiObject.SlotName = aws.String(v) } - return settings + return apiObject } func expandS3Settings(tfMap map[string]interface{}) *dms.S3Settings { From 174b0ae0eb5442a678f867476b67eea53c6e87f8 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 13 Dec 2023 11:24:54 -0500 Subject: [PATCH 13/17] r/aws_dms_endpoint: Add 'flattenPostgreSQLSettings'. --- internal/service/dms/endpoint.go | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/internal/service/dms/endpoint.go b/internal/service/dms/endpoint.go index aaf6b2e6e47..746c958b0e9 100644 --- a/internal/service/dms/endpoint.go +++ b/internal/service/dms/endpoint.go @@ -1553,6 +1553,9 @@ func resourceEndpointSetState(d *schema.ResourceData, endpoint *dms.Endpoint) er } else { flattenTopLevelConnectionInfo(d, endpoint) } + if err := d.Set("postgres_settings", flattenPostgreSQLSettings(endpoint.PostgreSQLSettings)); err != nil { + return fmt.Errorf("setting postgres_settings: %w", err) + } case engineNameDynamoDB: if endpoint.DynamoDbSettings != nil { d.Set("service_access_role", endpoint.DynamoDbSettings.ServiceAccessRoleArn) @@ -2200,6 +2203,65 @@ func expandPostgreSQLSettings(tfMap map[string]interface{}) *dms.PostgreSQLSetti return apiObject } +func flattenPostgreSQLSettings(apiObject *dms.PostgreSQLSettings) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.AfterConnectScript; v != nil { + tfMap["after_connect_script"] = aws.StringValue(v) + } + if v := apiObject.BabelfishDatabaseName; v != nil { + tfMap["babelfish_database_name"] = aws.StringValue(v) + } + if v := apiObject.CaptureDdls; v != nil { + tfMap["capture_ddls"] = aws.BoolValue(v) + } + if v := apiObject.DatabaseMode; v != nil { + tfMap["database_mode"] = aws.StringValue(v) + } + if v := apiObject.DdlArtifactsSchema; v != nil { + tfMap["ddl_artifacts_schema"] = aws.StringValue(v) + } + if v := apiObject.ExecuteTimeout; v != nil { + tfMap["execute_timeout"] = aws.Int64Value(v) + } + if v := apiObject.FailTasksOnLobTruncation; v != nil { + tfMap["fail_tasks_on_lob_truncation"] = aws.BoolValue(v) + } + if v := apiObject.HeartbeatEnable; v != nil { + tfMap["heartbeat_enable"] = aws.BoolValue(v) + } + if v := apiObject.HeartbeatFrequency; v != nil { + tfMap["heartbeat_frequency"] = aws.Int64Value(v) + } + if v := apiObject.HeartbeatSchema; v != nil { + tfMap["heartbeat_schema"] = aws.StringValue(v) + } + if v := apiObject.MapBooleanAsBoolean; v != nil { + tfMap["map_boolean_as_boolean"] = aws.BoolValue(v) + } + if v := apiObject.MapJsonbAsClob; v != nil { + tfMap["map_jsonb_as_clob"] = aws.BoolValue(v) + } + if v := apiObject.MapLongVarcharAs; v != nil { + tfMap["map_long_varchar_as"] = aws.StringValue(v) + } + if v := apiObject.MaxFileSize; v != nil { + tfMap["max_file_size"] = aws.Int64Value(v) + } + if v := apiObject.PluginName; v != nil { + tfMap["plugin_name"] = aws.StringValue(v) + } + if v := apiObject.SlotName; v != nil { + tfMap["slot_name"] = aws.StringValue(v) + } + + return tfMap +} + func expandS3Settings(tfMap map[string]interface{}) *dms.S3Settings { if tfMap == nil { return nil From 0fbe14782206debef8102cedc68bc136cc5b29b9 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 13 Dec 2023 11:52:58 -0500 Subject: [PATCH 14/17] Fix 'flattenPostgreSQLSettings' return value. --- internal/service/dms/endpoint.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/dms/endpoint.go b/internal/service/dms/endpoint.go index 746c958b0e9..fd284168cee 100644 --- a/internal/service/dms/endpoint.go +++ b/internal/service/dms/endpoint.go @@ -2203,7 +2203,7 @@ func expandPostgreSQLSettings(tfMap map[string]interface{}) *dms.PostgreSQLSetti return apiObject } -func flattenPostgreSQLSettings(apiObject *dms.PostgreSQLSettings) map[string]interface{} { +func flattenPostgreSQLSettings(apiObject *dms.PostgreSQLSettings) []map[string]interface{} { if apiObject == nil { return nil } @@ -2259,7 +2259,7 @@ func flattenPostgreSQLSettings(apiObject *dms.PostgreSQLSettings) map[string]int tfMap["slot_name"] = aws.StringValue(v) } - return tfMap + return []map[string]interface{}{tfMap} } func expandS3Settings(tfMap map[string]interface{}) *dms.S3Settings { From 2911b4f329b4d9cb0413e2edbc6ded90a3573395 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 13 Dec 2023 11:54:00 -0500 Subject: [PATCH 15/17] Fix terrafmt errors. --- internal/service/dms/endpoint_test.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/internal/service/dms/endpoint_test.go b/internal/service/dms/endpoint_test.go index 93910c75b3e..8dc8d0d08d1 100644 --- a/internal/service/dms/endpoint_test.go +++ b/internal/service/dms/endpoint_test.go @@ -3910,12 +3910,13 @@ resource "aws_dms_endpoint" "test" { database_name = "tftest" ssl_mode = "require" extra_connection_attributes = "" + postgres_settings { - after_connect_script = "SET search_path TO pg_catalog,public;" - babelfish_database_name = "babelfish" - database_mode = "babelfish" - execute_timeout = 100 - max_file_size = 1024 + after_connect_script = "SET search_path TO pg_catalog,public;" + babelfish_database_name = "babelfish" + database_mode = "babelfish" + execute_timeout = 100 + max_file_size = 1024 } } `, rName) From b9ace538035bc9c7b11093f6b2c4907d3a36a055 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 13 Dec 2023 12:24:01 -0500 Subject: [PATCH 16/17] Tweak 'stopReplicationTask'. --- internal/service/dms/endpoint.go | 3 --- internal/service/dms/replication_task.go | 6 +++++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/service/dms/endpoint.go b/internal/service/dms/endpoint.go index fd284168cee..0d597410865 100644 --- a/internal/service/dms/endpoint.go +++ b/internal/service/dms/endpoint.go @@ -1716,9 +1716,6 @@ func stopEndpointReplicationTasks(ctx context.Context, conn *dms.DatabaseMigrati switch aws.StringValue(task.Status) { case replicationTaskStatusRunning: err := stopReplicationTask(ctx, rtID, conn) - if tfawserr.ErrCodeEquals(err, dms.ErrCodeInvalidResourceStateFault) { - continue - } if err != nil { return stoppedTasks, err diff --git a/internal/service/dms/replication_task.go b/internal/service/dms/replication_task.go index 74dee1dae40..aeb3ae87f0f 100644 --- a/internal/service/dms/replication_task.go +++ b/internal/service/dms/replication_task.go @@ -387,7 +387,7 @@ func startReplicationTask(ctx context.Context, conn *dms.DatabaseMigrationServic } func stopReplicationTask(ctx context.Context, id string, conn *dms.DatabaseMigrationService) error { - log.Printf("[DEBUG] Stopping DMS Replication Task: (%s)", id) + log.Printf("[DEBUG] Stopping DMS Replication Task: %s", id) task, err := FindReplicationTaskByID(ctx, conn, id) if err != nil { @@ -402,6 +402,10 @@ func stopReplicationTask(ctx context.Context, id string, conn *dms.DatabaseMigra ReplicationTaskArn: task.ReplicationTaskArn, }) + if tfawserr.ErrMessageContains(err, dms.ErrCodeInvalidResourceStateFault, "is currently not running") { + return nil + } + if err != nil { return fmt.Errorf("stopping DMS Replication Task (%s): %w", id, err) } From af06aa66fc9ce6234b70e698f505a149529ab3f4 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 13 Dec 2023 12:30:30 -0500 Subject: [PATCH 17/17] d/aws_dms_endpoint: Add `postgres_settings` attribute. --- .changelog/34724.txt | 4 ++ internal/service/dms/endpoint_data_source.go | 72 ++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/.changelog/34724.txt b/.changelog/34724.txt index 2f038716a38..46c34e9d4a7 100644 --- a/.changelog/34724.txt +++ b/.changelog/34724.txt @@ -1,3 +1,7 @@ ```release-note:enhancement resource/aws_dms_endpoint: Add `postgres_settings` configuration block +``` + +```release-note:enhancement +data-source/aws_dms_endpoint: Add `postgres_settings` attribute ``` \ No newline at end of file diff --git a/internal/service/dms/endpoint_data_source.go b/internal/service/dms/endpoint_data_source.go index c6d4c3f95a4..94ddeb07a50 100644 --- a/internal/service/dms/endpoint_data_source.go +++ b/internal/service/dms/endpoint_data_source.go @@ -240,6 +240,78 @@ func DataSourceEndpoint() *schema.Resource { Type: schema.TypeInt, Computed: true, }, + "postgres_settings": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "after_connect_script": { + Type: schema.TypeString, + Computed: true, + }, + "babelfish_database_name": { + Type: schema.TypeString, + Computed: true, + }, + "capture_ddls": { + Type: schema.TypeBool, + Computed: true, + }, + "database_mode": { + Type: schema.TypeString, + Computed: true, + }, + "ddl_artifacts_schema": { + Type: schema.TypeString, + Computed: true, + }, + "execute_timeout": { + Type: schema.TypeInt, + Computed: true, + }, + "fail_tasks_on_lob_truncation": { + Type: schema.TypeBool, + Computed: true, + }, + "heartbeat_enable": { + Type: schema.TypeBool, + Computed: true, + }, + "heartbeat_frequency": { + Type: schema.TypeInt, + Computed: true, + }, + "heartbeat_schema": { + Type: schema.TypeString, + Computed: true, + }, + "map_boolean_as_boolean": { + Type: schema.TypeBool, + Computed: true, + }, + "map_jsonb_as_clob": { + Type: schema.TypeBool, + Computed: true, + }, + "map_long_varchar_as": { + Type: schema.TypeString, + Computed: true, + }, + "max_file_size": { + Type: schema.TypeInt, + Computed: true, + }, + "plugin_name": { + Type: schema.TypeString, + Computed: true, + }, + "slot_name": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, "redis_settings": { Type: schema.TypeList, Computed: true,