Skip to content

Commit 1b41728

Browse files
authored
Merge pull request #36936 from hashicorp/b-dms-replication-task-settings
`aws_dms_replication_config`, `aws_dms_replication_task`: suppress differences on task settings
2 parents 9198fc2 + d91e526 commit 1b41728

File tree

16 files changed

+2605
-674
lines changed

16 files changed

+2605
-674
lines changed

.changelog/36936.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
```release-note:bug
2+
resource/aws_dms_replication_task: Allows leaving `replication_task_settings` unset to use default settings.
3+
```
4+
5+
```release-note:bug
6+
resource/aws_dms_replication_task: Suppresses differences in partial `replication_task_settings` JSON documents.
7+
```
8+
9+
```release-note:bug
10+
resource/aws_dms_replication_task: Adds validation to `replication_task_settings` to disallow `Logging.CloudWatchLogGroup` and `Logging.CloudWatchLogStream`.
11+
```
12+
13+
```release-note:bug
14+
resource/aws_dms_replication_config: Suppresses differences in partial `replication_settings` JSON documents.
15+
```
16+
17+
```release-note:bug
18+
resource/aws_dms_replication_config: Adds validation to `replication_settings` to disallow `Logging.CloudWatchLogGroup` and `Logging.CloudWatchLogStream`.
19+
```

internal/service/dms/dms_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package dms_test
5+
6+
import (
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
10+
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
11+
"github.com/hashicorp/terraform-provider-aws/names"
12+
)
13+
14+
func init() {
15+
acctest.RegisterServiceErrorCheckFunc(names.DMSServiceID, testAccErrorCheckSkip)
16+
}
17+
18+
// testAccErrorCheckSkip skips DMS tests that have error messages indicating unsupported features
19+
func testAccErrorCheckSkip(t *testing.T) resource.ErrorCheckFunc {
20+
return acctest.ErrorCheckSkipMessagesContaining(t,
21+
// Serverless DMS in GovCloud
22+
"SERVERLESS feature is not available",
23+
)
24+
}

internal/service/dms/endpoint_test.go

Lines changed: 135 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"testing"
1010

