provider/aws: Add AWS DMS (data migration service) resources (#11122)
* Add aws dms vendoring * Add aws dms endpoint resource * Add aws dms replication instance resource * Add aws dms replication subnet group resource * Add aws dms replication task resource * Fix aws dms resource go vet errors * Review fixes: Add id validators for all resources. Add validator for endpoint engine_name. * Add aws dms resources to importability list * Review fixes: Add aws dms iam role dependencies to test cases * Review fixes: Adjustments for handling input values * Add aws dms replication subnet group tagging * Fix aws dms subnet group doesn't use standard error for resource not found * Missed update of aws dms vendored version * Add aws dms certificate resource * Update aws dms resources to force new for immutable attributes * Fix tests failing on subnet deletion by adding explicit dependencies. Combine import tests with basic tests to cut down runtime.
This commit is contained in:
parent
b30ef0f58d
commit
be56c7d2f6
|
@ -26,6 +26,7 @@ import (
|
|||
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
|
||||
"github.com/aws/aws-sdk-go/service/codecommit"
|
||||
"github.com/aws/aws-sdk-go/service/codedeploy"
|
||||
"github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/aws/aws-sdk-go/service/directoryservice"
|
||||
"github.com/aws/aws-sdk-go/service/dynamodb"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
|
@ -106,6 +107,7 @@ type AWSClient struct {
|
|||
cloudwatchconn *cloudwatch.CloudWatch
|
||||
cloudwatchlogsconn *cloudwatchlogs.CloudWatchLogs
|
||||
cloudwatcheventsconn *cloudwatchevents.CloudWatchEvents
|
||||
dmsconn *databasemigrationservice.DatabaseMigrationService
|
||||
dsconn *directoryservice.DirectoryService
|
||||
dynamodbconn *dynamodb.DynamoDB
|
||||
ec2conn *ec2.EC2
|
||||
|
@ -276,6 +278,7 @@ func (c *Config) Client() (interface{}, error) {
|
|||
client.cloudwatchlogsconn = cloudwatchlogs.New(sess)
|
||||
client.codecommitconn = codecommit.New(sess)
|
||||
client.codedeployconn = codedeploy.New(sess)
|
||||
client.dmsconn = databasemigrationservice.New(sess)
|
||||
client.dsconn = directoryservice.New(sess)
|
||||
client.dynamodbconn = dynamodb.New(dynamoSess)
|
||||
client.ec2conn = ec2.New(awsEc2Sess)
|
||||
|
|
|
@ -246,6 +246,11 @@ func Provider() terraform.ResourceProvider {
|
|||
"aws_db_security_group": resourceAwsDbSecurityGroup(),
|
||||
"aws_db_subnet_group": resourceAwsDbSubnetGroup(),
|
||||
"aws_directory_service_directory": resourceAwsDirectoryServiceDirectory(),
|
||||
"aws_dms_certificate": resourceAwsDmsCertificate(),
|
||||
"aws_dms_endpoint": resourceAwsDmsEndpoint(),
|
||||
"aws_dms_replication_instance": resourceAwsDmsReplicationInstance(),
|
||||
"aws_dms_replication_subnet_group": resourceAwsDmsReplicationSubnetGroup(),
|
||||
"aws_dms_replication_task": resourceAwsDmsReplicationTask(),
|
||||
"aws_dynamodb_table": resourceAwsDynamoDbTable(),
|
||||
"aws_ebs_snapshot": resourceAwsEbsSnapshot(),
|
||||
"aws_ebs_volume": resourceAwsEbsVolume(),
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func resourceAwsDmsCertificate() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsDmsCertificateCreate,
|
||||
Read: resourceAwsDmsCertificateRead,
|
||||
Delete: resourceAwsDmsCertificateDelete,
|
||||
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"certificate_arn": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"certificate_id": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateDmsCertificateId,
|
||||
},
|
||||
"certificate_pem": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"certificate_wallet": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceAwsDmsCertificateCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.ImportCertificateInput{
|
||||
CertificateIdentifier: aws.String(d.Get("certificate_id").(string)),
|
||||
}
|
||||
|
||||
pem, pemSet := d.GetOk("certificate_pem")
|
||||
wallet, walletSet := d.GetOk("certificate_wallet")
|
||||
|
||||
if !pemSet && !walletSet {
|
||||
return fmt.Errorf("Must set either certificate_pem and certificate_wallet.")
|
||||
}
|
||||
if pemSet && walletSet {
|
||||
return fmt.Errorf("Cannot set both certificate_pem and certificate_wallet.")
|
||||
}
|
||||
|
||||
if pemSet {
|
||||
request.CertificatePem = aws.String(pem.(string))
|
||||
}
|
||||
if walletSet {
|
||||
request.CertificateWallet = []byte(wallet.(string))
|
||||
}
|
||||
|
||||
log.Println("[DEBUG] DMS import certificate:", request)
|
||||
|
||||
_, err := conn.ImportCertificate(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(d.Get("certificate_id").(string))
|
||||
return resourceAwsDmsCertificateRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsDmsCertificateRead(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
response, err := conn.DescribeCertificates(&dms.DescribeCertificatesInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("certificate-id"),
|
||||
Values: []*string{aws.String(d.Id())}, // Must use d.Id() to work with import.
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
if dmserr, ok := err.(awserr.Error); ok && dmserr.Code() == "ResourceNotFoundFault" {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceAwsDmsCertificateSetState(d, response.Certificates[0])
|
||||
}
|
||||
|
||||
func resourceAwsDmsCertificateDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.DeleteCertificateInput{
|
||||
CertificateArn: aws.String(d.Get("certificate_arn").(string)),
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] DMS delete certificate: %#v", request)
|
||||
|
||||
_, err := conn.DeleteCertificate(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsCertificateSetState(d *schema.ResourceData, cert *dms.Certificate) error {
|
||||
d.SetId(*cert.CertificateIdentifier)
|
||||
|
||||
d.Set("certificate_id", cert.CertificateIdentifier)
|
||||
d.Set("certificate_arn", cert.CertificateArn)
|
||||
|
||||
if cert.CertificatePem != nil && *cert.CertificatePem != "" {
|
||||
d.Set("certificate_pem", cert.CertificatePem)
|
||||
}
|
||||
if cert.CertificateWallet != nil && len(cert.CertificateWallet) == 0 {
|
||||
d.Set("certificate_wallet", cert.CertificateWallet)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccAwsDmsCertificateBasic(t *testing.T) {
|
||||
resourceName := "aws_dms_certificate.dms_certificate"
|
||||
randId := acctest.RandString(8)
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: dmsCertificateDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: dmsCertificateConfig(randId),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
checkDmsCertificateExists(resourceName),
|
||||
resource.TestCheckResourceAttrSet(resourceName, "certificate_arn"),
|
||||
),
|
||||
},
|
||||
{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func dmsCertificateDestroy(s *terraform.State) error {
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "aws_dms_certificate" {
|
||||
continue
|
||||
}
|
||||
|
||||
err := checkDmsCertificateExists(rs.Primary.ID)
|
||||
if err == nil {
|
||||
return fmt.Errorf("Found a certificate that was not destroyed: %s", rs.Primary.ID)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkDmsCertificateExists(n string) resource.TestCheckFunc {
|
||||
providers := []*schema.Provider{testAccProvider}
|
||||
return checkDmsCertificateExistsWithProviders(n, &providers)
|
||||
}
|
||||
|
||||
func checkDmsCertificateExistsWithProviders(n string, providers *[]*schema.Provider) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No ID is set")
|
||||
}
|
||||
for _, provider := range *providers {
|
||||
// Ignore if Meta is empty, this can happen for validation providers
|
||||
if provider.Meta() == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
conn := provider.Meta().(*AWSClient).dmsconn
|
||||
_, err := conn.DescribeCertificates(&dms.DescribeCertificatesInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("certificate-id"),
|
||||
Values: []*string{aws.String(rs.Primary.ID)},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("DMS certificate error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("DMS certificate not found")
|
||||
}
|
||||
}
|
||||
|
||||
func dmsCertificateConfig(randId string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_dms_certificate" "dms_certificate" {
|
||||
certificate_id = "tf-test-dms-certificate-%[1]s"
|
||||
certificate_pem = "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIJAJ58TJVjU7G1MA0GCSqGSIb3DQEBBQUAMFExCzAJBgNV\nBAYTAlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRAwDgYD\nVQQKEwdDaGFydGVyMQwwCgYDVQQLEwNDU0UwHhcNMTcwMTMwMTkyMDA4WhcNMjYx\nMjA5MTkyMDA4WjBRMQswCQYDVQQGEwJVUzERMA8GA1UECBMIQ29sb3JhZG8xDzAN\nBgNVBAcTBkRlbnZlcjEQMA4GA1UEChMHQ2hhcnRlcjEMMAoGA1UECxMDQ1NFMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv6dq6VLIImlAaTrckb5w3X6J\nWP7EGz2ChGAXlkEYto6dPCba0v5+f+8UlMOpeB25XGoai7gdItqNWVFpYsgmndx3\nvTad3ukO1zeElKtw5oHPH2plOaiv/gVJaDa9NTeINj0EtGZs74fCOclAzGFX5vBc\nb08ESWBceRgGjGv3nlij4JzHfqTkCKQz6P6pBivQBfk62rcOkkH5rKoaGltRHROS\nMbkwOhu2hN0KmSYTXRvts0LXnZU4N0l2ms39gmr7UNNNlKYINL2JoTs9dNBc7APD\ndZvlEHd+/FjcLCI8hC3t4g4AbfW0okIBCNG0+oVjqGb2DeONSJKsThahXt89MQID\nAQABo4G0MIGxMB0GA1UdDgQWBBQKq8JxjY1GmeZXJjfOMfW0kBIzPDCBgQYDVR0j\nBHoweIAUCqvCcY2NRpnmVyY3zjH1tJASMzyhVaRTMFExCzAJBgNVBAYTAlVTMREw\nDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRAwDgYDVQQKEwdDaGFy\ndGVyMQwwCgYDVQQLEwNDU0WCCQCefEyVY1OxtTAMBgNVHRMEBTADAQH/MA0GCSqG\nSIb3DQEBBQUAA4IBAQAWifoMk5kbv+yuWXvFwHiB4dWUUmMlUlPU/E300yVTRl58\np6DfOgJs7MMftd1KeWqTO+uW134QlTt7+jwI8Jq0uyKCu/O2kJhVtH/Ryog14tGl\n+wLcuIPLbwJI9CwZX4WMBrq4DnYss+6F47i8NCc+Z3MAiG4vtq9ytBmaod0dj2bI\ng4/Lac0e00dql9RnqENh1+dF0V+QgTJCoPkMqDNAlSB8vOodBW81UAb2z12t+IFi\n3X9J3WtCK2+T5brXL6itzewWJ2ALvX3QpmZx7fMHJ3tE+SjjyivE1BbOlzYHx83t\nTeYnm7pS9un7A/UzTDHbs7hPUezLek+H3xTPAnnq\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
`, randId)
|
||||
}
|
|
@ -0,0 +1,343 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/private/waiter"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/helper/validation"
|
||||
)
|
||||
|
||||
func resourceAwsDmsEndpoint() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsDmsEndpointCreate,
|
||||
Read: resourceAwsDmsEndpointRead,
|
||||
Update: resourceAwsDmsEndpointUpdate,
|
||||
Delete: resourceAwsDmsEndpointDelete,
|
||||
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"certificate_arn": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ValidateFunc: validateArn,
|
||||
},
|
||||
"database_name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"endpoint_arn": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"endpoint_id": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateDmsEndpointId,
|
||||
},
|
||||
"endpoint_type": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: validation.StringInSlice([]string{
|
||||
"source",
|
||||
"target",
|
||||
}, false),
|
||||
},
|
||||
"engine_name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: validation.StringInSlice([]string{
|
||||
"mysql",
|
||||
"oracle",
|
||||
"postgres",
|
||||
"mariadb",
|
||||
"aurora",
|
||||
"redshift",
|
||||
"sybase",
|
||||
"sqlserver",
|
||||
}, false),
|
||||
},
|
||||
"extra_connection_attributes": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
},
|
||||
"kms_key_arn": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateArn,
|
||||
},
|
||||
"password": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"port": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"server_name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"ssl_mode": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ValidateFunc: validation.StringInSlice([]string{
|
||||
"none",
|
||||
"require",
|
||||
"verify-ca",
|
||||
"verify-full",
|
||||
}, false),
|
||||
},
|
||||
"tags": {
|
||||
Type: schema.TypeMap,
|
||||
Optional: true,
|
||||
},
|
||||
"username": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceAwsDmsEndpointCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.CreateEndpointInput{
|
||||
DatabaseName: aws.String(d.Get("database_name").(string)),
|
||||
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("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))
|
||||
}
|
||||
if v, ok := d.GetOk("ssl_mode"); ok {
|
||||
request.SslMode = aws.String(v.(string))
|
||||
}
|
||||
|
||||
log.Println("[DEBUG] DMS create endpoint:", request)
|
||||
|
||||
_, err := conn.CreateEndpoint(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(d.Get("endpoint_id").(string))
|
||||
return resourceAwsDmsEndpointRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsDmsEndpointRead(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
response, err := conn.DescribeEndpoints(&dms.DescribeEndpointsInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("endpoint-id"),
|
||||
Values: []*string{aws.String(d.Id())}, // Must use d.Id() to work with import.
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
if dmserr, ok := err.(awserr.Error); ok && dmserr.Code() == "ResourceNotFoundFault" {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
err = resourceAwsDmsEndpointSetState(d, response.Endpoints[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tagsResp, err := conn.ListTagsForResource(&dms.ListTagsForResourceInput{
|
||||
ResourceArn: aws.String(d.Get("endpoint_arn").(string)),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Set("tags", dmsTagsToMap(tagsResp.TagList))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsEndpointUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.ModifyEndpointInput{
|
||||
EndpointArn: aws.String(d.Get("endpoint_arn").(string)),
|
||||
}
|
||||
hasChanges := false
|
||||
|
||||
if d.HasChange("certificate_arn") {
|
||||
request.CertificateArn = aws.String(d.Get("certificate_arn").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("database_name") {
|
||||
request.DatabaseName = aws.String(d.Get("database_name").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("endpoint_type") {
|
||||
request.EndpointType = aws.String(d.Get("endpoint_type").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("engine_name") {
|
||||
request.EngineName = aws.String(d.Get("engine_name").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("extra_connection_attributes") {
|
||||
request.ExtraConnectionAttributes = aws.String(d.Get("extra_connection_attributes").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("password") {
|
||||
request.Password = aws.String(d.Get("password").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("port") {
|
||||
request.Port = aws.Int64(int64(d.Get("port").(int)))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("server_name") {
|
||||
request.ServerName = aws.String(d.Get("server_name").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("ssl_mode") {
|
||||
request.SslMode = aws.String(d.Get("ssl_mode").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("username") {
|
||||
request.Username = aws.String(d.Get("username").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("tags") {
|
||||
err := dmsSetTags(d.Get("endpoint_arn").(string), d, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if hasChanges {
|
||||
log.Println("[DEBUG] DMS update endpoint:", request)
|
||||
|
||||
_, err := conn.ModifyEndpoint(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceAwsDmsEndpointRead(d, meta)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsEndpointDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.DeleteEndpointInput{
|
||||
EndpointArn: aws.String(d.Get("endpoint_arn").(string)),
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] DMS delete endpoint: %#v", request)
|
||||
|
||||
_, err := conn.DeleteEndpoint(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
waitErr := waitForEndpointDelete(conn, d.Get("endpoint_id").(string), 30, 20)
|
||||
if waitErr != nil {
|
||||
return waitErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsEndpointSetState(d *schema.ResourceData, endpoint *dms.Endpoint) error {
|
||||
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)
|
||||
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
|
||||
}
|
||||
|
||||
func waitForEndpointDelete(client *dms.DatabaseMigrationService, endpointId string, delay int, maxAttempts int) error {
|
||||
input := &dms.DescribeEndpointsInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("endpoint-id"),
|
||||
Values: []*string{aws.String(endpointId)},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
config := waiter.Config{
|
||||
Operation: "DescribeEndpoints",
|
||||
Delay: delay,
|
||||
MaxAttempts: maxAttempts,
|
||||
Acceptors: []waiter.WaitAcceptor{
|
||||
{
|
||||
State: "success",
|
||||
Matcher: "path",
|
||||
Argument: "length(Endpoints[]) > `0`",
|
||||
Expected: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
w := waiter.Waiter{
|
||||
Client: client,
|
||||
Input: input,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
return w.Wait()
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccAwsDmsEndpointBasic(t *testing.T) {
|
||||
resourceName := "aws_dms_endpoint.dms_endpoint"
|
||||
randId := acctest.RandString(8)
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: dmsEndpointDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: dmsEndpointConfig(randId),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
checkDmsEndpointExists(resourceName),
|
||||
resource.TestCheckResourceAttrSet(resourceName, "endpoint_arn"),
|
||||
),
|
||||
},
|
||||
{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
ImportStateVerifyIgnore: []string{"password"},
|
||||
},
|
||||
{
|
||||
Config: dmsEndpointConfigUpdate(randId),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
checkDmsEndpointExists(resourceName),
|
||||
resource.TestCheckResourceAttr(resourceName, "database_name", "tf-test-dms-db-updated"),
|
||||
resource.TestCheckResourceAttr(resourceName, "extra_connection_attributes", "extra"),
|
||||
resource.TestCheckResourceAttr(resourceName, "password", "tftestupdate"),
|
||||
resource.TestCheckResourceAttr(resourceName, "port", "3303"),
|
||||
resource.TestCheckResourceAttr(resourceName, "ssl_mode", "none"),
|
||||
resource.TestCheckResourceAttr(resourceName, "server_name", "tftestupdate"),
|
||||
resource.TestCheckResourceAttr(resourceName, "username", "tftestupdate"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func dmsEndpointDestroy(s *terraform.State) error {
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "aws_dms_endpoint" {
|
||||
continue
|
||||
}
|
||||
|
||||
err := checkDmsEndpointExists(rs.Primary.ID)
|
||||
if err == nil {
|
||||
return fmt.Errorf("Found an endpoint that was not destroyed: %s", rs.Primary.ID)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkDmsEndpointExists(n string) resource.TestCheckFunc {
|
||||
providers := []*schema.Provider{testAccProvider}
|
||||
return checkDmsEndpointExistsWithProviders(n, &providers)
|
||||
}
|
||||
|
||||
func checkDmsEndpointExistsWithProviders(n string, providers *[]*schema.Provider) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No ID is set")
|
||||
}
|
||||
for _, provider := range *providers {
|
||||
// Ignore if Meta is empty, this can happen for validation providers
|
||||
if provider.Meta() == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
conn := provider.Meta().(*AWSClient).dmsconn
|
||||
_, err := conn.DescribeEndpoints(&dms.DescribeEndpointsInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("endpoint-id"),
|
||||
Values: []*string{aws.String(rs.Primary.ID)},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("DMS endpoint error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("DMS endpoint not found")
|
||||
}
|
||||
}
|
||||
|
||||
func dmsEndpointConfig(randId string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_dms_endpoint" "dms_endpoint" {
|
||||
database_name = "tf-test-dms-db"
|
||||
endpoint_id = "tf-test-dms-endpoint-%[1]s"
|
||||
endpoint_type = "source"
|
||||
engine_name = "aurora"
|
||||
extra_connection_attributes = ""
|
||||
password = "tftest"
|
||||
port = 3306
|
||||
server_name = "tftest"
|
||||
ssl_mode = "none"
|
||||
tags {
|
||||
Name = "tf-test-dms-endpoint-%[1]s"
|
||||
Update = "to-update"
|
||||
Remove = "to-remove"
|
||||
}
|
||||
username = "tftest"
|
||||
}
|
||||
`, randId)
|
||||
}
|
||||
|
||||
func dmsEndpointConfigUpdate(randId string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_dms_endpoint" "dms_endpoint" {
|
||||
database_name = "tf-test-dms-db-updated"
|
||||
endpoint_id = "tf-test-dms-endpoint-%[1]s"
|
||||
endpoint_type = "source"
|
||||
engine_name = "aurora"
|
||||
extra_connection_attributes = "extra"
|
||||
password = "tftestupdate"
|
||||
port = 3303
|
||||
server_name = "tftestupdate"
|
||||
ssl_mode = "none"
|
||||
tags {
|
||||
Name = "tf-test-dms-endpoint-%[1]s"
|
||||
Update = "updated"
|
||||
Add = "added"
|
||||
}
|
||||
username = "tftestupdate"
|
||||
}
|
||||
`, randId)
|
||||
}
|
|
@ -0,0 +1,422 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/private/waiter"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func resourceAwsDmsReplicationInstance() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsDmsReplicationInstanceCreate,
|
||||
Read: resourceAwsDmsReplicationInstanceRead,
|
||||
Update: resourceAwsDmsReplicationInstanceUpdate,
|
||||
Delete: resourceAwsDmsReplicationInstanceDelete,
|
||||
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"allocated_storage": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ValidateFunc: validateIntegerInRange(5, 6144),
|
||||
},
|
||||
"apply_immediately": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
},
|
||||
"auto_minor_version_upgrade": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
},
|
||||
"availability_zone": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"engine_version": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
},
|
||||
"kms_key_arn": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateArn,
|
||||
},
|
||||
"multi_az": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
},
|
||||
"preferred_maintenance_window": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ValidateFunc: validateOnceAWeekWindowFormat,
|
||||
},
|
||||
"publicly_accessible": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"replication_instance_arn": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"replication_instance_class": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
// Valid Values: dms.t2.micro | dms.t2.small | dms.t2.medium | dms.t2.large | dms.c4.large |
|
||||
// dms.c4.xlarge | dms.c4.2xlarge | dms.c4.4xlarge
|
||||
},
|
||||
"replication_instance_id": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateDmsReplicationInstanceId,
|
||||
},
|
||||
"replication_instance_private_ips": {
|
||||
Type: schema.TypeList,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Computed: true,
|
||||
},
|
||||
"replication_instance_public_ips": {
|
||||
Type: schema.TypeList,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Computed: true,
|
||||
},
|
||||
"replication_subnet_group_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"tags": {
|
||||
Type: schema.TypeMap,
|
||||
Optional: true,
|
||||
},
|
||||
"vpc_security_group_ids": {
|
||||
Type: schema.TypeSet,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Set: schema.HashString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationInstanceCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.CreateReplicationInstanceInput{
|
||||
AutoMinorVersionUpgrade: aws.Bool(d.Get("auto_minor_version_upgrade").(bool)),
|
||||
PubliclyAccessible: aws.Bool(d.Get("publicly_accessible").(bool)),
|
||||
ReplicationInstanceClass: aws.String(d.Get("replication_instance_class").(string)),
|
||||
ReplicationInstanceIdentifier: aws.String(d.Get("replication_instance_id").(string)),
|
||||
Tags: dmsTagsFromMap(d.Get("tags").(map[string]interface{})),
|
||||
}
|
||||
|
||||
// WARNING: GetOk returns the zero value for the type if the key is omitted in config. This means for optional
|
||||
// keys that the zero value is valid we cannot know if the zero value was in the config and cannot allow the API
|
||||
// to set the default value. See GitHub Issue #5694 https://github.com/hashicorp/terraform/issues/5694
|
||||
|
||||
if v, ok := d.GetOk("allocated_storage"); ok {
|
||||
request.AllocatedStorage = aws.Int64(int64(v.(int)))
|
||||
}
|
||||
if v, ok := d.GetOk("engine_version"); ok {
|
||||
request.EngineVersion = aws.String(v.(string))
|
||||
}
|
||||
if v, ok := d.GetOk("kms_key_arn"); ok {
|
||||
request.KmsKeyId = aws.String(v.(string))
|
||||
}
|
||||
if v, ok := d.GetOk("preferred_maintenance_window"); ok {
|
||||
request.PreferredMaintenanceWindow = aws.String(v.(string))
|
||||
}
|
||||
if v, ok := d.GetOk("replication_subnet_group_id"); ok {
|
||||
request.ReplicationSubnetGroupIdentifier = aws.String(v.(string))
|
||||
}
|
||||
if v, ok := d.GetOk("vpc_security_group_ids"); ok {
|
||||
request.VpcSecurityGroupIds = expandStringList(v.(*schema.Set).List())
|
||||
}
|
||||
|
||||
az, azSet := d.GetOk("availability_zone")
|
||||
if azSet {
|
||||
request.AvailabilityZone = aws.String(az.(string))
|
||||
}
|
||||
|
||||
if multiAz, ok := d.GetOk("multi_az"); ok {
|
||||
request.MultiAZ = aws.Bool(multiAz.(bool))
|
||||
|
||||
if multiAz.(bool) && azSet {
|
||||
return fmt.Errorf("Cannot set availability_zone if multi_az is set to true")
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("[DEBUG] DMS create replication instance:", request)
|
||||
|
||||
_, err := conn.CreateReplicationInstance(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = waitForInstanceCreated(conn, d.Get("replication_instance_id").(string), 30, 20)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(d.Get("replication_instance_id").(string))
|
||||
return resourceAwsDmsReplicationInstanceRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationInstanceRead(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
response, err := conn.DescribeReplicationInstances(&dms.DescribeReplicationInstancesInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("replication-instance-id"),
|
||||
Values: []*string{aws.String(d.Id())}, // Must use d.Id() to work with import.
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
if dmserr, ok := err.(awserr.Error); ok && dmserr.Code() == "ResourceNotFoundFault" {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
err = resourceAwsDmsReplicationInstanceSetState(d, response.ReplicationInstances[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tagsResp, err := conn.ListTagsForResource(&dms.ListTagsForResourceInput{
|
||||
ResourceArn: aws.String(d.Get("replication_instance_arn").(string)),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Set("tags", dmsTagsToMap(tagsResp.TagList))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
request := &dms.ModifyReplicationInstanceInput{
|
||||
ApplyImmediately: aws.Bool(d.Get("apply_immediately").(bool)),
|
||||
ReplicationInstanceArn: aws.String(d.Get("replication_instance_arn").(string)),
|
||||
}
|
||||
hasChanges := false
|
||||
|
||||
if d.HasChange("auto_minor_version_upgrade") {
|
||||
request.AutoMinorVersionUpgrade = aws.Bool(d.Get("auto_minor_version_upgrade").(bool))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("allocated_storage") {
|
||||
if v, ok := d.GetOk("allocated_storage"); ok {
|
||||
request.AllocatedStorage = aws.Int64(int64(v.(int)))
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange("engine_version") {
|
||||
if v, ok := d.GetOk("engine_version"); ok {
|
||||
request.ReplicationInstanceClass = aws.String(v.(string))
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange("multi_az") {
|
||||
if v, ok := d.GetOk("multi_az"); ok {
|
||||
request.MultiAZ = aws.Bool(v.(bool))
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange("preferred_maintenance_window") {
|
||||
if v, ok := d.GetOk("preferred_maintenance_window"); ok {
|
||||
request.PreferredMaintenanceWindow = aws.String(v.(string))
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange("replication_instance_class") {
|
||||
if v, ok := d.GetOk("replication_instance_class"); ok {
|
||||
request.ReplicationInstanceClass = aws.String(v.(string))
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange("vpc_security_group_ids") {
|
||||
if v, ok := d.GetOk("vpc_security_group_ids"); ok {
|
||||
request.VpcSecurityGroupIds = expandStringList(v.(*schema.Set).List())
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange("tags") {
|
||||
err := dmsSetTags(d.Get("replication_instance_arn").(string), d, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if hasChanges {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
_, err := conn.ModifyReplicationInstance(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceAwsDmsReplicationInstanceRead(d, meta)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationInstanceDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.DeleteReplicationInstanceInput{
|
||||
ReplicationInstanceArn: aws.String(d.Get("replication_instance_arn").(string)),
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] DMS delete replication instance: %#v", request)
|
||||
|
||||
_, err := conn.DeleteReplicationInstance(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
waitErr := waitForInstanceDeleted(conn, d.Get("replication_instance_id").(string), 30, 20)
|
||||
if waitErr != nil {
|
||||
return waitErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationInstanceSetState(d *schema.ResourceData, instance *dms.ReplicationInstance) error {
|
||||
d.SetId(*instance.ReplicationInstanceIdentifier)
|
||||
|
||||
d.Set("replication_instance_id", instance.ReplicationInstanceIdentifier)
|
||||
d.Set("allocated_storage", instance.AllocatedStorage)
|
||||
d.Set("auto_minor_version_upgrade", instance.AutoMinorVersionUpgrade)
|
||||
d.Set("availability_zone", instance.AvailabilityZone)
|
||||
d.Set("engine_version", instance.EngineVersion)
|
||||
d.Set("kms_key_arn", instance.KmsKeyId)
|
||||
d.Set("multi_az", instance.MultiAZ)
|
||||
d.Set("preferred_maintenance_window", instance.PreferredMaintenanceWindow)
|
||||
d.Set("publicly_accessible", instance.PubliclyAccessible)
|
||||
d.Set("replication_instance_arn", instance.ReplicationInstanceArn)
|
||||
d.Set("replication_instance_class", instance.ReplicationInstanceClass)
|
||||
d.Set("replication_subnet_group_id", instance.ReplicationSubnetGroup.ReplicationSubnetGroupIdentifier)
|
||||
|
||||
vpc_security_group_ids := []string{}
|
||||
for _, sg := range instance.VpcSecurityGroups {
|
||||
vpc_security_group_ids = append(vpc_security_group_ids, aws.StringValue(sg.VpcSecurityGroupId))
|
||||
}
|
||||
|
||||
d.Set("vpc_security_group_ids", vpc_security_group_ids)
|
||||
|
||||
private_ip_addresses := []string{}
|
||||
for _, ip := range instance.ReplicationInstancePrivateIpAddresses {
|
||||
private_ip_addresses = append(private_ip_addresses, aws.StringValue(ip))
|
||||
}
|
||||
|
||||
d.Set("replication_instance_private_ips", private_ip_addresses)
|
||||
|
||||
public_ip_addresses := []string{}
|
||||
for _, ip := range instance.ReplicationInstancePublicIpAddresses {
|
||||
public_ip_addresses = append(public_ip_addresses, aws.StringValue(ip))
|
||||
}
|
||||
|
||||
d.Set("replication_instance_public_ips", public_ip_addresses)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitForInstanceCreated(client *dms.DatabaseMigrationService, id string, delay int, maxAttempts int) error {
|
||||
input := &dms.DescribeReplicationInstancesInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("replication-instance-id"),
|
||||
Values: []*string{aws.String(id)},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
config := waiter.Config{
|
||||
Operation: "DescribeReplicationInstances",
|
||||
Delay: delay,
|
||||
MaxAttempts: maxAttempts,
|
||||
Acceptors: []waiter.WaitAcceptor{
|
||||
{
|
||||
State: "success",
|
||||
Matcher: "pathAll",
|
||||
Argument: "ReplicationInstances[].ReplicationInstanceStatus",
|
||||
Expected: "available",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
w := waiter.Waiter{
|
||||
Client: client,
|
||||
Input: input,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
return w.Wait()
|
||||
}
|
||||
|
||||
func waitForInstanceDeleted(client *dms.DatabaseMigrationService, id string, delay int, maxAttempts int) error {
|
||||
input := &dms.DescribeReplicationInstancesInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("replication-instance-id"),
|
||||
Values: []*string{aws.String(id)},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
config := waiter.Config{
|
||||
Operation: "DescribeReplicationInstances",
|
||||
Delay: delay,
|
||||
MaxAttempts: maxAttempts,
|
||||
Acceptors: []waiter.WaitAcceptor{
|
||||
{
|
||||
State: "success",
|
||||
Matcher: "path",
|
||||
Argument: "length(ReplicationInstances[]) > `0`",
|
||||
Expected: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
w := waiter.Waiter{
|
||||
Client: client,
|
||||
Input: input,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
return w.Wait()
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccAwsDmsReplicationInstanceBasic(t *testing.T) {
|
||||
resourceName := "aws_dms_replication_instance.dms_replication_instance"
|
||||
randId := acctest.RandString(8)
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: dmsReplicationInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: dmsReplicationInstanceConfig(randId),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
checkDmsReplicationInstanceExists(resourceName),
|
||||
resource.TestCheckResourceAttrSet(resourceName, "replication_instance_arn"),
|
||||
),
|
||||
},
|
||||
{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
{
|
||||
Config: dmsReplicationInstanceConfigUpdate(randId),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
checkDmsReplicationInstanceExists(resourceName),
|
||||
resource.TestCheckResourceAttrSet(resourceName, "apply_immediately"),
|
||||
resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"),
|
||||
resource.TestCheckResourceAttr(resourceName, "preferred_maintenance_window", "mon:00:30-mon:02:30"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func checkDmsReplicationInstanceExists(n string) resource.TestCheckFunc {
|
||||
providers := []*schema.Provider{testAccProvider}
|
||||
return checkDmsReplicationInstanceExistsWithProviders(n, &providers)
|
||||
}
|
||||
|
||||
func checkDmsReplicationInstanceExistsWithProviders(n string, providers *[]*schema.Provider) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No ID is set")
|
||||
}
|
||||
for _, provider := range *providers {
|
||||
// Ignore if Meta is empty, this can happen for validation providers
|
||||
if provider.Meta() == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
conn := provider.Meta().(*AWSClient).dmsconn
|
||||
_, err := conn.DescribeReplicationInstances(&dms.DescribeReplicationInstancesInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("replication-instance-id"),
|
||||
Values: []*string{aws.String(rs.Primary.ID)},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("DMS replication instance error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("DMS replication instance not found")
|
||||
}
|
||||
}
|
||||
|
||||
func dmsReplicationInstanceDestroy(s *terraform.State) error {
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "aws_dms_replication_instance" {
|
||||
continue
|
||||
}
|
||||
|
||||
err := checkDmsReplicationInstanceExists(rs.Primary.ID)
|
||||
if err == nil {
|
||||
return fmt.Errorf("Found replication instance that was not destroyed: %s", rs.Primary.ID)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func dmsReplicationInstanceConfig(randId string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_iam_role" "dms_iam_role" {
|
||||
name = "dms-vpc-role"
|
||||
assume_role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"dms.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "dms_iam_role_policy" {
|
||||
role = "${aws_iam_role.dms_iam_role.name}"
|
||||
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole"
|
||||
}
|
||||
|
||||
resource "aws_vpc" "dms_vpc" {
|
||||
cidr_block = "10.1.0.0/16"
|
||||
tags {
|
||||
Name = "tf-test-dms-vpc-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_1" {
|
||||
cidr_block = "10.1.1.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_2" {
|
||||
cidr_block = "10.1.2.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_subnet_group" "dms_replication_subnet_group" {
|
||||
replication_subnet_group_id = "tf-test-dms-replication-subnet-group-%[1]s"
|
||||
replication_subnet_group_description = "terraform test for replication subnet group"
|
||||
subnet_ids = ["${aws_subnet.dms_subnet_1.id}", "${aws_subnet.dms_subnet_2.id}"]
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_instance" "dms_replication_instance" {
|
||||
allocated_storage = 5
|
||||
auto_minor_version_upgrade = true
|
||||
replication_instance_class = "dms.t2.micro"
|
||||
replication_instance_id = "tf-test-dms-replication-instance-%[1]s"
|
||||
preferred_maintenance_window = "sun:00:30-sun:02:30"
|
||||
publicly_accessible = false
|
||||
replication_subnet_group_id = "${aws_dms_replication_subnet_group.dms_replication_subnet_group.replication_subnet_group_id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-replication-instance-%[1]s"
|
||||
Update = "to-update"
|
||||
Remove = "to-remove"
|
||||
}
|
||||
}
|
||||
`, randId)
|
||||
}
|
||||
|
||||
func dmsReplicationInstanceConfigUpdate(randId string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_iam_role" "dms_iam_role" {
|
||||
name = "dms-vpc-role"
|
||||
assume_role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"dms.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "dms_iam_role_policy" {
|
||||
role = "${aws_iam_role.dms_iam_role.name}"
|
||||
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole"
|
||||
}
|
||||
|
||||
resource "aws_vpc" "dms_vpc" {
|
||||
cidr_block = "10.1.0.0/16"
|
||||
tags {
|
||||
Name = "tf-test-dms-vpc-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_1" {
|
||||
cidr_block = "10.1.1.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_2" {
|
||||
cidr_block = "10.1.2.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_subnet_group" "dms_replication_subnet_group" {
|
||||
replication_subnet_group_id = "tf-test-dms-replication-subnet-group-%[1]s"
|
||||
replication_subnet_group_description = "terraform test for replication subnet group"
|
||||
subnet_ids = ["${aws_subnet.dms_subnet_1.id}", "${aws_subnet.dms_subnet_2.id}"]
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_instance" "dms_replication_instance" {
|
||||
allocated_storage = 5
|
||||
apply_immediately = true
|
||||
auto_minor_version_upgrade = false
|
||||
replication_instance_class = "dms.t2.micro"
|
||||
replication_instance_id = "tf-test-dms-replication-instance-%[1]s"
|
||||
preferred_maintenance_window = "mon:00:30-mon:02:30"
|
||||
publicly_accessible = false
|
||||
replication_subnet_group_id = "${aws_dms_replication_subnet_group.dms_replication_subnet_group.replication_subnet_group_id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-replication-instance-%[1]s"
|
||||
Update = "updated"
|
||||
Add = "added"
|
||||
}
|
||||
}
|
||||
`, randId)
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func resourceAwsDmsReplicationSubnetGroup() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsDmsReplicationSubnetGroupCreate,
|
||||
Read: resourceAwsDmsReplicationSubnetGroupRead,
|
||||
Update: resourceAwsDmsReplicationSubnetGroupUpdate,
|
||||
Delete: resourceAwsDmsReplicationSubnetGroupDelete,
|
||||
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"replication_subnet_group_arn": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"replication_subnet_group_description": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"replication_subnet_group_id": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateDmsReplicationSubnetGroupId,
|
||||
},
|
||||
"subnet_ids": {
|
||||
Type: schema.TypeSet,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Set: schema.HashString,
|
||||
Required: true,
|
||||
},
|
||||
"tags": {
|
||||
Type: schema.TypeMap,
|
||||
Optional: true,
|
||||
},
|
||||
"vpc_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationSubnetGroupCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.CreateReplicationSubnetGroupInput{
|
||||
ReplicationSubnetGroupIdentifier: aws.String(d.Get("replication_subnet_group_id").(string)),
|
||||
ReplicationSubnetGroupDescription: aws.String(d.Get("replication_subnet_group_description").(string)),
|
||||
SubnetIds: expandStringList(d.Get("subnet_ids").(*schema.Set).List()),
|
||||
Tags: dmsTagsFromMap(d.Get("tags").(map[string]interface{})),
|
||||
}
|
||||
|
||||
log.Println("[DEBUG] DMS create replication subnet group:", request)
|
||||
|
||||
_, err := conn.CreateReplicationSubnetGroup(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(d.Get("replication_subnet_group_id").(string))
|
||||
return resourceAwsDmsReplicationSubnetGroupRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationSubnetGroupRead(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
response, err := conn.DescribeReplicationSubnetGroups(&dms.DescribeReplicationSubnetGroupsInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("replication-subnet-group-id"),
|
||||
Values: []*string{aws.String(d.Id())}, // Must use d.Id() to work with import.
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(response.ReplicationSubnetGroups) == 0 {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
// The AWS API for DMS subnet groups does not return the ARN which is required to
|
||||
// retrieve tags. This ARN can be built.
|
||||
d.Set("replication_subnet_group_arn", fmt.Sprintf("arn:aws:dms:%s:%s:subgrp:%s",
|
||||
meta.(*AWSClient).region, meta.(*AWSClient).accountid, d.Id()))
|
||||
|
||||
err = resourceAwsDmsReplicationSubnetGroupSetState(d, response.ReplicationSubnetGroups[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tagsResp, err := conn.ListTagsForResource(&dms.ListTagsForResourceInput{
|
||||
ResourceArn: aws.String(d.Get("replication_subnet_group_arn").(string)),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Set("tags", dmsTagsToMap(tagsResp.TagList))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationSubnetGroupUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
// Updates to subnet groups are only valid when sending SubnetIds even if there are no
|
||||
// changes to SubnetIds.
|
||||
request := &dms.ModifyReplicationSubnetGroupInput{
|
||||
ReplicationSubnetGroupIdentifier: aws.String(d.Get("replication_subnet_group_id").(string)),
|
||||
SubnetIds: expandStringList(d.Get("subnet_ids").(*schema.Set).List()),
|
||||
}
|
||||
|
||||
if d.HasChange("replication_subnet_group_description") {
|
||||
request.ReplicationSubnetGroupDescription = aws.String(d.Get("replication_subnet_group_description").(string))
|
||||
}
|
||||
|
||||
if d.HasChange("tags") {
|
||||
err := dmsSetTags(d.Get("replication_subnet_group_arn").(string), d, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("[DEBUG] DMS update replication subnet group:", request)
|
||||
|
||||
_, err := conn.ModifyReplicationSubnetGroup(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceAwsDmsReplicationSubnetGroupRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationSubnetGroupDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.DeleteReplicationSubnetGroupInput{
|
||||
ReplicationSubnetGroupIdentifier: aws.String(d.Get("replication_subnet_group_id").(string)),
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] DMS delete replication subnet group: %#v", request)
|
||||
|
||||
_, err := conn.DeleteReplicationSubnetGroup(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationSubnetGroupSetState(d *schema.ResourceData, group *dms.ReplicationSubnetGroup) error {
|
||||
d.SetId(*group.ReplicationSubnetGroupIdentifier)
|
||||
|
||||
subnet_ids := []string{}
|
||||
for _, subnet := range group.Subnets {
|
||||
subnet_ids = append(subnet_ids, aws.StringValue(subnet.SubnetIdentifier))
|
||||
}
|
||||
|
||||
d.Set("replication_subnet_group_description", group.ReplicationSubnetGroupDescription)
|
||||
d.Set("replication_subnet_group_id", group.ReplicationSubnetGroupIdentifier)
|
||||
d.Set("subnet_ids", subnet_ids)
|
||||
d.Set("vpc_id", group.VpcId)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccAwsDmsReplicationSubnetGroupBasic(t *testing.T) {
|
||||
resourceName := "aws_dms_replication_subnet_group.dms_replication_subnet_group"
|
||||
randId := acctest.RandString(8)
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: dmsReplicationSubnetGroupDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: dmsReplicationSubnetGroupConfig(randId),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
checkDmsReplicationSubnetGroupExists(resourceName),
|
||||
resource.TestCheckResourceAttrSet(resourceName, "vpc_id"),
|
||||
),
|
||||
},
|
||||
{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
{
|
||||
Config: dmsReplicationSubnetGroupConfigUpdate(randId),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
checkDmsReplicationSubnetGroupExists(resourceName),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func checkDmsReplicationSubnetGroupExists(n string) resource.TestCheckFunc {
|
||||
providers := []*schema.Provider{testAccProvider}
|
||||
return checkDmsReplicationSubnetGroupExistsWithProviders(n, &providers)
|
||||
}
|
||||
|
||||
func checkDmsReplicationSubnetGroupExistsWithProviders(n string, providers *[]*schema.Provider) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No ID is set")
|
||||
}
|
||||
for _, provider := range *providers {
|
||||
// Ignore if Meta is empty, this can happen for validation providers
|
||||
if provider.Meta() == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
conn := provider.Meta().(*AWSClient).dmsconn
|
||||
_, err := conn.DescribeReplicationSubnetGroups(&dms.DescribeReplicationSubnetGroupsInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("replication-subnet-group-id"),
|
||||
Values: []*string{aws.String(rs.Primary.ID)},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("DMS replication subnet group error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("DMS replication subnet group not found")
|
||||
}
|
||||
}
|
||||
|
||||
func dmsReplicationSubnetGroupDestroy(s *terraform.State) error {
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "aws_dms_replication_subnet_group" {
|
||||
continue
|
||||
}
|
||||
|
||||
err := checkDmsReplicationSubnetGroupExists(rs.Primary.ID)
|
||||
if err == nil {
|
||||
return fmt.Errorf("Found replication subnet group that was not destroyed: %s", rs.Primary.ID)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func dmsReplicationSubnetGroupConfig(randId string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_iam_role" "dms_iam_role" {
|
||||
name = "dms-vpc-role"
|
||||
assume_role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"dms.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "dms_iam_role_policy" {
|
||||
role = "${aws_iam_role.dms_iam_role.name}"
|
||||
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole"
|
||||
}
|
||||
|
||||
resource "aws_vpc" "dms_vpc" {
|
||||
cidr_block = "10.1.0.0/16"
|
||||
tags {
|
||||
Name = "tf-test-dms-vpc-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_1" {
|
||||
cidr_block = "10.1.1.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_2" {
|
||||
cidr_block = "10.1.2.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_3" {
|
||||
cidr_block = "10.1.3.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_subnet_group" "dms_replication_subnet_group" {
|
||||
replication_subnet_group_id = "tf-test-dms-replication-subnet-group-%[1]s"
|
||||
replication_subnet_group_description = "terraform test for replication subnet group"
|
||||
subnet_ids = ["${aws_subnet.dms_subnet_1.id}", "${aws_subnet.dms_subnet_2.id}"]
|
||||
tags {
|
||||
Name = "tf-test-dms-replication-subnet-group-%[1]s"
|
||||
Update = "to-update"
|
||||
Remove = "to-remove"
|
||||
}
|
||||
}
|
||||
`, randId)
|
||||
}
|
||||
|
||||
func dmsReplicationSubnetGroupConfigUpdate(randId string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_iam_role" "dms_iam_role" {
|
||||
name = "dms-vpc-role"
|
||||
assume_role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"dms.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "dms_iam_role_policy" {
|
||||
role = "${aws_iam_role.dms_iam_role.name}"
|
||||
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole"
|
||||
}
|
||||
|
||||
resource "aws_vpc" "dms_vpc" {
|
||||
cidr_block = "10.1.0.0/16"
|
||||
tags {
|
||||
Name = "tf-test-dms-vpc-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_1" {
|
||||
cidr_block = "10.1.1.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_2" {
|
||||
cidr_block = "10.1.2.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_3" {
|
||||
cidr_block = "10.1.3.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_subnet_group" "dms_replication_subnet_group" {
|
||||
replication_subnet_group_id = "tf-test-dms-replication-subnet-group-%[1]s"
|
||||
replication_subnet_group_description = "terraform test for replication subnet group"
|
||||
subnet_ids = ["${aws_subnet.dms_subnet_1.id}", "${aws_subnet.dms_subnet_3.id}"]
|
||||
tags {
|
||||
Name = "tf-test-dms-replication-subnet-group-%[1]s"
|
||||
Update = "updated"
|
||||
Add = "added"
|
||||
}
|
||||
}
|
||||
`, randId)
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/private/waiter"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/helper/validation"
|
||||
)
|
||||
|
||||
func resourceAwsDmsReplicationTask() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsDmsReplicationTaskCreate,
|
||||
Read: resourceAwsDmsReplicationTaskRead,
|
||||
Update: resourceAwsDmsReplicationTaskUpdate,
|
||||
Delete: resourceAwsDmsReplicationTaskDelete,
|
||||
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"cdc_start_time": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
// Requires a Unix timestamp in seconds. Example 1484346880
|
||||
},
|
||||
"migration_type": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: validation.StringInSlice([]string{
|
||||
"full-load",
|
||||
"cdc",
|
||||
"full-load-and-cdc",
|
||||
}, false),
|
||||
},
|
||||
"replication_instance_arn": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateArn,
|
||||
},
|
||||
"replication_task_arn": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"replication_task_id": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateDmsReplicationTaskId,
|
||||
},
|
||||
"replication_task_settings": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ValidateFunc: validateJsonString,
|
||||
},
|
||||
"source_endpoint_arn": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateArn,
|
||||
},
|
||||
"table_mappings": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: validateJsonString,
|
||||
},
|
||||
"tags": {
|
||||
Type: schema.TypeMap,
|
||||
Optional: true,
|
||||
},
|
||||
"target_endpoint_arn": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateArn,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationTaskCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.CreateReplicationTaskInput{
|
||||
MigrationType: aws.String(d.Get("migration_type").(string)),
|
||||
ReplicationInstanceArn: aws.String(d.Get("replication_instance_arn").(string)),
|
||||
ReplicationTaskIdentifier: aws.String(d.Get("replication_task_id").(string)),
|
||||
SourceEndpointArn: aws.String(d.Get("source_endpoint_arn").(string)),
|
||||
TableMappings: aws.String(d.Get("table_mappings").(string)),
|
||||
Tags: dmsTagsFromMap(d.Get("tags").(map[string]interface{})),
|
||||
TargetEndpointArn: aws.String(d.Get("target_endpoint_arn").(string)),
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("cdc_start_time"); ok {
|
||||
seconds, err := strconv.ParseInt(v.(string), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[ERROR] DMS create replication task. Invalid CDC Unix timestamp: %s", err)
|
||||
}
|
||||
request.CdcStartTime = aws.Time(time.Unix(seconds, 0))
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("replication_task_settings"); ok {
|
||||
request.ReplicationTaskSettings = aws.String(v.(string))
|
||||
}
|
||||
|
||||
log.Println("[DEBUG] DMS create replication task:", request)
|
||||
|
||||
_, err := conn.CreateReplicationTask(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
taskId := d.Get("replication_task_id").(string)
|
||||
|
||||
err = waitForTaskCreated(conn, taskId, 30, 10)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(taskId)
|
||||
return resourceAwsDmsReplicationTaskRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationTaskRead(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
response, err := conn.DescribeReplicationTasks(&dms.DescribeReplicationTasksInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("replication-task-id"),
|
||||
Values: []*string{aws.String(d.Id())}, // Must use d.Id() to work with import.
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
if dmserr, ok := err.(awserr.Error); ok && dmserr.Code() == "ResourceNotFoundFault" {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
err = resourceAwsDmsReplicationTaskSetState(d, response.ReplicationTasks[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tagsResp, err := conn.ListTagsForResource(&dms.ListTagsForResourceInput{
|
||||
ResourceArn: aws.String(d.Get("replication_task_arn").(string)),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Set("tags", dmsTagsToMap(tagsResp.TagList))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationTaskUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.ModifyReplicationTaskInput{
|
||||
ReplicationTaskArn: aws.String(d.Get("replication_task_arn").(string)),
|
||||
}
|
||||
hasChanges := false
|
||||
|
||||
if d.HasChange("cdc_start_time") {
|
||||
seconds, err := strconv.ParseInt(d.Get("cdc_start_time").(string), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[ERROR] DMS update replication task. Invalid CRC Unix timestamp: %s", err)
|
||||
}
|
||||
request.CdcStartTime = aws.Time(time.Unix(seconds, 0))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("migration_type") {
|
||||
request.MigrationType = aws.String(d.Get("migration_type").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("replication_task_settings") {
|
||||
request.ReplicationTaskSettings = aws.String(d.Get("replication_task_settings").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("table_mappings") {
|
||||
request.TableMappings = aws.String(d.Get("table_mappings").(string))
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if d.HasChange("tags") {
|
||||
err := dmsSetTags(d.Get("replication_task_arn").(string), d, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if hasChanges {
|
||||
log.Println("[DEBUG] DMS update replication task:", request)
|
||||
|
||||
_, err := conn.ModifyReplicationTask(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = waitForTaskUpdated(conn, d.Get("replication_task_id").(string), 30, 10)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceAwsDmsReplicationTaskRead(d, meta)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationTaskDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
request := &dms.DeleteReplicationTaskInput{
|
||||
ReplicationTaskArn: aws.String(d.Get("replication_task_arn").(string)),
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] DMS delete replication task: %#v", request)
|
||||
|
||||
_, err := conn.DeleteReplicationTask(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
waitErr := waitForTaskDeleted(conn, d.Get("replication_task_id").(string), 30, 10)
|
||||
if waitErr != nil {
|
||||
return waitErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsDmsReplicationTaskSetState(d *schema.ResourceData, task *dms.ReplicationTask) error {
|
||||
d.SetId(*task.ReplicationTaskIdentifier)
|
||||
|
||||
d.Set("migration_type", task.MigrationType)
|
||||
d.Set("replication_instance_arn", task.ReplicationInstanceArn)
|
||||
d.Set("replication_task_arn", task.ReplicationTaskArn)
|
||||
d.Set("replication_task_id", task.ReplicationTaskIdentifier)
|
||||
d.Set("replication_task_settings", task.ReplicationTaskSettings)
|
||||
d.Set("source_endpoint_arn", task.SourceEndpointArn)
|
||||
d.Set("table_mappings", task.TableMappings)
|
||||
d.Set("target_endpoint_arn", task.TargetEndpointArn)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitForTaskCreated(client *dms.DatabaseMigrationService, id string, delay int, maxAttempts int) error {
|
||||
input := &dms.DescribeReplicationTasksInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("replication-task-id"),
|
||||
Values: []*string{aws.String(id)},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
config := waiter.Config{
|
||||
Operation: "DescribeReplicationTasks",
|
||||
Delay: delay,
|
||||
MaxAttempts: maxAttempts,
|
||||
Acceptors: []waiter.WaitAcceptor{
|
||||
{
|
||||
State: "retry",
|
||||
Matcher: "pathAll",
|
||||
Argument: "ReplicationTasks[].Status",
|
||||
Expected: "creating",
|
||||
},
|
||||
{
|
||||
State: "success",
|
||||
Matcher: "pathAll",
|
||||
Argument: "ReplicationTasks[].Status",
|
||||
Expected: "ready",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
w := waiter.Waiter{
|
||||
Client: client,
|
||||
Input: input,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
return w.Wait()
|
||||
}
|
||||
|
||||
func waitForTaskUpdated(client *dms.DatabaseMigrationService, id string, delay int, maxAttempts int) error {
|
||||
input := &dms.DescribeReplicationTasksInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("replication-task-id"),
|
||||
Values: []*string{aws.String(id)},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
config := waiter.Config{
|
||||
Operation: "DescribeReplicationTasks",
|
||||
Delay: delay,
|
||||
MaxAttempts: maxAttempts,
|
||||
Acceptors: []waiter.WaitAcceptor{
|
||||
{
|
||||
State: "retry",
|
||||
Matcher: "pathAll",
|
||||
Argument: "ReplicationTasks[].Status",
|
||||
Expected: "modifying",
|
||||
},
|
||||
{
|
||||
State: "success",
|
||||
Matcher: "pathAll",
|
||||
Argument: "ReplicationTasks[].Status",
|
||||
Expected: "ready",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
w := waiter.Waiter{
|
||||
Client: client,
|
||||
Input: input,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
return w.Wait()
|
||||
}
|
||||
|
||||
func waitForTaskDeleted(client *dms.DatabaseMigrationService, id string, delay int, maxAttempts int) error {
|
||||
input := &dms.DescribeReplicationTasksInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("replication-task-id"),
|
||||
Values: []*string{aws.String(id)},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
config := waiter.Config{
|
||||
Operation: "DescribeReplicationTasks",
|
||||
Delay: delay,
|
||||
MaxAttempts: maxAttempts,
|
||||
Acceptors: []waiter.WaitAcceptor{
|
||||
{
|
||||
State: "retry",
|
||||
Matcher: "pathAll",
|
||||
Argument: "ReplicationTasks[].Status",
|
||||
Expected: "deleting",
|
||||
},
|
||||
{
|
||||
State: "success",
|
||||
Matcher: "path",
|
||||
Argument: "length(ReplicationTasks[]) > `0`",
|
||||
Expected: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
w := waiter.Waiter{
|
||||
Client: client,
|
||||
Input: input,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
return w.Wait()
|
||||
}
|
|
@ -0,0 +1,296 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccAwsDmsReplicationTaskBasic(t *testing.T) {
|
||||
resourceName := "aws_dms_replication_task.dms_replication_task"
|
||||
randId := acctest.RandString(8)
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: dmsReplicationTaskDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: dmsReplicationTaskConfig(randId),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
checkDmsReplicationTaskExists(resourceName),
|
||||
resource.TestCheckResourceAttrSet(resourceName, "replication_task_arn"),
|
||||
),
|
||||
},
|
||||
{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
{
|
||||
Config: dmsReplicationTaskConfigUpdate(randId),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
checkDmsReplicationTaskExists(resourceName),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func checkDmsReplicationTaskExists(n string) resource.TestCheckFunc {
|
||||
providers := []*schema.Provider{testAccProvider}
|
||||
return checkDmsReplicationTaskExistsWithProviders(n, &providers)
|
||||
}
|
||||
|
||||
func checkDmsReplicationTaskExistsWithProviders(n string, providers *[]*schema.Provider) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No ID is set")
|
||||
}
|
||||
for _, provider := range *providers {
|
||||
// Ignore if Meta is empty, this can happen for validation providers
|
||||
if provider.Meta() == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
conn := provider.Meta().(*AWSClient).dmsconn
|
||||
_, err := conn.DescribeReplicationTasks(&dms.DescribeReplicationTasksInput{
|
||||
Filters: []*dms.Filter{
|
||||
{
|
||||
Name: aws.String("replication-task-id"),
|
||||
Values: []*string{aws.String(rs.Primary.ID)},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("DMS replication subnet group error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("DMS replication subnet group not found")
|
||||
}
|
||||
}
|
||||
|
||||
func dmsReplicationTaskDestroy(s *terraform.State) error {
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "aws_dms_replication_task" {
|
||||
continue
|
||||
}
|
||||
|
||||
err := checkDmsReplicationTaskExists(rs.Primary.ID)
|
||||
if err == nil {
|
||||
return fmt.Errorf("Found replication subnet group that was not destroyed: %s", rs.Primary.ID)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func dmsReplicationTaskConfig(randId string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_iam_role" "dms_iam_role" {
|
||||
name = "dms-vpc-role"
|
||||
assume_role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"dms.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "dms_iam_role_policy" {
|
||||
role = "${aws_iam_role.dms_iam_role.name}"
|
||||
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole"
|
||||
}
|
||||
|
||||
resource "aws_vpc" "dms_vpc" {
|
||||
cidr_block = "10.1.0.0/16"
|
||||
tags {
|
||||
Name = "tf-test-dms-vpc-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_1" {
|
||||
cidr_block = "10.1.1.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_2" {
|
||||
cidr_block = "10.1.2.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_dms_endpoint" "dms_endpoint_source" {
|
||||
database_name = "tf-test-dms-db"
|
||||
endpoint_id = "tf-test-dms-endpoint-source-%[1]s"
|
||||
endpoint_type = "source"
|
||||
engine_name = "aurora"
|
||||
server_name = "tf-test-cluster.cluster-xxxxxxx.us-west-2.rds.amazonaws.com"
|
||||
port = 3306
|
||||
username = "tftest"
|
||||
password = "tftest"
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_dms_endpoint" "dms_endpoint_target" {
|
||||
database_name = "tf-test-dms-db"
|
||||
endpoint_id = "tf-test-dms-endpoint-target-%[1]s"
|
||||
endpoint_type = "target"
|
||||
engine_name = "aurora"
|
||||
server_name = "tf-test-cluster.cluster-xxxxxxx.us-west-2.rds.amazonaws.com"
|
||||
port = 3306
|
||||
username = "tftest"
|
||||
password = "tftest"
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_subnet_group" "dms_replication_subnet_group" {
|
||||
replication_subnet_group_id = "tf-test-dms-replication-subnet-group-%[1]s"
|
||||
replication_subnet_group_description = "terraform test for replication subnet group"
|
||||
subnet_ids = ["${aws_subnet.dms_subnet_1.id}", "${aws_subnet.dms_subnet_2.id}"]
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_instance" "dms_replication_instance" {
|
||||
allocated_storage = 5
|
||||
auto_minor_version_upgrade = true
|
||||
replication_instance_class = "dms.t2.micro"
|
||||
replication_instance_id = "tf-test-dms-replication-instance-%[1]s"
|
||||
preferred_maintenance_window = "sun:00:30-sun:02:30"
|
||||
publicly_accessible = false
|
||||
replication_subnet_group_id = "${aws_dms_replication_subnet_group.dms_replication_subnet_group.replication_subnet_group_id}"
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_task" "dms_replication_task" {
|
||||
migration_type = "full-load"
|
||||
replication_instance_arn = "${aws_dms_replication_instance.dms_replication_instance.replication_instance_arn}"
|
||||
replication_task_id = "tf-test-dms-replication-task-%[1]s"
|
||||
replication_task_settings = "{\"TargetMetadata\":{\"TargetSchema\":\"\",\"SupportLobs\":true,\"FullLobMode\":false,\"LobChunkSize\":0,\"LimitedSizeLobMode\":true,\"LobMaxSize\":32,\"LoadMaxFileSize\":0,\"ParallelLoadThreads\":0,\"BatchApplyEnabled\":false},\"FullLoadSettings\":{\"FullLoadEnabled\":true,\"ApplyChangesEnabled\":false,\"TargetTablePrepMode\":\"DROP_AND_CREATE\",\"CreatePkAfterFullLoad\":false,\"StopTaskCachedChangesApplied\":false,\"StopTaskCachedChangesNotApplied\":false,\"ResumeEnabled\":false,\"ResumeMinTableSize\":100000,\"ResumeOnlyClusteredPKTables\":true,\"MaxFullLoadSubTasks\":8,\"TransactionConsistencyTimeout\":600,\"CommitRate\":10000},\"Logging\":{\"EnableLogging\":false,\"LogComponents\":[{\"Id\":\"SOURCE_UNLOAD\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"TARGET_LOAD\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"SOURCE_CAPTURE\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"TARGET_APPLY\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"TASK_MANAGER\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"}],\"CloudWatchLogGroup\":null,\"CloudWatchLogStream\":null},\"ControlTablesSettings\":{\"historyTimeslotInMinutes\":5,\"ControlSchema\":\"\",\"HistoryTimeslotInMinutes\":5,\"HistoryTableEnabled\":false,\"SuspendedTablesTableEnabled\":false,\"StatusTableEnabled\":false},\"StreamBufferSettings\":{\"StreamBufferCount\":3,\"StreamBufferSizeInMB\":8,\"CtrlStreamBufferSizeInMB\":5},\"ChangeProcessingDdlHandlingPolicy\":{\"HandleSourceTableDropped\":true,\"HandleSourceTableTruncated\":true,\"HandleSourceTableAltered\":true},\"ErrorBehavior\":{\"DataErrorPolicy\":\"LOG_ERROR\",\"DataTruncationErrorPolicy\":\"LOG_ERROR\",\"DataErrorEscalationPolicy\":\"SUSPEND_TABLE\",\"DataErrorEscalationCount\":0,\"TableErrorPolicy\":\"SUSPEND_TABLE\",\"TableErrorEscalationPolicy\":\"STOP_TASK\",\"TableErrorEscalationCount\":0,\"RecoverableErrorCount\":-1,\"RecoverableErrorInterval\":5,\"RecoverableErrorThrottling\":true,\"RecoverableErrorThrottlingMax\":1800,\"ApplyErrorDeletePolicy\":\"IGNORE_RECORD\",\"ApplyErrorInsertPolicy\":\"LOG_ERROR\",\"ApplyErrorUpdatePolicy\":\"LOG_ERROR\",\"ApplyErrorEscalationPolicy\":\"LOG_ERROR\",\"ApplyErrorEscalationCount\":0,\"FullLoadIgnoreConflicts\":true},\"ChangeProcessingTuning\":{\"BatchApplyPreserveTransaction\":true,\"BatchApplyTimeoutMin\":1,\"BatchApplyTimeoutMax\":30,\"BatchApplyMemoryLimit\":500,\"BatchSplitSize\":0,\"MinTransactionSize\":1000,\"CommitTimeout\":1,\"MemoryLimitTotal\":1024,\"MemoryKeepTime\":60,\"StatementCacheSize\":50}}"
|
||||
source_endpoint_arn = "${aws_dms_endpoint.dms_endpoint_source.endpoint_arn}"
|
||||
table_mappings = "{\"rules\":[{\"rule-type\":\"selection\",\"rule-id\":\"1\",\"rule-name\":\"1\",\"object-locator\":{\"schema-name\":\"%%\",\"table-name\":\"%%\"},\"rule-action\":\"include\"}]}"
|
||||
tags {
|
||||
Name = "tf-test-dms-replication-task-%[1]s"
|
||||
Update = "to-update"
|
||||
Remove = "to-remove"
|
||||
}
|
||||
target_endpoint_arn = "${aws_dms_endpoint.dms_endpoint_target.endpoint_arn}"
|
||||
}
|
||||
`, randId)
|
||||
}
|
||||
|
||||
func dmsReplicationTaskConfigUpdate(randId string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_iam_role" "dms_iam_role" {
|
||||
name = "dms-vpc-role"
|
||||
assume_role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"dms.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "dms_iam_role_policy" {
|
||||
role = "${aws_iam_role.dms_iam_role.name}"
|
||||
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole"
|
||||
}
|
||||
|
||||
resource "aws_vpc" "dms_vpc" {
|
||||
cidr_block = "10.1.0.0/16"
|
||||
tags {
|
||||
Name = "tf-test-dms-vpc-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_1" {
|
||||
cidr_block = "10.1.1.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_subnet" "dms_subnet_2" {
|
||||
cidr_block = "10.1.2.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
vpc_id = "${aws_vpc.dms_vpc.id}"
|
||||
tags {
|
||||
Name = "tf-test-dms-subnet-%[1]s"
|
||||
}
|
||||
depends_on = ["aws_vpc.dms_vpc"]
|
||||
}
|
||||
|
||||
resource "aws_dms_endpoint" "dms_endpoint_source" {
|
||||
database_name = "tf-test-dms-db"
|
||||
endpoint_id = "tf-test-dms-endpoint-source-%[1]s"
|
||||
endpoint_type = "source"
|
||||
engine_name = "aurora"
|
||||
server_name = "tf-test-cluster.cluster-xxxxxxx.us-west-2.rds.amazonaws.com"
|
||||
port = 3306
|
||||
username = "tftest"
|
||||
password = "tftest"
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_dms_endpoint" "dms_endpoint_target" {
|
||||
database_name = "tf-test-dms-db"
|
||||
endpoint_id = "tf-test-dms-endpoint-target-%[1]s"
|
||||
endpoint_type = "target"
|
||||
engine_name = "aurora"
|
||||
server_name = "tf-test-cluster.cluster-xxxxxxx.us-west-2.rds.amazonaws.com"
|
||||
port = 3306
|
||||
username = "tftest"
|
||||
password = "tftest"
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_subnet_group" "dms_replication_subnet_group" {
|
||||
replication_subnet_group_id = "tf-test-dms-replication-subnet-group-%[1]s"
|
||||
replication_subnet_group_description = "terraform test for replication subnet group"
|
||||
subnet_ids = ["${aws_subnet.dms_subnet_1.id}", "${aws_subnet.dms_subnet_2.id}"]
|
||||
depends_on = ["aws_iam_role_policy_attachment.dms_iam_role_policy"]
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_instance" "dms_replication_instance" {
|
||||
allocated_storage = 5
|
||||
auto_minor_version_upgrade = true
|
||||
replication_instance_class = "dms.t2.micro"
|
||||
replication_instance_id = "tf-test-dms-replication-instance-%[1]s"
|
||||
preferred_maintenance_window = "sun:00:30-sun:02:30"
|
||||
publicly_accessible = false
|
||||
replication_subnet_group_id = "${aws_dms_replication_subnet_group.dms_replication_subnet_group.replication_subnet_group_id}"
|
||||
}
|
||||
|
||||
resource "aws_dms_replication_task" "dms_replication_task" {
|
||||
migration_type = "full-load"
|
||||
replication_instance_arn = "${aws_dms_replication_instance.dms_replication_instance.replication_instance_arn}"
|
||||
replication_task_id = "tf-test-dms-replication-task-%[1]s"
|
||||
replication_task_settings = "{\"TargetMetadata\":{\"TargetSchema\":\"\",\"SupportLobs\":true,\"FullLobMode\":false,\"LobChunkSize\":0,\"LimitedSizeLobMode\":true,\"LobMaxSize\":32,\"LoadMaxFileSize\":0,\"ParallelLoadThreads\":0,\"BatchApplyEnabled\":false},\"FullLoadSettings\":{\"FullLoadEnabled\":true,\"ApplyChangesEnabled\":false,\"TargetTablePrepMode\":\"DROP_AND_CREATE\",\"CreatePkAfterFullLoad\":false,\"StopTaskCachedChangesApplied\":false,\"StopTaskCachedChangesNotApplied\":false,\"ResumeEnabled\":false,\"ResumeMinTableSize\":100000,\"ResumeOnlyClusteredPKTables\":true,\"MaxFullLoadSubTasks\":7,\"TransactionConsistencyTimeout\":600,\"CommitRate\":10000},\"Logging\":{\"EnableLogging\":false,\"LogComponents\":[{\"Id\":\"SOURCE_UNLOAD\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"TARGET_LOAD\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"SOURCE_CAPTURE\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"TARGET_APPLY\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"},{\"Id\":\"TASK_MANAGER\",\"Severity\":\"LOGGER_SEVERITY_DEFAULT\"}],\"CloudWatchLogGroup\":null,\"CloudWatchLogStream\":null},\"ControlTablesSettings\":{\"historyTimeslotInMinutes\":5,\"ControlSchema\":\"\",\"HistoryTimeslotInMinutes\":5,\"HistoryTableEnabled\":false,\"SuspendedTablesTableEnabled\":false,\"StatusTableEnabled\":false},\"StreamBufferSettings\":{\"StreamBufferCount\":3,\"StreamBufferSizeInMB\":8,\"CtrlStreamBufferSizeInMB\":5},\"ChangeProcessingDdlHandlingPolicy\":{\"HandleSourceTableDropped\":true,\"HandleSourceTableTruncated\":true,\"HandleSourceTableAltered\":true},\"ErrorBehavior\":{\"DataErrorPolicy\":\"LOG_ERROR\",\"DataTruncationErrorPolicy\":\"LOG_ERROR\",\"DataErrorEscalationPolicy\":\"SUSPEND_TABLE\",\"DataErrorEscalationCount\":0,\"TableErrorPolicy\":\"SUSPEND_TABLE\",\"TableErrorEscalationPolicy\":\"STOP_TASK\",\"TableErrorEscalationCount\":0,\"RecoverableErrorCount\":-1,\"RecoverableErrorInterval\":5,\"RecoverableErrorThrottling\":true,\"RecoverableErrorThrottlingMax\":1800,\"ApplyErrorDeletePolicy\":\"IGNORE_RECORD\",\"ApplyErrorInsertPolicy\":\"LOG_ERROR\",\"ApplyErrorUpdatePolicy\":\"LOG_ERROR\",\"ApplyErrorEscalationPolicy\":\"LOG_ERROR\",\"ApplyErrorEscalationCount\":0,\"FullLoadIgnoreConflicts\":true},\"ChangeProcessingTuning\":{\"BatchApplyPreserveTransaction\":true,\"BatchApplyTimeoutMin\":1,\"BatchApplyTimeoutMax\":30,\"BatchApplyMemoryLimit\":500,\"BatchSplitSize\":0,\"MinTransactionSize\":1000,\"CommitTimeout\":1,\"MemoryLimitTotal\":1024,\"MemoryKeepTime\":60,\"StatementCacheSize\":50}}"
|
||||
source_endpoint_arn = "${aws_dms_endpoint.dms_endpoint_source.endpoint_arn}"
|
||||
table_mappings = "{\"rules\":[{\"rule-type\":\"selection\",\"rule-id\":\"1\",\"rule-name\":\"1\",\"object-locator\":{\"schema-name\":\"%%\",\"table-name\":\"%%\"},\"rule-action\":\"include\"}]}"
|
||||
tags {
|
||||
Name = "tf-test-dms-replication-task-%[1]s"
|
||||
Update = "updated"
|
||||
Add = "added"
|
||||
}
|
||||
target_endpoint_arn = "${aws_dms_endpoint.dms_endpoint_target.endpoint_arn}"
|
||||
}
|
||||
`, randId)
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func dmsTagsToMap(tags []*dms.Tag) map[string]string {
|
||||
result := make(map[string]string)
|
||||
|
||||
for _, tag := range tags {
|
||||
result[*tag.Key] = *tag.Value
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func dmsTagsFromMap(m map[string]interface{}) []*dms.Tag {
|
||||
result := make([]*dms.Tag, 0, len(m))
|
||||
|
||||
for k, v := range m {
|
||||
result = append(result, &dms.Tag{
|
||||
Key: aws.String(k),
|
||||
Value: aws.String(v.(string)),
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func dmsDiffTags(oldTags, newTags []*dms.Tag) ([]*dms.Tag, []*dms.Tag) {
|
||||
create := make(map[string]interface{})
|
||||
for _, t := range newTags {
|
||||
create[*t.Key] = *t.Value
|
||||
}
|
||||
|
||||
remove := []*dms.Tag{}
|
||||
for _, t := range oldTags {
|
||||
v, ok := create[*t.Key]
|
||||
if !ok || v != *t.Value {
|
||||
remove = append(remove, t)
|
||||
}
|
||||
}
|
||||
|
||||
return dmsTagsFromMap(create), remove
|
||||
}
|
||||
|
||||
func dmsGetTagKeys(tags []*dms.Tag) []*string {
|
||||
keys := []*string{}
|
||||
|
||||
for _, tag := range tags {
|
||||
keys = append(keys, tag.Key)
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
func dmsSetTags(arn string, d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).dmsconn
|
||||
|
||||
if d.HasChange("tags") {
|
||||
oraw, nraw := d.GetChange("tags")
|
||||
o := oraw.(map[string]interface{})
|
||||
n := nraw.(map[string]interface{})
|
||||
|
||||
add, remove := dmsDiffTags(dmsTagsFromMap(o), dmsTagsFromMap(n))
|
||||
|
||||
if len(remove) > 0 {
|
||||
_, err := conn.RemoveTagsFromResource(&dms.RemoveTagsFromResourceInput{
|
||||
ResourceArn: aws.String(arn),
|
||||
TagKeys: dmsGetTagKeys(remove),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(add) > 0 {
|
||||
_, err := conn.AddTagsToResource(&dms.AddTagsToResourceInput{
|
||||
ResourceArn: aws.String(arn),
|
||||
Tags: add,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func TestDmsTagsToMap(t *testing.T) {
|
||||
tags := []*dms.Tag{
|
||||
{
|
||||
Key: aws.String("test-key-1"),
|
||||
Value: aws.String("test-value-1"),
|
||||
},
|
||||
{
|
||||
Key: aws.String("test-key-2"),
|
||||
Value: aws.String("test-value-2"),
|
||||
},
|
||||
}
|
||||
|
||||
result := dmsTagsToMap(tags)
|
||||
|
||||
for _, tag := range tags {
|
||||
if v, ok := result[*tag.Key]; ok {
|
||||
if v != *tag.Value {
|
||||
t.Fatalf("Key %s had value of %s. Expected %s.", *tag.Key, v, *tag.Value)
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Key %s not in map.", *tag.Key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDmsTagsFromMap(t *testing.T) {
|
||||
tagMap := map[string]interface{}{
|
||||
"test-key-1": "test-value-1",
|
||||
"test-key-2": "test-value-2",
|
||||
}
|
||||
|
||||
result := dmsTagsFromMap(tagMap)
|
||||
|
||||
for k, v := range tagMap {
|
||||
found := false
|
||||
for _, tag := range result {
|
||||
if k == *tag.Key {
|
||||
if v != *tag.Value {
|
||||
t.Fatalf("Key %s had value of %s. Expected %s.", k, v, *tag.Value)
|
||||
}
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("Key %s not in tags.", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDmsDiffTags(t *testing.T) {
|
||||
cases := []struct {
|
||||
o, n map[string]interface{}
|
||||
a, r map[string]string
|
||||
}{
|
||||
// basic add / remove
|
||||
{
|
||||
o: map[string]interface{}{"test-key-1": "test-value-1"},
|
||||
n: map[string]interface{}{"test-key-2": "test-value-2"},
|
||||
a: map[string]string{"test-key-2": "test-value-2"},
|
||||
r: map[string]string{"test-key-1": "test-value-1"},
|
||||
},
|
||||
// modify
|
||||
{
|
||||
o: map[string]interface{}{"test-key-1": "test-value-1"},
|
||||
n: map[string]interface{}{"test-key-1": "test-value-1-modified"},
|
||||
a: map[string]string{"test-key-1": "test-value-1-modified"},
|
||||
r: map[string]string{"test-key-1": "test-value-1"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
ar, rr := dmsDiffTags(dmsTagsFromMap(c.o), dmsTagsFromMap(c.n))
|
||||
a := dmsTagsToMap(ar)
|
||||
r := dmsTagsToMap(rr)
|
||||
|
||||
if !reflect.DeepEqual(a, c.a) {
|
||||
t.Fatalf("Add tags mismatch: Actual %#v; Expected %#v", a, c.a)
|
||||
}
|
||||
if !reflect.DeepEqual(r, c.r) {
|
||||
t.Fatalf("Remove tags mismatch: Actual %#v; Expected %#v", r, c.r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDmsGetTagKeys(t *testing.T) {
|
||||
tags := []*dms.Tag{
|
||||
{
|
||||
Key: aws.String("test-key-1"),
|
||||
Value: aws.String("test-value-1"),
|
||||
},
|
||||
{
|
||||
Key: aws.String("test-key-2"),
|
||||
Value: aws.String("test-value-2"),
|
||||
},
|
||||
}
|
||||
|
||||
result := dmsGetTagKeys(tags)
|
||||
expected := []*string{aws.String("test-key-1"), aws.String("test-key-2")}
|
||||
|
||||
if !reflect.DeepEqual(result, expected) {
|
||||
t.Fatalf("Actual %s; Expected %s", aws.StringValueSlice(result), aws.StringValueSlice(expected))
|
||||
}
|
||||
}
|
|
@ -774,6 +774,95 @@ func validateSfnStateMachineName(v interface{}, k string) (ws []string, errors [
|
|||
return
|
||||
}
|
||||
|
||||
func validateDmsCertificateId(v interface{}, k string) (ws []string, es []error) {
|
||||
val := v.(string)
|
||||
|
||||
if len(val) > 255 {
|
||||
es = append(es, fmt.Errorf("%q must not be longer than 255 characters", k))
|
||||
}
|
||||
if !regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9-]+$").MatchString(val) {
|
||||
es = append(es, fmt.Errorf("%q must start with a letter, only contain alphanumeric characters and hyphens", k))
|
||||
}
|
||||
if strings.Contains(val, "--") {
|
||||
es = append(es, fmt.Errorf("%q must not contain consecutive hyphens", k))
|
||||
}
|
||||
if strings.HasSuffix(val, "-") {
|
||||
es = append(es, fmt.Errorf("%q must not end in a hyphen", k))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateDmsEndpointId(v interface{}, k string) (ws []string, es []error) {
|
||||
val := v.(string)
|
||||
|
||||
if len(val) > 255 {
|
||||
es = append(es, fmt.Errorf("%q must not be longer than 255 characters", k))
|
||||
}
|
||||
if !regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9-]+$").MatchString(val) {
|
||||
es = append(es, fmt.Errorf("%q must start with a letter, only contain alphanumeric characters and hyphens", k))
|
||||
}
|
||||
if strings.Contains(val, "--") {
|
||||
es = append(es, fmt.Errorf("%q must not contain consecutive hyphens", k))
|
||||
}
|
||||
if strings.HasSuffix(val, "-") {
|
||||
es = append(es, fmt.Errorf("%q must not end in a hyphen", k))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateDmsReplicationInstanceId(v interface{}, k string) (ws []string, es []error) {
|
||||
val := v.(string)
|
||||
|
||||
if len(val) > 63 {
|
||||
es = append(es, fmt.Errorf("%q must not be longer than 63 characters", k))
|
||||
}
|
||||
if !regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9-]+$").MatchString(val) {
|
||||
es = append(es, fmt.Errorf("%q must start with a letter, only contain alphanumeric characters and hyphens", k))
|
||||
}
|
||||
if strings.Contains(val, "--") {
|
||||
es = append(es, fmt.Errorf("%q must not contain consecutive hyphens", k))
|
||||
}
|
||||
if strings.HasSuffix(val, "-") {
|
||||
es = append(es, fmt.Errorf("%q must not end in a hyphen", k))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateDmsReplicationSubnetGroupId(v interface{}, k string) (ws []string, es []error) {
|
||||
val := v.(string)
|
||||
|
||||
if val == "default" {
|
||||
es = append(es, fmt.Errorf("%q must not be default", k))
|
||||
}
|
||||
if len(val) > 255 {
|
||||
es = append(es, fmt.Errorf("%q must not be longer than 255 characters", k))
|
||||
}
|
||||
if !regexp.MustCompile(`^[a-zA-Z0-9. _-]+$`).MatchString(val) {
|
||||
es = append(es, fmt.Errorf("%q must only contain alphanumeric characters, periods, spaces, underscores and hyphens", k))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateDmsReplicationTaskId(v interface{}, k string) (ws []string, es []error) {
|
||||
val := v.(string)
|
||||
|
||||
if len(val) > 255 {
|
||||
es = append(es, fmt.Errorf("%q must not be longer than 255 characters", k))
|
||||
}
|
||||
if !regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9-]+$").MatchString(val) {
|
||||
es = append(es, fmt.Errorf("%q must start with a letter, only contain alphanumeric characters and hyphens", k))
|
||||
}
|
||||
if strings.Contains(val, "--") {
|
||||
es = append(es, fmt.Errorf("%q must not contain consecutive hyphens", k))
|
||||
}
|
||||
if strings.HasSuffix(val, "-") {
|
||||
es = append(es, fmt.Errorf("%q must not end in a hyphen", k))
|
||||
}
|
||||
|
||||
func validateAppautoscalingScalableDimension(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(string)
|
||||
dimensions := map[string]bool{
|
||||
|
|
|
@ -1386,3 +1386,157 @@ func TestValidateAppautoscalingServiceNamespace(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDmsEndpointId(t *testing.T) {
|
||||
validIds := []string{
|
||||
"tf-test-endpoint-1",
|
||||
"tfTestEndpoint",
|
||||
}
|
||||
|
||||
for _, s := range validIds {
|
||||
_, errors := validateDmsEndpointId(s, "endpoint_id")
|
||||
if len(errors) > 0 {
|
||||
t.Fatalf("%q should be a valid endpoint id: %v", s, errors)
|
||||
}
|
||||
}
|
||||
|
||||
invalidIds := []string{
|
||||
"tf_test_endpoint_1",
|
||||
"tf.test.endpoint.1",
|
||||
"tf test endpoint 1",
|
||||
"tf-test-endpoint-1!",
|
||||
"tf-test-endpoint-1-",
|
||||
"tf-test-endpoint--1",
|
||||
"tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1",
|
||||
}
|
||||
|
||||
for _, s := range invalidIds {
|
||||
_, errors := validateDmsEndpointId(s, "endpoint_id")
|
||||
if len(errors) == 0 {
|
||||
t.Fatalf("%q should not be a valid endpoint id: %v", s, errors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDmsCertificateId(t *testing.T) {
|
||||
validIds := []string{
|
||||
"tf-test-certificate-1",
|
||||
"tfTestEndpoint",
|
||||
}
|
||||
|
||||
for _, s := range validIds {
|
||||
_, errors := validateDmsCertificateId(s, "certificate_id")
|
||||
if len(errors) > 0 {
|
||||
t.Fatalf("%q should be a valid certificate id: %v", s, errors)
|
||||
}
|
||||
}
|
||||
|
||||
invalidIds := []string{
|
||||
"tf_test_certificate_1",
|
||||
"tf.test.certificate.1",
|
||||
"tf test certificate 1",
|
||||
"tf-test-certificate-1!",
|
||||
"tf-test-certificate-1-",
|
||||
"tf-test-certificate--1",
|
||||
"tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1",
|
||||
}
|
||||
|
||||
for _, s := range invalidIds {
|
||||
_, errors := validateDmsEndpointId(s, "certificate_id")
|
||||
if len(errors) == 0 {
|
||||
t.Fatalf("%q should not be a valid certificate id: %v", s, errors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDmsReplicationInstanceId(t *testing.T) {
|
||||
validIds := []string{
|
||||
"tf-test-replication-instance-1",
|
||||
"tfTestReplicaitonInstance",
|
||||
}
|
||||
|
||||
for _, s := range validIds {
|
||||
_, errors := validateDmsReplicationInstanceId(s, "replicaiton_instance_id")
|
||||
if len(errors) > 0 {
|
||||
t.Fatalf("%q should be a valid replication instance id: %v", s, errors)
|
||||
}
|
||||
}
|
||||
|
||||
invalidIds := []string{
|
||||
"tf_test_replication-instance_1",
|
||||
"tf.test.replication.instance.1",
|
||||
"tf test replication instance 1",
|
||||
"tf-test-replication-instance-1!",
|
||||
"tf-test-replication-instance-1-",
|
||||
"tf-test-replication-instance--1",
|
||||
"tf-test-replication-instance-1tf-test-replication-instance-1tf-test-replication-instance-1",
|
||||
}
|
||||
|
||||
for _, s := range invalidIds {
|
||||
_, errors := validateDmsReplicationInstanceId(s, "replication_instance_id")
|
||||
if len(errors) == 0 {
|
||||
t.Fatalf("%q should not be a valid replication instance id: %v", s, errors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDmsReplicationSubnetGroupId(t *testing.T) {
|
||||
validIds := []string{
|
||||
"tf-test-replication-subnet-group-1",
|
||||
"tf_test_replication_subnet_group_1",
|
||||
"tf.test.replication.subnet.group.1",
|
||||
"tf test replication subnet group 1",
|
||||
"tfTestReplicationSubnetGroup",
|
||||
}
|
||||
|
||||
for _, s := range validIds {
|
||||
_, errors := validateDmsReplicationSubnetGroupId(s, "replication_subnet_group_id")
|
||||
if len(errors) > 0 {
|
||||
t.Fatalf("%q should be a valid replication subnet group id: %v", s, errors)
|
||||
}
|
||||
}
|
||||
|
||||
invalidIds := []string{
|
||||
"default",
|
||||
"tf-test-replication-subnet-group-1!",
|
||||
"tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1",
|
||||
}
|
||||
|
||||
for _, s := range invalidIds {
|
||||
_, errors := validateDmsReplicationSubnetGroupId(s, "replication_subnet_group_id")
|
||||
if len(errors) == 0 {
|
||||
t.Fatalf("%q should not be a valid replication subnet group id: %v", s, errors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDmsReplicationTaskId(t *testing.T) {
|
||||
validIds := []string{
|
||||
"tf-test-replication-task-1",
|
||||
"tfTestReplicationTask",
|
||||
}
|
||||
|
||||
for _, s := range validIds {
|
||||
_, errors := validateDmsReplicationTaskId(s, "replication_task_id")
|
||||
if len(errors) > 0 {
|
||||
t.Fatalf("%q should be a valid replication task id: %v", s, errors)
|
||||
}
|
||||
}
|
||||
|
||||
invalidIds := []string{
|
||||
"tf_test_replication_task_1",
|
||||
"tf.test.replication.task.1",
|
||||
"tf test replication task 1",
|
||||
"tf-test-replication-task-1!",
|
||||
"tf-test-replication-task-1-",
|
||||
"tf-test-replication-task--1",
|
||||
"tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1",
|
||||
}
|
||||
|
||||
for _, s := range invalidIds {
|
||||
_, errors := validateDmsReplicationTaskId(s, "replication_task_id")
|
||||
if len(errors) == 0 {
|
||||
t.Fatalf("%q should not be a valid replication task id: %v", s, errors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
7100
vendor/github.com/aws/aws-sdk-go/service/databasemigrationservice/api.go
generated
vendored
Normal file
7100
vendor/github.com/aws/aws-sdk-go/service/databasemigrationservice/api.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
99
vendor/github.com/aws/aws-sdk-go/service/databasemigrationservice/service.go
generated
vendored
Normal file
99
vendor/github.com/aws/aws-sdk-go/service/databasemigrationservice/service.go
generated
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||
|
||||
package databasemigrationservice
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/client"
|
||||
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/aws/signer/v4"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/jsonrpc"
|
||||
)
|
||||
|
||||
// AWS Database Migration Service (AWS DMS) can migrate your data to and from
|
||||
// the most widely used commercial and open-source databases such as Oracle,
|
||||
// PostgreSQL, Microsoft SQL Server, Amazon Redshift, MariaDB, Amazon Aurora,
|
||||
// MySQL, and SAP Adaptive Server Enterprise (ASE). The service supports homogeneous
|
||||
// migrations such as Oracle to Oracle, as well as heterogeneous migrations
|
||||
// between different database platforms, such as Oracle to MySQL or SQL Server
|
||||
// to PostgreSQL.
|
||||
// The service client's operations are safe to be used concurrently.
|
||||
// It is not safe to mutate any of the client's properties though.
|
||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/dms-2016-01-01
|
||||
type DatabaseMigrationService struct {
|
||||
*client.Client
|
||||
}
|
||||
|
||||
// Used for custom client initialization logic
|
||||
var initClient func(*client.Client)
|
||||
|
||||
// Used for custom request initialization logic
|
||||
var initRequest func(*request.Request)
|
||||
|
||||
// Service information constants
|
||||
const (
|
||||
ServiceName = "dms" // Service endpoint prefix API calls made to.
|
||||
EndpointsID = ServiceName // Service ID for Regions and Endpoints metadata.
|
||||
)
|
||||
|
||||
// New creates a new instance of the DatabaseMigrationService client with a session.
|
||||
// If additional configuration is needed for the client instance use the optional
|
||||
// aws.Config parameter to add your extra config.
|
||||
//
|
||||
// Example:
|
||||
// // Create a DatabaseMigrationService client from just a session.
|
||||
// svc := databasemigrationservice.New(mySession)
|
||||
//
|
||||
// // Create a DatabaseMigrationService client with additional configuration
|
||||
// svc := databasemigrationservice.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
|
||||
func New(p client.ConfigProvider, cfgs ...*aws.Config) *DatabaseMigrationService {
|
||||
c := p.ClientConfig(EndpointsID, cfgs...)
|
||||
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName)
|
||||
}
|
||||
|
||||
// newClient creates, initializes and returns a new service client instance.
|
||||
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *DatabaseMigrationService {
|
||||
svc := &DatabaseMigrationService{
|
||||
Client: client.New(
|
||||
cfg,
|
||||
metadata.ClientInfo{
|
||||
ServiceName: ServiceName,
|
||||
SigningName: signingName,
|
||||
SigningRegion: signingRegion,
|
||||
Endpoint: endpoint,
|
||||
APIVersion: "2016-01-01",
|
||||
JSONVersion: "1.1",
|
||||
TargetPrefix: "AmazonDMSv20160101",
|
||||
},
|
||||
handlers,
|
||||
),
|
||||
}
|
||||
|
||||
// Handlers
|
||||
svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
|
||||
svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler)
|
||||
svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler)
|
||||
svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler)
|
||||
svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler)
|
||||
|
||||
// Run custom client initialization if present
|
||||
if initClient != nil {
|
||||
initClient(svc.Client)
|
||||
}
|
||||
|
||||
return svc
|
||||
}
|
||||
|
||||
// newRequest creates a new request for a DatabaseMigrationService operation and runs any
|
||||
// custom request initialization.
|
||||
func (c *DatabaseMigrationService) newRequest(op *request.Operation, params, data interface{}) *request.Request {
|
||||
req := c.NewRequest(op, params, data)
|
||||
|
||||
// Run custom request initialization if present
|
||||
if initRequest != nil {
|
||||
initRequest(req)
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
|
@ -788,6 +788,14 @@
|
|||
"version": "v1.6.18",
|
||||
"versionExact": "v1.6.18"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "xKUp9QOvMJOavwFwnbLcqq1FxOE=",
|
||||
"path": "github.com/aws/aws-sdk-go/service/databasemigrationservice",
|
||||
"revision": "f82d132783af109928d89d526ccc8d9fc320639e",
|
||||
"revisionTime": "2017-01-19T23:36:13Z",
|
||||
"version": "v1.6.14",
|
||||
"versionExact": "v1.6.14"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "W29S9x3pVL3xha1nsGqGtSQtGwA=",
|
||||
"path": "github.com/aws/aws-sdk-go/service/directoryservice",
|
||||
|
|
|
@ -41,6 +41,11 @@ To make a resource importable, please see the
|
|||
* aws_db_parameter_group
|
||||
* aws_db_security_group
|
||||
* aws_db_subnet_group
|
||||
* aws_dms_certificate
|
||||
* aws_dms_endpoint
|
||||
* aws_dms_replication_instance
|
||||
* aws_dms_replication_subnet_group
|
||||
* aws_dms_replication_task
|
||||
* aws_dynamodb_table
|
||||
* aws_ebs_volume
|
||||
* aws_ecr_repository
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_dms_certificate"
|
||||
sidebar_current: "docs-aws-resource-dms-certificate"
|
||||
description: |-
|
||||
Provides a DMS (Data Migration Service) certificate resource.
|
||||
---
|
||||
|
||||
# aws\_dms\_certificate
|
||||
|
||||
Provides a DMS (Data Migration Service) certificate resource. DMS certificates can be created, deleted, and imported.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
# Create a new certificate
|
||||
resource "aws_dms_certificate" "test" {
|
||||
certificate_id = "test-dms-certificate-tf"
|
||||
certificate_pem = "..."
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `certificate_id` - (Required) The certificate identifier.
|
||||
|
||||
- Must contain from 1 to 255 alphanumeric characters and hyphens.
|
||||
|
||||
* `certificate_pem` - (Optional) The contents of the .pem X.509 certificate file for the certificate. Either `certificate_pem` or `certificate_wallet` must be set.
|
||||
* `certificate_wallet` - (Optional) The contents of the Oracle Wallet certificate for use with SSL. Either `certificate_pem` or `certificate_wallet` must be set.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `certificate_arn` - The Amazon Resource Name (ARN) for the certificate.
|
||||
|
||||
## Import
|
||||
|
||||
Certificates can be imported using the `certificate_arn`, e.g.
|
||||
|
||||
```
|
||||
$ terraform import aws_dms_certificate.test arn:aws:dms:us-west-2:123456789:cert:xxxxxxxxxx
|
||||
```
|
|
@ -0,0 +1,73 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_dms_endpoint"
|
||||
sidebar_current: "docs-aws-resource-dms-endpoint"
|
||||
description: |-
|
||||
Provides a DMS (Data Migration Service) endpoint resource.
|
||||
---
|
||||
|
||||
# aws\_dms\_endpoint
|
||||
|
||||
Provides a DMS (Data Migration Service) endpoint resource. DMS endpoints can be created, updated, deleted, and imported.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
# Create a new endpoint
|
||||
resource "aws_dms_endpoint" "test" {
|
||||
certificate_arn = "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012"
|
||||
database_name = "test"
|
||||
endpoint_id = "test-dms-endpoint-tf"
|
||||
endpoint_type = "source"
|
||||
engine_name = "aurora"
|
||||
extra_connection_attributes = ""
|
||||
kms_key_arn = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
|
||||
password = "test"
|
||||
port = 3306
|
||||
server_name = "test"
|
||||
ssl_mode = "none"
|
||||
tags {
|
||||
Name = "test"
|
||||
}
|
||||
username = "test"
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `certificate_arn` - (Optional, Default: empty string) The Amazon Resource Name (ARN) for the certificate.
|
||||
* `database_name` - (Optional, Default: empty string) The name of the endpoint database.
|
||||
* `endpoint_id` - (Required) The database endpoint identifier.
|
||||
|
||||
- Must contain from 1 to 255 alphanumeric characters or hyphens.
|
||||
- Must begin with a letter
|
||||
- Must contain only ASCII letters, digits, and hyphens
|
||||
- Must not end with a hyphen
|
||||
- Must not contain two consecutive hyphens
|
||||
|
||||
* `endpoint_type` - (Required) The type of endpoint. Can be one of `source | target`.
|
||||
* `engine_name` - (Required) The type of engine for the endpoint. Can be one of `mysql | oracle | postgres | mariadb | aurora | redshift | sybase | sqlserver`.
|
||||
* `extra_connection_attributes` - (Optional) Additional attributes associated with the connection. For available attributes see [Using Extra Connection Attributes with AWS Database Migration Service](http://docs.aws.amazon.com/dms/latest/userguide/CHAP_Introduction.ConnectionAttributes.html).
|
||||
* `kms_key_arn` - (Optional) The Amazon Resource Name (ARN) for the KMS key that will be used to encrypt the connection parameters. If you do not specify a value for `kms_key_arn`, then AWS DMS will use your default encryption key. AWS KMS creates the default encryption key for your AWS account. Your AWS account has a different default encryption key for each AWS region.
|
||||
* `password` - (Required) The password to be used to login to the endpoint database.
|
||||
* `port` - (Required) The port used by the endpoint database.
|
||||
* `server_name` - (Required) The host name of the server.
|
||||
* `ssl_mode` - (Optional, Default: none) The SSL mode to use for the connection. Can be one of `none | require | verify-ca | verify-full`
|
||||
* `tags` - (Optional) A mapping of tags to assign to the resource.
|
||||
* `username` - (Required) The user name to be used to login to the endpoint database.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `endpoint_arn` - The Amazon Resource Name (ARN) for the endpoint.
|
||||
|
||||
## Import
|
||||
|
||||
Endpoints can be imported using the `endpoint_id`, e.g.
|
||||
|
||||
```
|
||||
$ terraform import aws_dms_endpoint.test test-dms-endpoint-tf
|
||||
```
|
|
@ -0,0 +1,84 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_dms_replication_instance"
|
||||
sidebar_current: "docs-aws-resource-dms-replication-instance"
|
||||
description: |-
|
||||
Provides a DMS (Data Migration Service) replication instance resource.
|
||||
---
|
||||
|
||||
# aws\_dms\_replication\_instance
|
||||
|
||||
Provides a DMS (Data Migration Service) replication instance resource. DMS replication instances can be created, updated, deleted, and imported.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
# Create a new replication instance
|
||||
resource "aws_dms_replication_instance" "test" {
|
||||
allocated_storage = 20
|
||||
apply_immediately = true
|
||||
auto_minor_version_upgrade = true
|
||||
availability_zone = "us-west-2c"
|
||||
engine_version = "1.9.0"
|
||||
kms_key_arn = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
|
||||
multi_az = false
|
||||
preferred_maintenance_window = "sun:10:30-sun:14:30"
|
||||
publicly_accessible = true
|
||||
replication_instance_class = "dms.t2.micro"
|
||||
replication_instance_id = "test-dms-replication-instance-tf"
|
||||
replication_subnet_group_id = "${aws_dms_replication_subnet_group.test-dms-replication-subnet-group-tf}"
|
||||
tags {
|
||||
Name = "test"
|
||||
}
|
||||
vpc_security_group_ids = [
|
||||
"sg-12345678",
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `allocated_storage` - (Optional, Default: 50, Min: 5, Max: 6144) The amount of storage (in gigabytes) to be initially allocated for the replication instance.
|
||||
* `apply_immediately` - (Optional, Default: false) Indicates whether the changes should be applied immediately or during the next maintenance window. Only used when updating an existing resource.
|
||||
* `auto_minor_version_upgrade` - (Optional, Default: false) Indicates that minor engine upgrades will be applied automatically to the replication instance during the maintenance window.
|
||||
* `availability_zone` - (Optional) The EC2 Availability Zone that the replication instance will be created in.
|
||||
* `engine_version` - (Optional) The engine version number of the replication instance.
|
||||
* `kms_key_arn` - (Optional) The Amazon Resource Name (ARN) for the KMS key that will be used to encrypt the connection parameters. If you do not specify a value for `kms_key_arn`, then AWS DMS will use your default encryption key. AWS KMS creates the default encryption key for your AWS account. Your AWS account has a different default encryption key for each AWS region.
|
||||
* `multi_az` - (Optional) Specifies if the replication instance is a multi-az deployment. You cannot set the `availability_zone` parameter if the `multi_az` parameter is set to `true`.
|
||||
* `preferred_maintenance_window` - (Optional) The weekly time range during which system maintenance can occur, in Universal Coordinated Time (UTC).
|
||||
|
||||
- Default: A 30-minute window selected at random from an 8-hour block of time per region, occurring on a random day of the week.
|
||||
- Format: `ddd:hh24:mi-ddd:hh24:mi`
|
||||
- Valid Days: `mon, tue, wed, thu, fri, sat, sun`
|
||||
- Constraints: Minimum 30-minute window.
|
||||
|
||||
* `publicly_accessible` - (Optional, Default: false) Specifies the accessibility options for the replication instance. A value of true represents an instance with a public IP address. A value of false represents an instance with a private IP address.
|
||||
* `replication_instance_class` - (Required) The compute and memory capacity of the replication instance as specified by the replication instance class. Can be one of `dms.t2.micro | dms.t2.small | dms.t2.medium | dms.t2.large | dms.c4.large | dms.c4.xlarge | dms.c4.2xlarge | dms.c4.4xlarge`
|
||||
* `replication_instance_id` - (Required) The replication instance identifier. This parameter is stored as a lowercase string.
|
||||
|
||||
- Must contain from 1 to 63 alphanumeric characters or hyphens.
|
||||
- First character must be a letter.
|
||||
- Cannot end with a hyphen
|
||||
- Cannot contain two consecutive hyphens.
|
||||
|
||||
* `replication_subnet_group_id` - (Optional) A subnet group to associate with the replication instance.
|
||||
* `tags` - (Optional) A mapping of tags to assign to the resource.
|
||||
* `vpc_security_group_ids` - (Optional) A list of VPC security group IDs to be used with the replication instance. The VPC security groups must work with the VPC containing the replication instance.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `replication_instance_arn` - The Amazon Resource Name (ARN) of the replication instance.
|
||||
* `replication_instance_private_ips` - A list of the private IP addresses of the replication instance.
|
||||
* `replication_instance_public_ips` - A list of the public IP addresses of the replication instance.
|
||||
|
||||
## Import
|
||||
|
||||
Replication instances can be imported using the `replication_instance_id`, e.g.
|
||||
|
||||
```
|
||||
$ terraform import aws_dms_replication_instance.test test-dms-replication-instance-tf
|
||||
```
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_dms_replication_subnet_group"
|
||||
sidebar_current: "docs-aws-resource-dms-replication-subnet-group"
|
||||
description: |-
|
||||
Provides a DMS (Data Migration Service) subnet group resource.
|
||||
---
|
||||
|
||||
# aws\_dms\_replication\_subnet\_group
|
||||
|
||||
Provides a DMS (Data Migration Service) replication subnet group resource. DMS replication subnet groups can be created, updated, deleted, and imported.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
# Create a new replication subnet group
|
||||
resource "aws_dms_replication_subnet_group" "test" {
|
||||
replication_subnet_group_description = "Test replication subnet group"
|
||||
replication_subnet_group_id = "test-dms-replication-subnet-group-tf"
|
||||
subnet_ids = [
|
||||
"subnet-12345678",
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `replication_subnet_group_description` - (Required) The description for the subnet group.
|
||||
* `replication_subnet_group_id` - (Required) The name for the replication subnet group. This value is stored as a lowercase string.
|
||||
|
||||
- Must contain no more than 255 alphanumeric characters, periods, spaces, underscores, or hyphens.
|
||||
- Must not be "default".
|
||||
|
||||
* `subnet_ids` - (Required) A list of the EC2 subnet IDs for the subnet group.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `vpc_id` - The ID of the VPC the subnet group is in.
|
||||
|
||||
## Import
|
||||
|
||||
Replication subnet groups can be imported using the `replication_subnet_group_id`, e.g.
|
||||
|
||||
```
|
||||
$ terraform import aws_dms_replication_subnet_group.test test-dms-replication-subnet-group-tf
|
||||
```
|
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_dms_replication_task"
|
||||
sidebar_current: "docs-aws-resource-dms-replication-task"
|
||||
description: |-
|
||||
Provides a DMS (Data Migration Service) replication task resource.
|
||||
---
|
||||
|
||||
# aws\_dms\_replication\_task
|
||||
|
||||
Provides a DMS (Data Migration Service) replication task resource. DMS replication tasks can be created, updated, deleted, and imported.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
# Create a new replication task
|
||||
resource "aws_dms_replication_task" "test" {
|
||||
cdc_start_time = 1484346880
|
||||
migration_type = "full-load"
|
||||
replication_instance_arn = "${aws_dms_replication_instance.test-dms-replication-instance-tf.replication_instance_arn}"
|
||||
replication_task_id = "test-dms-replication-task-tf"
|
||||
replication_task_settings = "..."
|
||||
source_endpoint_arn = "${aws_dms_endpoint.test-dms-source-endpoint-tf.endpoint_arn}"
|
||||
table_mappings = "{\"rules\":[{\"rule-type\":\"selection\",\"rule-id\":\"1\",\"rule-name\":\"1\",\"object-locator\":{\"schema-name\":\"%\",\"table-name\":\"%\"},\"rule-action\":\"include\"}]}"
|
||||
tags {
|
||||
Name = "test"
|
||||
}
|
||||
target_endpoint_arn = "${aws_dms_endpoint.test-dms-target-endpoint-tf.endpoint_arn}"
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `cdc_start_time` - (Optional) The Unix timestamp integer for the start of the Change Data Capture (CDC) operation.
|
||||
* `migration_type` - (Required) The migration type. Can be one of `full-load | cdc | full-load-and-cdc`.
|
||||
* `replication_instance_arn` - (Required) The Amazon Resource Name (ARN) of the replication instance.
|
||||
* `replication_task_id` - (Required) The replication task identifier.
|
||||
|
||||
- Must contain from 1 to 255 alphanumeric characters or hyphens.
|
||||
- First character must be a letter.
|
||||
- Cannot end with a hyphen.
|
||||
- Cannot contain two consecutive hyphens.
|
||||
|
||||
* `replication_task_settings` - (Optional) An escaped JSON string that contains the task settings. For a complete list of task settings, see [Task Settings for AWS Database Migration Service Tasks](http://docs.aws.amazon.com/dms/latest/userguide/CHAP_Tasks.CustomizingTasks.TaskSettings.html).
|
||||
* `source_endpoint_arn` - (Required) The Amazon Resource Name (ARN) string that uniquely identifies the source endpoint.
|
||||
* `table_mappings` - (Required) An escaped JSON string that contains the table mappings. For information on table mapping see [Using Table Mapping with an AWS Database Migration Service Task to Select and Filter Data](http://docs.aws.amazon.com/dms/latest/userguide/CHAP_Tasks.CustomizingTasks.TableMapping.html)
|
||||
* `tags` - (Optional) A mapping of tags to assign to the resource.
|
||||
* `target_endpoint_arn` - (Required) The Amazon Resource Name (ARN) string that uniquely identifies the target endpoint.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `replication_task_arn` - The Amazon Resource Name (ARN) for the replication task.
|
||||
|
||||
## Import
|
||||
|
||||
Replication tasks can be imported using the `replication_task_id`, e.g.
|
||||
|
||||
```
|
||||
$ terraform import aws_dms_replication_task.test test-dms-replication-task-tf
|
||||
```
|
|
@ -278,6 +278,33 @@
|
|||
</ul>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current(/^docs-aws-resource-dms/) %>>
|
||||
<a href="#">Database Migration Service</a>
|
||||
<ul class="nav nav-visible">
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-dms-certificate") %>>
|
||||
<a href="/docs/providers/aws/r/dms_certificate.html">aws_dms_certificate</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-dms-endpoint") %>>
|
||||
<a href="/docs/providers/aws/r/dms_endpoint.html">aws_dms_endpoint</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-dms-replication-instance") %>>
|
||||
<a href="/docs/providers/aws/r/dms_replication_instance.html">aws_dms_replication_instance</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-dms-replication-subnet-group") %>>
|
||||
<a href="/docs/providers/aws/r/dms_replication_subnet_group.html">aws_dms_replication_subnet_group</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-dms-replication-task") %>>
|
||||
<a href="/docs/providers/aws/r/dms_replication_task.html">aws_dms_replication_task</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current(/^docs-aws-resource-directory-service/) %>>
|
||||
<a href="#">Directory Service Resources</a>
|
||||
<ul class="nav nav-visible">
|
||||
|
|
Loading…
Reference in New Issue