From 84e031a9bcf00a7d43f3f864b7dbe91646fdedca Mon Sep 17 00:00:00 2001 From: chris harding Date: Fri, 2 Jun 2017 14:09:23 +0000 Subject: [PATCH] Added support for dynamodb as dms endpoint (with tests). For issue: (https://github.com/hashicorp/terraform/issues/14752) Signed-off-by: stack72 --- aws/resource_aws_dms_endpoint.go | 67 ++++++++--- aws/resource_aws_dms_endpoint_test.go | 167 +++++++++++++++++++++++++- 2 files changed, 211 insertions(+), 23 deletions(-) diff --git a/aws/resource_aws_dms_endpoint.go b/aws/resource_aws_dms_endpoint.go index 586ed9f7c5c..d2d3f3eed8f 100644 --- a/aws/resource_aws_dms_endpoint.go +++ b/aws/resource_aws_dms_endpoint.go @@ -43,6 +43,10 @@ func resourceAwsDmsEndpoint() *schema.Resource { ForceNew: true, ValidateFunc: validateDmsEndpointId, }, + "service_access_role": { + Type: schema.TypeString, + Optional: true, + }, "endpoint_type": { Type: schema.TypeString, Required: true, @@ -58,6 +62,7 @@ func resourceAwsDmsEndpoint() *schema.Resource { "mysql", "oracle", "postgres", + "dynamodb", "mariadb", "aurora", "redshift", @@ -79,16 +84,16 @@ func resourceAwsDmsEndpoint() *schema.Resource { }, "password": { Type: schema.TypeString, - Required: true, + Optional: true, Sensitive: true, }, "port": { Type: schema.TypeInt, - Required: true, + Optional: true, }, "server_name": { Type: schema.TypeString, - Required: true, + Optional: true, }, "ssl_mode": { Type: schema.TypeString, @@ -107,7 +112,7 @@ func resourceAwsDmsEndpoint() *schema.Resource { }, "username": { Type: schema.TypeString, - Required: true, + Optional: true, }, }, } @@ -120,22 +125,31 @@ func resourceAwsDmsEndpointCreate(d *schema.ResourceData, meta interface{}) erro EndpointIdentifier: aws.String(d.Get("endpoint_id").(string)), EndpointType: aws.String(d.Get("endpoint_type").(string)), EngineName: aws.String(d.Get("engine_name").(string)), - Password: aws.String(d.Get("password").(string)), - Port: aws.Int64(int64(d.Get("port").(int))), - ServerName: aws.String(d.Get("server_name").(string)), Tags: dmsTagsFromMap(d.Get("tags").(map[string]interface{})), - Username: aws.String(d.Get("username").(string)), } - if v, ok := d.GetOk("database_name"); ok { - request.DatabaseName = aws.String(v.(string)) + // if dynamodb then add required params + if d.Get("engine_name").(string) == "dynamodb" { + request.DynamoDbSettings = &dms.DynamoDbSettings{ + ServiceAccessRoleArn: aws.String(d.Get("service_access_role").(string)), + } + } else { + request.Password = aws.String(d.Get("password").(string)) + request.Port = aws.Int64(int64(d.Get("port").(int))) + request.ServerName = aws.String(d.Get("server_name").(string)) + request.Username = aws.String(d.Get("username").(string)) + + if v, ok := d.GetOk("database_name"); ok { + request.DatabaseName = aws.String(v.(string)) + } + if v, ok := d.GetOk("extra_connection_attributes"); ok { + request.ExtraConnectionAttributes = aws.String(v.(string)) + } } + if v, ok := d.GetOk("certificate_arn"); ok { request.CertificateArn = aws.String(v.(string)) } - if v, ok := d.GetOk("extra_connection_attributes"); ok { - request.ExtraConnectionAttributes = aws.String(v.(string)) - } if v, ok := d.GetOk("kms_key_arn"); ok { request.KmsKeyId = aws.String(v.(string)) } @@ -208,6 +222,13 @@ func resourceAwsDmsEndpointUpdate(d *schema.ResourceData, meta interface{}) erro hasChanges = true } + if d.HasChange("service_access_role") { + request.DynamoDbSettings = &dms.DynamoDbSettings{ + ServiceAccessRoleArn: aws.String(d.Get("service_access_role").(string)), + } + hasChanges = true + } + if d.HasChange("endpoint_type") { request.EndpointType = aws.String(d.Get("endpoint_type").(string)) hasChanges = true @@ -290,18 +311,28 @@ func resourceAwsDmsEndpointSetState(d *schema.ResourceData, endpoint *dms.Endpoi d.SetId(*endpoint.EndpointIdentifier) d.Set("certificate_arn", endpoint.CertificateArn) - d.Set("database_name", endpoint.DatabaseName) d.Set("endpoint_arn", endpoint.EndpointArn) d.Set("endpoint_id", endpoint.EndpointIdentifier) // For some reason the AWS API only accepts lowercase type but returns it as uppercase d.Set("endpoint_type", strings.ToLower(*endpoint.EndpointType)) d.Set("engine_name", endpoint.EngineName) - d.Set("extra_connection_attributes", endpoint.ExtraConnectionAttributes) + + if *endpoint.EngineName == "dynamodb" { + if endpoint.DynamoDbSettings != nil { + d.Set("service_access_role", endpoint.DynamoDbSettings.ServiceAccessRoleArn) + } else { + d.Set("service_access_role", "") + } + } else { + d.Set("database_name", endpoint.DatabaseName) + d.Set("extra_connection_attributes", endpoint.ExtraConnectionAttributes) + d.Set("port", endpoint.Port) + d.Set("server_name", endpoint.ServerName) + d.Set("username", endpoint.Username) + } + d.Set("kms_key_arn", endpoint.KmsKeyId) - d.Set("port", endpoint.Port) - d.Set("server_name", endpoint.ServerName) d.Set("ssl_mode", endpoint.SslMode) - d.Set("username", endpoint.Username) return nil } diff --git a/aws/resource_aws_dms_endpoint_test.go b/aws/resource_aws_dms_endpoint_test.go index 59c3d87c77b..dbae275ddd0 100644 --- a/aws/resource_aws_dms_endpoint_test.go +++ b/aws/resource_aws_dms_endpoint_test.go @@ -13,7 +13,7 @@ import ( func TestAccAwsDmsEndpointBasic(t *testing.T) { resourceName := "aws_dms_endpoint.dms_endpoint" - randId := acctest.RandString(8) + randId := acctest.RandString(8) + "-basic" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -21,7 +21,7 @@ func TestAccAwsDmsEndpointBasic(t *testing.T) { CheckDestroy: dmsEndpointDestroy, Steps: []resource.TestStep{ { - Config: dmsEndpointConfig(randId), + Config: dmsEndpointBasicConfig(randId), Check: resource.ComposeTestCheckFunc( checkDmsEndpointExists(resourceName), resource.TestCheckResourceAttrSet(resourceName, "endpoint_arn"), @@ -34,7 +34,7 @@ func TestAccAwsDmsEndpointBasic(t *testing.T) { ImportStateVerifyIgnore: []string{"password"}, }, { - Config: dmsEndpointConfigUpdate(randId), + Config: dmsEndpointBasicConfigUpdate(randId), Check: resource.ComposeTestCheckFunc( checkDmsEndpointExists(resourceName), resource.TestCheckResourceAttr(resourceName, "database_name", "tf-test-dms-db-updated"), @@ -50,6 +50,40 @@ func TestAccAwsDmsEndpointBasic(t *testing.T) { }) } +func TestAccAwsDmsEndpointDynamoDb(t *testing.T) { + resourceName := "aws_dms_endpoint.dms_endpoint" + randId := acctest.RandString(8) + "-dynamodb" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: dmsEndpointDestroy, + Steps: []resource.TestStep{ + { + Config: dmsEndpointDynamoDbConfig(randId), + Check: resource.ComposeTestCheckFunc( + checkDmsEndpointExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "endpoint_arn"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"password"}, + }, + { + Config: dmsEndpointDynamoDbConfigUpdate(randId), + Check: resource.ComposeTestCheckFunc( + checkDmsEndpointExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "ssl_mode", "none"), + resource.TestCheckResourceAttr(resourceName, "server_name", "tftestupdate"), + ), + }, + }, + }) +} + func dmsEndpointDestroy(s *terraform.State) error { for _, rs := range s.RootModule().Resources { if rs.Type != "aws_dms_endpoint" { @@ -98,7 +132,7 @@ func checkDmsEndpointExists(n string) resource.TestCheckFunc { } } -func dmsEndpointConfig(randId string) string { +func dmsEndpointBasicConfig(randId string) string { return fmt.Sprintf(` resource "aws_dms_endpoint" "dms_endpoint" { database_name = "tf-test-dms-db" @@ -120,7 +154,7 @@ resource "aws_dms_endpoint" "dms_endpoint" { `, randId) } -func dmsEndpointConfigUpdate(randId string) string { +func dmsEndpointBasicConfigUpdate(randId string) string { return fmt.Sprintf(` resource "aws_dms_endpoint" "dms_endpoint" { database_name = "tf-test-dms-db-updated" @@ -141,3 +175,126 @@ resource "aws_dms_endpoint" "dms_endpoint" { } `, randId) } + +func dmsEndpointDynamoDbConfig(randId string) string { + return fmt.Sprintf(` +resource "aws_dms_endpoint" "dms_endpoint" { + endpoint_id = "tf-test-dms-endpoint-%[1]s" + endpoint_type = "target" + engine_name = "dynamodb" + server_name = "tftest" + service_access_role = "${aws_iam_role.iam_role.arn}" + ssl_mode = "none" + tags { + Name = "tf-test-dynamodb-endpoint-%[1]s" + Update = "to-update" + Remove = "to-remove" + } +} +resource "aws_iam_role" "iam_role" { + name = "tf-test-iam-dynamodb-role-%[1]s" + + assume_role_policy = <