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, Optional: 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{ EndpointIdentifier: aws.String(d.Get("endpoint_id").(string)), EndpointType: aws.String(d.Get("endpoint_type").(string)), EngineName: aws.String(d.Get("engine_name").(string)), Password: aws.String(d.Get("password").(string)), Port: aws.Int64(int64(d.Get("port").(int))), ServerName: aws.String(d.Get("server_name").(string)), Tags: dmsTagsFromMap(d.Get("tags").(map[string]interface{})), Username: aws.String(d.Get("username").(string)), } if v, ok := d.GetOk("database_name"); ok { request.DatabaseName = aws.String(v.(string)) } if 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() }