Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws_dms_endpoint redis target settings bug fix #26411

Merged
124 changes: 124 additions & 0 deletions internal/service/dms/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,51 @@ func ResourceEndpoint() *schema.Resource {
Optional: true,
ConflictsWith: []string{"secrets_manager_access_role_arn", "secrets_manager_arn"},
},
"redis_settings": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
DiffSuppressFunc: verify.SuppressMissingOptionalConfigurationBlock,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"auth_password": {
Type: schema.TypeString,
Optional: true,
RequiredWith: []string{"auth_type"},
},
"auth_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(dms.RedisAuthTypeValue_Values(), false),
},
"auth_user_name": {
Type: schema.TypeString,
Optional: true,
RequiredWith: []string{"auth_type"},
},
"port": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(0),
},
"server_name": {
Type: schema.TypeString,
Required: true,
},
"ssl_ca_certificate_arn": {
Type: schema.TypeString,
Optional: true,
RequiredWith: []string{"ssl_security_protocol"},
},
"ssl_security_protocol": {
Type: schema.TypeString,
Required: true,
Default: dms.SslSecurityProtocolValueSslEncryption,
ValidateFunc: validation.StringInSlice(dms.SslSecurityProtocolValue_Values(), false),
},
},
},
},
"redshift_settings": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -757,6 +802,8 @@ func resourceEndpointCreate(d *schema.ResourceData, meta interface{}) error {
// Set connection info in top-level namespace as well
expandTopLevelConnectionInfo(d, input)
}
case engineNameRedis:
input.RedisSettings = expandRedisSettings(d.Get("redis_settings").([]interface{})[0].(map[string]interface{}))
case engineNameRedshift:
var settings = &dms.RedshiftSettings{
DatabaseName: aws.String(d.Get("database_name").(string)),
Expand Down Expand Up @@ -1062,6 +1109,11 @@ func resourceEndpointUpdate(d *schema.ResourceData, meta interface{}) error {
expandTopLevelConnectionInfoModify(d, input)
}
}
case engineNameRedis:
if d.HasChanges("redis_settings") {
input.RedisSettings = expandRedisSettings(d.Get("redis_settings").([]interface{})[0].(map[string]interface{}))
input.EngineName = aws.String(engineName)
}
case engineNameRedshift:
if d.HasChanges(
"username", "password", "server_name", "port", "database_name",
Expand Down Expand Up @@ -1223,6 +1275,10 @@ func resourceEndpointCustomizeDiff(_ context.Context, diff *schema.ResourceDiff,
if v, ok := diff.GetOk("mongodb_settings"); !ok || len(v.([]interface{})) == 0 || v.([]interface{})[0] == nil {
return fmt.Errorf("mongodb_settings must be set when engine_name = %q", engineName)
}
case engineNameRedis:
if v, ok := diff.GetOk("redis_settings"); !ok || len(v.([]interface{})) == 0 || v.([]interface{})[0] == nil {
return fmt.Errorf("redis_settings must be set when engine_name = %q", engineName)
}
case engineNameS3:
if v, ok := diff.GetOk("s3_settings"); !ok || len(v.([]interface{})) == 0 || v.([]interface{})[0] == nil {
return fmt.Errorf("s3_settings must be set when engine_name = %q", engineName)
Expand Down Expand Up @@ -1317,6 +1373,10 @@ func resourceEndpointSetState(d *schema.ResourceData, endpoint *dms.Endpoint) er
} else {
flattenTopLevelConnectionInfo(d, endpoint)
}
case engineNameRedis:
if err := d.Set("redis_settings", flattenRedisSettings(endpoint.RedisSettings)); err != nil {
return fmt.Errorf("Error setting redis_settings for DMS: %s", err)
}
case engineNameRedshift:
if endpoint.RedshiftSettings != nil {
d.Set("username", endpoint.RedshiftSettings.Username)
Expand Down Expand Up @@ -1648,6 +1708,70 @@ func flattenMongoDBSettings(settings *dms.MongoDbSettings) []map[string]interfac
return []map[string]interface{}{m}
}

func expandRedisSettings(tfMap map[string]interface{}) *dms.RedisSettings {
if tfMap == nil {
return nil
}

apiObject := &dms.RedisSettings{}

if v, ok := tfMap["auth_password"].(string); ok {
apiObject.AuthPassword = aws.String(v)
}
if v, ok := tfMap["auth_type"].(string); ok {
apiObject.AuthType = aws.String(v)
}
if v, ok := tfMap["auth_user_name"].(string); ok {
apiObject.AuthUserName = aws.String(v)
}
if v, ok := tfMap["port"].(int); ok {
apiObject.Port = aws.Int64(int64(v))
}
if v, ok := tfMap["server_name"].(string); ok {
apiObject.ServerName = aws.String(v)
}
if v, ok := tfMap["ssl_ca_certificate_arn"].(string); ok {
apiObject.SslCaCertificateArn = aws.String(v)
}
if v, ok := tfMap["ssl_security_protocol"].(string); ok {
apiObject.SslSecurityProtocol = aws.String(v)
}

return apiObject
}

func flattenRedisSettings(apiObject *dms.RedisSettings) []map[string]interface{} {
if apiObject == nil {
return []map[string]interface{}{}
}

tfMap := map[string]interface{}{}

if v := apiObject.AuthPassword; v != nil {
tfMap["auth_password"] = aws.StringValue(v)
}
if v := apiObject.AuthType; v != nil {
tfMap["auth_type"] = aws.StringValue(v)
}
if v := apiObject.AuthUserName; v != nil {
tfMap["auth_user_name"] = aws.StringValue(v)
}
if v := apiObject.Port; v != nil {
tfMap["port"] = aws.Int64Value(v)
}
if v := apiObject.ServerName; v != nil {
tfMap["server_name"] = aws.StringValue(v)
}
if v := apiObject.SslCaCertificateArn; v != nil {
tfMap["ssl_ca_certificate_arn"] = aws.StringValue(v)
}
if v := apiObject.SslSecurityProtocol; v != nil {
tfMap["ssl_security_protocol"] = aws.StringValue(v)
}

return []map[string]interface{}{tfMap}
}

func flattenRedshiftSettings(settings *dms.RedshiftSettings) []map[string]interface{} {
if settings == nil {
return []map[string]interface{}{}
Expand Down
123 changes: 123 additions & 0 deletions internal/service/dms/endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,81 @@ func TestAccDMSEndpoint_db2(t *testing.T) {
})
}

func TestAccDMSEndpoint_Redis_basic(t *testing.T) {
resourceName := "aws_dms_endpoint.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, dms.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckEndpointDestroy,
Steps: []resource.TestStep{
{
Config: testAccEndpointConfig_redis(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckEndpointExists(resourceName),
resource.TestCheckResourceAttrSet(resourceName, "endpoint_arn"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.#", "1"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.auth_type", "auth-role"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.auth_user_name", "user"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.port", "6379"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.server_name", "redis_dns"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.ssl_ca_certificate_arn", "arn"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.ssl_security_protocol", "ssl-encryption"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"redis_settings.0.auth_password"},
},
},
})
}

func TestAccDMSEndpoint_Redis_update(t *testing.T) {
resourceName := "aws_dms_endpoint.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, dms.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckEndpointDestroy,
Steps: []resource.TestStep{
{
Config: testAccEndpointConfig_redisUpdate(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckEndpointExists(resourceName),
resource.TestCheckResourceAttrSet(resourceName, "endpoint_arn"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.#", "1"),
),
},
{
Config: testAccEndpointConfig_redisUpdate(rName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckEndpointExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "redis_settings.#", "1"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.auth_type", "auth-role"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.auth_user_name", "user"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.port", "6379"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.server_name", "redis_dns"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.ssl_ca_certificate_arn", "arn"),
resource.TestCheckResourceAttr(resourceName, "redis_settings.0.ssl_security_protocol", "ssl-encryption"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"redis_settings.0.auth_password"},
},
},
})
}

func TestAccDMSEndpoint_Redshift_basic(t *testing.T) {
resourceName := "aws_dms_endpoint.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
Expand Down Expand Up @@ -2918,6 +2993,54 @@ resource "aws_dms_endpoint" "test" {
`, rName)
}

func testAccEndpointConfig_redis(rName string) string {
return fmt.Sprintf(`
resource "aws_dms_endpoint" "test" {
endpoint_id = %[1]q
endpoint_type = "target"
engine_name = "redis"
redis_settings {
auth_password = "password"
auth_type = "auth-role"
auth_user_name = "user"
port = 6379
server_name = "redis_dns"
ssl_ca_certificate_arn = "arn"
ssl_security_protocol = "ssl-encryption"
}
tags = {
Name = %[1]q
Update = "to-update"
Remove = "to-remove"
}
}
`, rName)
}

func testAccEndpointConfig_redisUpdate(rName string) string {
return fmt.Sprintf(`
resource "aws_dms_endpoint" "test" {
endpoint_id = %[1]q
endpoint_type = "target"
engine_name = "redis"
redis_settings {
auth_password = "password"
auth_type = "auth-role"
auth_user_name = "user"
port = 6379
server_name = "redis_dns"
ssl_ca_certificate_arn = "arn"
ssl_security_protocol = "ssl-encryption"
}
tags = {
Name = %[1]q
Update = "to-update"
Remove = "to-remove"
}
}
`, rName)
}

func testAccEndpointConfig_redshiftBase(rName string) string {
return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptInExclude("usw2-az2"), fmt.Sprintf(`
resource "aws_redshift_cluster" "test" {
Expand Down
12 changes: 12 additions & 0 deletions website/docs/r/dms_endpoint.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,18 @@ 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).

### 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).

* `auth_password` - (Optional) The password provided with the auth-role and auth-token options of the AuthType setting for a Redis target endpoint.
* `auth_type` - (Required) The type of authentication to perform when connecting to a Redis target. Options include `none`, `auth-token`, and `auth-role`. The `auth-token` option requires an `auth_password` value to be provided. The `auth-role` option requires `auth_user_name` and `auth_password` values to be provided.
* `auth_user_name` - (Optional) The username provided with the `auth-role` option of the AuthType setting for a Redis target endpoint.
* `server_name` - Fully qualified domain name of the endpoint.
* `port` - Transmission Control Protocol (TCP) port for the endpoint.
* `ssl_ca_certificate_arn` - (Optional) The Amazon Resource Name (ARN) for the certificate authority (CA) that DMS uses to connect to your Redis target endpoint.
* `ssl_security_protocol`- (Required) The plaintext option doesn't provide Transport Layer Security (TLS) encryption for traffic between endpoint and database. Options include `plaintext`, `ssl-encryption`. For `ssl-encryption` please reffer to docs

### redshift_settings

-> Additional information can be found in the [Using Amazon Redshift as a Target for AWS Database Migration Service documentation](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Target.Redshift.html).
Expand Down