github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/builtin/providers/aws/resource_aws_dms_replication_task.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strconv"
     7  	"time"
     8  
     9  	"github.com/aws/aws-sdk-go/aws"
    10  	"github.com/aws/aws-sdk-go/aws/awserr"
    11  	dms "github.com/aws/aws-sdk-go/service/databasemigrationservice"
    12  	"github.com/hashicorp/terraform/helper/resource"
    13  	"github.com/hashicorp/terraform/helper/schema"
    14  	"github.com/hashicorp/terraform/helper/validation"
    15  )
    16  
    17  func resourceAwsDmsReplicationTask() *schema.Resource {
    18  	return &schema.Resource{
    19  		Create: resourceAwsDmsReplicationTaskCreate,
    20  		Read:   resourceAwsDmsReplicationTaskRead,
    21  		Update: resourceAwsDmsReplicationTaskUpdate,
    22  		Delete: resourceAwsDmsReplicationTaskDelete,
    23  
    24  		Importer: &schema.ResourceImporter{
    25  			State: schema.ImportStatePassthrough,
    26  		},
    27  
    28  		Schema: map[string]*schema.Schema{
    29  			"cdc_start_time": {
    30  				Type:     schema.TypeString,
    31  				Optional: true,
    32  				// Requires a Unix timestamp in seconds. Example 1484346880
    33  			},
    34  			"migration_type": {
    35  				Type:     schema.TypeString,
    36  				Required: true,
    37  				ValidateFunc: validation.StringInSlice([]string{
    38  					"full-load",
    39  					"cdc",
    40  					"full-load-and-cdc",
    41  				}, false),
    42  			},
    43  			"replication_instance_arn": {
    44  				Type:         schema.TypeString,
    45  				Required:     true,
    46  				ForceNew:     true,
    47  				ValidateFunc: validateArn,
    48  			},
    49  			"replication_task_arn": {
    50  				Type:     schema.TypeString,
    51  				Computed: true,
    52  			},
    53  			"replication_task_id": {
    54  				Type:         schema.TypeString,
    55  				Required:     true,
    56  				ForceNew:     true,
    57  				ValidateFunc: validateDmsReplicationTaskId,
    58  			},
    59  			"replication_task_settings": {
    60  				Type:             schema.TypeString,
    61  				Optional:         true,
    62  				ValidateFunc:     validateJsonString,
    63  				DiffSuppressFunc: suppressEquivalentJsonDiffs,
    64  			},
    65  			"source_endpoint_arn": {
    66  				Type:         schema.TypeString,
    67  				Required:     true,
    68  				ForceNew:     true,
    69  				ValidateFunc: validateArn,
    70  			},
    71  			"table_mappings": {
    72  				Type:             schema.TypeString,
    73  				Required:         true,
    74  				ValidateFunc:     validateJsonString,
    75  				DiffSuppressFunc: suppressEquivalentJsonDiffs,
    76  			},
    77  			"tags": {
    78  				Type:     schema.TypeMap,
    79  				Optional: true,
    80  			},
    81  			"target_endpoint_arn": {
    82  				Type:         schema.TypeString,
    83  				Required:     true,
    84  				ForceNew:     true,
    85  				ValidateFunc: validateArn,
    86  			},
    87  		},
    88  	}
    89  }
    90  
    91  func resourceAwsDmsReplicationTaskCreate(d *schema.ResourceData, meta interface{}) error {
    92  	conn := meta.(*AWSClient).dmsconn
    93  
    94  	request := &dms.CreateReplicationTaskInput{
    95  		MigrationType:             aws.String(d.Get("migration_type").(string)),
    96  		ReplicationInstanceArn:    aws.String(d.Get("replication_instance_arn").(string)),
    97  		ReplicationTaskIdentifier: aws.String(d.Get("replication_task_id").(string)),
    98  		SourceEndpointArn:         aws.String(d.Get("source_endpoint_arn").(string)),
    99  		TableMappings:             aws.String(d.Get("table_mappings").(string)),
   100  		Tags:                      dmsTagsFromMap(d.Get("tags").(map[string]interface{})),
   101  		TargetEndpointArn:         aws.String(d.Get("target_endpoint_arn").(string)),
   102  	}
   103  
   104  	if v, ok := d.GetOk("cdc_start_time"); ok {
   105  		seconds, err := strconv.ParseInt(v.(string), 10, 64)
   106  		if err != nil {
   107  			return fmt.Errorf("[ERROR] DMS create replication task. Invalid CDC Unix timestamp: %s", err)
   108  		}
   109  		request.CdcStartTime = aws.Time(time.Unix(seconds, 0))
   110  	}
   111  
   112  	if v, ok := d.GetOk("replication_task_settings"); ok {
   113  		request.ReplicationTaskSettings = aws.String(v.(string))
   114  	}
   115  
   116  	log.Println("[DEBUG] DMS create replication task:", request)
   117  
   118  	_, err := conn.CreateReplicationTask(request)
   119  	if err != nil {
   120  		return err
   121  	}
   122  
   123  	taskId := d.Get("replication_task_id").(string)
   124  	d.SetId(taskId)
   125  
   126  	stateConf := &resource.StateChangeConf{
   127  		Pending:    []string{"creating"},
   128  		Target:     []string{"ready"},
   129  		Refresh:    resourceAwsDmsReplicationTaskStateRefreshFunc(d, meta),
   130  		Timeout:    d.Timeout(schema.TimeoutCreate),
   131  		MinTimeout: 10 * time.Second,
   132  		Delay:      30 * time.Second, // Wait 30 secs before starting
   133  	}
   134  
   135  	// Wait, catching any errors
   136  	_, err = stateConf.WaitForState()
   137  	if err != nil {
   138  		return err
   139  	}
   140  
   141  	return resourceAwsDmsReplicationTaskRead(d, meta)
   142  }
   143  
   144  func resourceAwsDmsReplicationTaskRead(d *schema.ResourceData, meta interface{}) error {
   145  	conn := meta.(*AWSClient).dmsconn
   146  
   147  	response, err := conn.DescribeReplicationTasks(&dms.DescribeReplicationTasksInput{
   148  		Filters: []*dms.Filter{
   149  			{
   150  				Name:   aws.String("replication-task-id"),
   151  				Values: []*string{aws.String(d.Id())}, // Must use d.Id() to work with import.
   152  			},
   153  		},
   154  	})
   155  	if err != nil {
   156  		if dmserr, ok := err.(awserr.Error); ok && dmserr.Code() == "ResourceNotFoundFault" {
   157  			log.Printf("[DEBUG] DMS Replication Task %q Not Found", d.Id())
   158  			d.SetId("")
   159  			return nil
   160  		}
   161  		return err
   162  	}
   163  
   164  	err = resourceAwsDmsReplicationTaskSetState(d, response.ReplicationTasks[0])
   165  	if err != nil {
   166  		return err
   167  	}
   168  
   169  	tagsResp, err := conn.ListTagsForResource(&dms.ListTagsForResourceInput{
   170  		ResourceArn: aws.String(d.Get("replication_task_arn").(string)),
   171  	})
   172  	if err != nil {
   173  		return err
   174  	}
   175  	d.Set("tags", dmsTagsToMap(tagsResp.TagList))
   176  
   177  	return nil
   178  }
   179  
   180  func resourceAwsDmsReplicationTaskUpdate(d *schema.ResourceData, meta interface{}) error {
   181  	conn := meta.(*AWSClient).dmsconn
   182  
   183  	request := &dms.ModifyReplicationTaskInput{
   184  		ReplicationTaskArn: aws.String(d.Get("replication_task_arn").(string)),
   185  	}
   186  	hasChanges := false
   187  
   188  	if d.HasChange("cdc_start_time") {
   189  		seconds, err := strconv.ParseInt(d.Get("cdc_start_time").(string), 10, 64)
   190  		if err != nil {
   191  			return fmt.Errorf("[ERROR] DMS update replication task. Invalid CRC Unix timestamp: %s", err)
   192  		}
   193  		request.CdcStartTime = aws.Time(time.Unix(seconds, 0))
   194  		hasChanges = true
   195  	}
   196  
   197  	if d.HasChange("migration_type") {
   198  		request.MigrationType = aws.String(d.Get("migration_type").(string))
   199  		hasChanges = true
   200  	}
   201  
   202  	if d.HasChange("replication_task_settings") {
   203  		request.ReplicationTaskSettings = aws.String(d.Get("replication_task_settings").(string))
   204  		hasChanges = true
   205  	}
   206  
   207  	if d.HasChange("table_mappings") {
   208  		request.TableMappings = aws.String(d.Get("table_mappings").(string))
   209  		hasChanges = true
   210  	}
   211  
   212  	if d.HasChange("tags") {
   213  		err := dmsSetTags(d.Get("replication_task_arn").(string), d, meta)
   214  		if err != nil {
   215  			return err
   216  		}
   217  	}
   218  
   219  	if hasChanges {
   220  		log.Println("[DEBUG] DMS update replication task:", request)
   221  
   222  		_, err := conn.ModifyReplicationTask(request)
   223  		if err != nil {
   224  			return err
   225  		}
   226  
   227  		stateConf := &resource.StateChangeConf{
   228  			Pending:    []string{"modifying"},
   229  			Target:     []string{"ready", "stopped", "failed"},
   230  			Refresh:    resourceAwsDmsReplicationTaskStateRefreshFunc(d, meta),
   231  			Timeout:    d.Timeout(schema.TimeoutCreate),
   232  			MinTimeout: 10 * time.Second,
   233  			Delay:      30 * time.Second, // Wait 30 secs before starting
   234  		}
   235  
   236  		// Wait, catching any errors
   237  		_, err = stateConf.WaitForState()
   238  		if err != nil {
   239  			return err
   240  		}
   241  
   242  		return resourceAwsDmsReplicationTaskRead(d, meta)
   243  	}
   244  
   245  	return nil
   246  }
   247  
   248  func resourceAwsDmsReplicationTaskDelete(d *schema.ResourceData, meta interface{}) error {
   249  	conn := meta.(*AWSClient).dmsconn
   250  
   251  	request := &dms.DeleteReplicationTaskInput{
   252  		ReplicationTaskArn: aws.String(d.Get("replication_task_arn").(string)),
   253  	}
   254  
   255  	log.Printf("[DEBUG] DMS delete replication task: %#v", request)
   256  
   257  	_, err := conn.DeleteReplicationTask(request)
   258  	if err != nil {
   259  		if dmserr, ok := err.(awserr.Error); ok && dmserr.Code() == "ResourceNotFoundFault" {
   260  			log.Printf("[DEBUG] DMS Replication Task %q Not Found", d.Id())
   261  			d.SetId("")
   262  			return nil
   263  		}
   264  		return err
   265  	}
   266  
   267  	stateConf := &resource.StateChangeConf{
   268  		Pending:    []string{"deleting"},
   269  		Target:     []string{},
   270  		Refresh:    resourceAwsDmsReplicationTaskStateRefreshFunc(d, meta),
   271  		Timeout:    d.Timeout(schema.TimeoutCreate),
   272  		MinTimeout: 10 * time.Second,
   273  		Delay:      30 * time.Second, // Wait 30 secs before starting
   274  	}
   275  
   276  	// Wait, catching any errors
   277  	_, err = stateConf.WaitForState()
   278  	if err != nil {
   279  		return err
   280  	}
   281  
   282  	return nil
   283  }
   284  
   285  func resourceAwsDmsReplicationTaskSetState(d *schema.ResourceData, task *dms.ReplicationTask) error {
   286  	d.SetId(*task.ReplicationTaskIdentifier)
   287  
   288  	d.Set("migration_type", task.MigrationType)
   289  	d.Set("replication_instance_arn", task.ReplicationInstanceArn)
   290  	d.Set("replication_task_arn", task.ReplicationTaskArn)
   291  	d.Set("replication_task_id", task.ReplicationTaskIdentifier)
   292  	d.Set("replication_task_settings", task.ReplicationTaskSettings)
   293  	d.Set("source_endpoint_arn", task.SourceEndpointArn)
   294  	d.Set("table_mappings", task.TableMappings)
   295  	d.Set("target_endpoint_arn", task.TargetEndpointArn)
   296  
   297  	return nil
   298  }
   299  
   300  func resourceAwsDmsReplicationTaskStateRefreshFunc(
   301  	d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc {
   302  	return func() (interface{}, string, error) {
   303  		conn := meta.(*AWSClient).dmsconn
   304  
   305  		v, err := conn.DescribeReplicationTasks(&dms.DescribeReplicationTasksInput{
   306  			Filters: []*dms.Filter{
   307  				{
   308  					Name:   aws.String("replication-task-id"),
   309  					Values: []*string{aws.String(d.Id())}, // Must use d.Id() to work with import.
   310  				},
   311  			},
   312  		})
   313  		if err != nil {
   314  			if dmserr, ok := err.(awserr.Error); ok && dmserr.Code() == "ResourceNotFoundFault" {
   315  				return nil, "", nil
   316  			}
   317  			log.Printf("Error on retrieving DMS Replication Task when waiting: %s", err)
   318  			return nil, "", err
   319  		}
   320  
   321  		if v == nil {
   322  			return nil, "", nil
   323  		}
   324  
   325  		if v.ReplicationTasks != nil {
   326  			log.Printf("[DEBUG] DMS Replication Task status for instance %s: %s", d.Id(), *v.ReplicationTasks[0].Status)
   327  		}
   328  
   329  		return v, *v.ReplicationTasks[0].Status, nil
   330  	}
   331  }