1111
"github.com/YakDriver/regexache"
12+
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
1213
sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
1314
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
1415
"github.com/hashicorp/terraform-plugin-testing/terraform"
@@ -2211,6 +2212,7 @@ func TestAccDMSEndpoint_pauseReplicationTasks(t *testing.T) {
22112212
endpointNameSource := "aws_dms_endpoint.source"
22122213
endpointNameTarget := "aws_dms_endpoint.target"
22132214
replicationTaskName := "aws_dms_replication_task.test"
2215+
var task dms.ReplicationTask
22142216

22152217
resource.ParallelTest(t, resource.TestCase{
22162218
PreCheck: func() { acctest.PreCheck(ctx, t) },
@@ -2223,7 +2225,7 @@ func TestAccDMSEndpoint_pauseReplicationTasks(t *testing.T) {
22232225
Check: resource.ComposeTestCheckFunc(
22242226
testAccCheckEndpointExists(ctx, endpointNameSource),
22252227
testAccCheckEndpointExists(ctx, endpointNameTarget),
2226-
testAccCheckReplicationTaskExists(ctx, replicationTaskName),
2228+
testAccCheckReplicationTaskExists(ctx, replicationTaskName, &task),
22272229
resource.TestCheckResourceAttr(replicationTaskName, "status", "running"),
22282230
),
22292231
},
@@ -2232,7 +2234,7 @@ func TestAccDMSEndpoint_pauseReplicationTasks(t *testing.T) {
22322234
Check: resource.ComposeTestCheckFunc(
22332235
testAccCheckEndpointExists(ctx, endpointNameSource),
22342236
testAccCheckEndpointExists(ctx, endpointNameTarget),
2235-
testAccCheckReplicationTaskExists(ctx, replicationTaskName),
2237+
testAccCheckReplicationTaskExists(ctx, replicationTaskName, &task),
22362238
resource.TestCheckResourceAttr(replicationTaskName, "status", "running"),
22372239
),
22382240
},
@@ -4680,7 +4682,7 @@ resource "aws_kms_key" "test" {
46804682
}
46814683

46824684
func testAccEndpointConfig_pauseReplicationTasks(rName string, pause bool) string {
4683-
return acctest.ConfigCompose(testAccRDSClustersConfig_base(rName), fmt.Sprintf(`
4685+
return acctest.ConfigCompose(testAccEndpointConfig_rdsClusterBase(rName), fmt.Sprintf(`
46844686
resource "aws_dms_endpoint" "source" {
46854687
database_name = "tftest"
46864688
endpoint_id = "%[1]s-source"
@@ -4723,12 +4725,26 @@ resource "aws_dms_replication_instance" "test" {
47234725
}
47244726
47254727
resource "aws_dms_replication_task" "test" {
4726-
migration_type = "full-load-and-cdc"
4727-
replication_instance_arn = aws_dms_replication_instance.test.replication_instance_arn
4728-
replication_task_id = %[1]q
4729-
replication_task_settings = "{\"BeforeImageSettings\":null,\"FailTaskWhenCleanTaskResourceFailed\":false,\"ChangeProcessingDdlHandlingPolicy\":{\"HandleSourceTableAltered\":true,\"HandleSourceTableDropped\":true,\"HandleSourceTableTruncated\":true},\"ChangeProcessingTuning\":{\"BatchApplyMemoryLimit\":500,\"BatchApplyPreserveTransaction\":true,\"BatchApplyTimeoutMax\":30,\"BatchApplyTimeoutMin\":1,\"BatchSplitSize\":0,\"CommitTimeout\":1,\"MemoryKeepTime\":60,\"MemoryLimitTotal\":1024,\"MinTransactionSize\":1000,\"StatementCacheSize\":50},\"CharacterSetSettings\":null,\"ControlTablesSettings\":{\"ControlSchema\":\"\",\"FullLoadExceptionTableEnabled\":false,\"HistoryTableEnabled\":false,\"HistoryTimeslotInMinutes\":5,\"StatusTableEnabled\":false,\"SuspendedTablesTableEnabled\":false},\"ErrorBehavior\":{\"ApplyErrorDeletePolicy\":\"IGNORE_RECORD\",\"ApplyErrorEscalationCount\":0,\"ApplyErrorEscalationPolicy\":\"LOG_ERROR\",\"ApplyErrorFailOnTruncationDdl\":false,\"ApplyErrorInsertPolicy\":\"LOG_ERROR\",\"ApplyErrorUpdatePolicy\":\"LOG_ERROR\",\"DataErrorEscalationCount\":0,\"DataErrorEscalationPolicy\":\"SUSPEND_TABLE\",\"DataErrorPolicy\":\"LOG_ERROR\",\"DataTruncationErrorPolicy\":\"LOG_ERROR\",\"EventErrorPolicy\":\"IGNORE\",\"FailOnNoTablesCaptured\":false,\"FailOnTransactionConsistencyBreached\":false,\"FullLoadIgnoreConflicts\":true,\"RecoverableErrorCount\":-1,\"RecoverableErrorInterval\":5,\"RecoverableErrorStopRetryAfterThrottlingMax\":false,\"RecoverableErrorThrottling\":true,\"RecoverableErrorThrottlingMax\":1800,\"TableErrorEscalationCount\":0,\"TableErrorEscalationPolicy\":\"STOP_TASK\",\"TableErrorPolicy\":\"SUSPEND_TABLE\"},\"FullLoadSettings\":{\"CommitRate\":10000,\"CreatePkAfterFullLoad\":false,\"MaxFullLoadSubTasks\":8,\"StopTaskCachedChangesApplied\":false,\"StopTaskCachedChangesNotApplied\":false,\"TargetTablePrepMode\":\"DROP_AND_CREATE\",\"TransactionConsistencyTimeout\":600},\"Logging\":{\"EnableLogging\":false,\"LogComponents\":[{\"Id\":\"TRANSFORMATION\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"SOURCE_UNLOAD\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"IO\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"TARGET_LOAD\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"PERFORMANCE\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"SOURCE_CAPTURE\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"SORTER\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"REST_SERVER\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"VALIDATOR_EXT\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"TARGET_APPLY\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"TASK_MANAGER\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"TABLES_MANAGER\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"METADATA_MANAGER\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"FILE_FACTORY\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"COMMON\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"ADDONS\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"DATA_STRUCTURE\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"COMMUNICATION\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"FILE_TRANSFER\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"}]},\"LoopbackPreventionSettings\":null,\"PostProcessingRules\":null,\"StreamBufferSettings\":{\"CtrlStreamBufferSizeInMB\":5,\"StreamBufferCount\":3,\"StreamBufferSizeInMB\":8},\"TargetMetadata\":{\"BatchApplyEnabled\":false,\"FullLobMode\":false,\"InlineLobMaxSize\":0,\"LimitedSizeLobMode\":true,\"LoadMaxFileSize\":0,\"LobChunkSize\":0,\"LobMaxSize\":32,\"ParallelApplyBufferSize\":0,\"ParallelApplyQueuesPerThread\":0,\"ParallelApplyThreads\":0,\"ParallelLoadBufferSize\":0,\"ParallelLoadQueuesPerThread\":0,\"ParallelLoadThreads\":0,\"SupportLobs\":true,\"TargetSchema\":\"\",\"TaskRecoveryTableEnabled\":false},\"TTSettings\":{\"EnableTT\":false,\"TTRecordSettings\":null,\"TTS3Settings\":null}}"
4730-
source_endpoint_arn = aws_dms_endpoint.source.endpoint_arn
4731-
table_mappings = "{\"rules\":[{\"rule-type\":\"selection\",\"rule-id\":\"1\",\"rule-name\":\"testrule\",\"object-locator\":{\"schema-name\":\"%%\",\"table-name\":\"%%\"},\"rule-action\":\"include\"}]}"
4728+
migration_type = "full-load-and-cdc"
4729+
replication_instance_arn = aws_dms_replication_instance.test.replication_instance_arn
4730+
replication_task_id = %[1]q
4731+
source_endpoint_arn = aws_dms_endpoint.source.endpoint_arn
4732+
table_mappings = jsonencode(
4733+
{
4734+
"rules" = [
4735+
{
4736+
"rule-type" = "selection",
4737+
"rule-id" = "1",
4738+
"rule-name" = "testrule",
4739+
"object-locator" = {
4740+
"schema-name" = "%%",
4741+
"table-name" = "%%"
4742+
},
4743+
"rule-action" = "include"
4744+
}
4745+
]
4746+
}
4747+
)
47324748
47334749
start_replication_task = true
47344750
@@ -4742,3 +4758,113 @@ resource "aws_dms_replication_task" "test" {
47424758
}
47434759
`, rName, pause))
47444760
}
4761+
4762+
// testAccEndpointConfig_rdsClusterBase configures a pair of Aurora RDS clusters (and instances) ready for replication.
4763+
func testAccEndpointConfig_rdsClusterBase(rName string) string {
4764+
return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 2), fmt.Sprintf(`
4765+
resource "aws_db_subnet_group" "test" {
4766+
name = %[1]q
4767+
subnet_ids = aws_subnet.test[*].id
4768+
}
4769+
4770+
resource "aws_security_group" "test" {
4771+
name = %[1]q
4772+
vpc_id = aws_vpc.test.id
4773+
4774+
ingress {
4775+
from_port = 0
4776+
to_port = 0
4777+
protocol = -1
4778+
cidr_blocks = ["0.0.0.0/0"]
4779+
}
4780+
4781+
egress {
4782+
from_port = 0
4783+
to_port = 0
4784+
protocol = "-1"
4785+
cidr_blocks = ["0.0.0.0/0"]
4786+
}
4787+
4788+
tags = {
4789+
Name = %[1]q
4790+
}
4791+
}
4792+
4793+
data "aws_rds_engine_version" "default" {
4794+
engine = "aurora-mysql"
4795+
}
4796+
4797+
data "aws_rds_orderable_db_instance" "test" {
4798+
engine = data.aws_rds_engine_version.default.engine
4799+
engine_version = data.aws_rds_engine_version.default.version
4800+
preferred_instance_classes = ["db.t3.small", "db.t3.medium", "db.t3.large"]
4801+
}
4802+
4803+
resource "aws_rds_cluster_parameter_group" "test" {
4804+
name = "%[1]s-pg-cluster"
4805+
family = data.aws_rds_engine_version.default.parameter_group_family
4806+
description = "DMS cluster parameter group"
4807+
4808+
parameter {
4809+
name = "binlog_format"
4810+
value = "ROW"
4811+
apply_method = "pending-reboot"
4812+
}
4813+
4814+
parameter {
4815+
name = "binlog_row_image"
4816+
value = "Full"
4817+
apply_method = "pending-reboot"
4818+
}
4819+
4820+
parameter {
4821+
name = "binlog_checksum"
4822+
value = "NONE"
4823+
apply_method = "pending-reboot"
4824+
}
4825+
}
4826+
4827+
resource "aws_rds_cluster" "source" {
4828+
cluster_identifier = "%[1]s-aurora-cluster-source"
4829+
engine = data.aws_rds_orderable_db_instance.test.engine
4830+
engine_version = data.aws_rds_orderable_db_instance.test.engine_version
4831+
database_name = "tftest"
4832+
master_username = "tftest"
4833+
master_password = "mustbeeightcharaters"
4834+
skip_final_snapshot = true
4835+
vpc_security_group_ids = [aws_security_group.test.id]
4836+
db_subnet_group_name = aws_db_subnet_group.test.name
4837+
db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.test.name
4838+
}
4839+
4840+
resource "aws_rds_cluster_instance" "source" {
4841+
identifier = "%[1]s-source-primary"
4842+
cluster_identifier = aws_rds_cluster.source.id
4843+
engine = data.aws_rds_orderable_db_instance.test.engine
4844+
engine_version = data.aws_rds_orderable_db_instance.test.engine_version
4845+
instance_class = data.aws_rds_orderable_db_instance.test.instance_class
4846+
db_subnet_group_name = aws_db_subnet_group.test.name
4847+
}
4848+
4849+
resource "aws_rds_cluster" "target" {
4850+
cluster_identifier = "%[1]s-aurora-cluster-target"
4851+
engine = data.aws_rds_orderable_db_instance.test.engine
4852+
engine_version = data.aws_rds_orderable_db_instance.test.engine_version
4853+
database_name = "tftest"
4854+
master_username = "tftest"
4855+
master_password = "mustbeeightcharaters"
4856+
skip_final_snapshot = true
4857+
vpc_security_group_ids = [aws_security_group.test.id]
4858+
db_subnet_group_name = aws_db_subnet_group.test.name
4859+
}
4860+
4861+
resource "aws_rds_cluster_instance" "target" {
4862+
identifier = "%[1]s-target-primary"
4863+
cluster_identifier = aws_rds_cluster.target.id
4864+
engine = data.aws_rds_orderable_db_instance.test.engine
4865+
engine_version = data.aws_rds_orderable_db_instance.test.engine_version
4866+
instance_class = data.aws_rds_orderable_db_instance.test.instance_class
4867+
db_subnet_group_name = aws_db_subnet_group.test.name
4868+
}
4869+
`, rName))
4870+
}

internal/service/dms/replication_config.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,16 @@ func ResourceReplicationConfig() *schema.Resource {
113113
Required: true,
114114
ForceNew: true,
115115
},
116+
// "replication_settings" is equivalent to "replication_task_settings" on "aws_dms_replication_task"
117+
// All changes to this field and supporting tests should be mirrored in "aws_dms_replication_task"
116118
"replication_settings": {
117-
Type: schema.TypeString,
118-
Optional: true,
119-
Computed: true,
120-
ValidateFunc: validation.StringIsJSON,
119+
Type: schema.TypeString,
120+
Optional: true,
121+
Computed: true,
122+
ValidateDiagFunc: validation.AllDiag(
123+
validation.ToDiagFunc(validation.StringIsJSON),
124+
validateReplicationSettings,
125+
),
121126
DiffSuppressFunc: suppressEquivalentTaskSettings,
122127
DiffSuppressOnRefresh: true,
123128
},

0 commit comments

Comments
 (0)