Skip to content

Commit dc17889

Browse files
committed
resource/aws_dms_endpoint: send postgres_settings on Modify
Fixes a bug where ModifyEndpoint did not include `PostgreSQLSettings` when only the nested `postgres_settings` block changed (e.g. toggling `heartbeat_enable` or setting `heartbeat_schema`). Previously the Update logic only attached `PostgreSQLSettings` when top-level connection or secrets fields changed, so nested-only diffs were lost. Implementation: * Build a single `PostgreSQLSettings` object for the update. * If `postgres_settings` changed, expand and attach those fields. * If top-level connection or secrets fields changed, overlay those onto the same object and, for the non-secrets path, call `expandTopLevelConnectionInfoModify` to keep top-level fields in sync. * Ensure `EngineName` is set so DMS accepts the modify call. Tests: * Add `TestAccDMSEndpoint_PostgreSQL_settings_update` to toggle `heartbeat_enable` and set `heartbeat_schema`, verifying that nested-only changes are applied. No schema changes, no docs changes. Fixes #35834
1 parent fa67f60 commit dc17889

File tree

3 files changed

+97
-15
lines changed

3 files changed

+97
-15
lines changed

.changelog/44389.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:bug
2+
resource/aws_dms_endpoint: fix ModifyEndpoint not sending `postgres_settings` when only nested fields are updated
3+
```

internal/service/dms/endpoint.go

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -942,29 +942,47 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an
942942
}
943943
}
944944
case engineNameAuroraPostgresql, engineNamePostgres:
945+
// Build up a single PostgreSQLSettings object so we can merge:
946+
// 1) nested postgres_settings block changes and
947+
// 2) connection/secrets changes (username/password/server/port/db OR secrets_manager_*)
948+
var pgSettings *awstypes.PostgreSQLSettings
949+
950+
// If the nested postgres_settings block changed, expand it into pgSettings
951+
if d.HasChange("postgres_settings") {
952+
raw := d.Get("postgres_settings").([]any)
953+
if len(raw) > 0 && raw[0] != nil {
954+
pgSettings = expandPostgreSQLSettings(raw[0].(map[string]any))
955+
}
956+
}
957+
958+
// If connection or secrets changed, overlay those onto the same settings object
945959
if d.HasChanges(
946-
names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, "secrets_manager_access_role_arn",
947-
"secrets_manager_arn") {
960+
names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName,
961+
"secrets_manager_access_role_arn", "secrets_manager_arn") {
962+
if pgSettings == nil {
963+
pgSettings = &awstypes.PostgreSQLSettings{}
964+
}
948965
if _, ok := d.GetOk("secrets_manager_arn"); ok {
949-
input.PostgreSQLSettings = &awstypes.PostgreSQLSettings{
950-
DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)),
951-
SecretsManagerAccessRoleArn: aws.String(d.Get("secrets_manager_access_role_arn").(string)),
952-
SecretsManagerSecretId: aws.String(d.Get("secrets_manager_arn").(string)),
953-
}
966+
pgSettings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string))
967+
pgSettings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string))
968+
pgSettings.DatabaseName = aws.String(d.Get(names.AttrDatabaseName).(string))
954969
} else {
955-
input.PostgreSQLSettings = &awstypes.PostgreSQLSettings{
956-
Username: aws.String(d.Get(names.AttrUsername).(string)),
957-
Password: aws.String(d.Get(names.AttrPassword).(string)),
958-
ServerName: aws.String(d.Get("server_name").(string)),
959-
Port: aws.Int32(int32(d.Get(names.AttrPort).(int))),
960-
DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)),
961-
}
962-
input.EngineName = aws.String(engineName) // Must be included (should be 'postgres')
970+
pgSettings.Username = aws.String(d.Get(names.AttrUsername).(string))
971+
pgSettings.Password = aws.String(d.Get(names.AttrPassword).(string))
972+
pgSettings.ServerName = aws.String(d.Get("server_name").(string))
973+
pgSettings.Port = aws.Int32(int32(d.Get(names.AttrPort).(int)))
974+
pgSettings.DatabaseName = aws.String(d.Get(names.AttrDatabaseName).(string))
963975

964976
// Update connection info in top-level namespace as well
965977
expandTopLevelConnectionInfoModify(d, &input)
966978
}
967979
}
980+
981+
// Attach PostgreSQLSettings and ensure EngineName is set
982+
if pgSettings != nil {
983+
input.PostgreSQLSettings = pgSettings
984+
input.EngineName = aws.String(engineName) // should be "postgres" or "aurora-postgresql"
985+
}
968986
case engineNameDynamoDB:
969987
if d.HasChange("service_access_role") {
970988
input.DynamoDbSettings = &awstypes.DynamoDbSettings{

internal/service/dms/endpoint_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,67 @@ func TestAccDMSEndpoint_PostgreSQL_settings_target(t *testing.T) {
12101210
})
12111211
}
12121212

1213+
func TestAccDMSEndpoint_PostgreSQL_settings_update(t *testing.T) {
1214+
ctx := acctest.Context(t)
1215+
resourceName := "aws_dms_endpoint.test"
1216+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
1217+
1218+
resource.ParallelTest(t, resource.TestCase{
1219+
PreCheck: func() { acctest.PreCheck(ctx, t) },
1220+
ErrorCheck: acctest.ErrorCheck(t, names.DMSServiceID),
1221+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
1222+
CheckDestroy: testAccCheckEndpointDestroy(ctx),
1223+
Steps: []resource.TestStep{
1224+
{
1225+
// Create with heartbeat disabled
1226+
Config: testAccEndpointConfig_postgreSQLHeartbeat(rName, false, ""),
1227+
Check: resource.ComposeAggregateTestCheckFunc(
1228+
testAccCheckEndpointExists(ctx, resourceName),
1229+
resource.TestCheckResourceAttr(resourceName, "engine_name", "postgres"),
1230+
resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.heartbeat_enable", acctest.CtFalse),
1231+
),
1232+
},
1233+
{
1234+
// Update only nested postgres_settings: enable heartbeat + set schema
1235+
Config: testAccEndpointConfig_postgreSQLHeartbeat(rName, true, "dms_heartbeat"),
1236+
Check: resource.ComposeAggregateTestCheckFunc(
1237+
testAccCheckEndpointExists(ctx, resourceName),
1238+
resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.heartbeat_enable", acctest.CtTrue),
1239+
resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.heartbeat_schema", "dms_heartbeat"),
1240+
),
1241+
},
1242+
},
1243+
})
1244+
}
1245+
1246+
func testAccEndpointConfig_postgreSQLHeartbeat(id string, heartbeat bool, schema string) string {
1247+
schemaLine := ""
1248+
if schema != "" {
1249+
schemaLine = fmt.Sprintf(`heartbeat_schema = %q`, schema)
1250+
}
1251+
1252+
// DMS ModifyEndpoint accepts metadata changes without validating connectivity,
1253+
// so placeholder connection values are sufficient for the test
1254+
return fmt.Sprintf(`
1255+
resource "aws_dms_endpoint" "test" {
1256+
endpoint_id = %q
1257+
endpoint_type = "source"
1258+
engine_name = "postgres"
1259+
1260+
username = "user"
1261+
password = "pass"
1262+
server_name = "example.com"
1263+
database_name = "postgres"
1264+
port = 5432
1265+
1266+
postgres_settings {
1267+
heartbeat_enable = %t
1268+
%s
1269+
}
1270+
}
1271+
`, id, heartbeat, schemaLine)
1272+
}
1273+
12131274
func TestAccDMSEndpoint_SQLServer_basic(t *testing.T) {
12141275
ctx := acctest.Context(t)
12151276
resourceName := "aws_dms_endpoint.test"

0 commit comments

Comments
 (0)