Skip to content

Commit

Permalink
provider/aws: Add AWS DMS (data migration service) resources (hashico…
Browse files Browse the repository at this point in the history
…rp#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.
  • Loading branch information
jzbruno authored and arcadiatea committed Feb 7, 2017
1 parent 9d621b9 commit 86cd872
Show file tree
Hide file tree
Showing 26 changed files with 10,480 additions and 0 deletions.
3 changes: 3 additions & 0 deletions builtin/providers/aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions builtin/providers/aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
138 changes: 138 additions & 0 deletions builtin/providers/aws/resource_aws_dms_certificate.go
Original file line number Diff line number Diff line change
@@ -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
}
103 changes: 103 additions & 0 deletions builtin/providers/aws/resource_aws_dms_certificate_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
Loading

0 comments on commit 86cd872

Please sign in to comment.