github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/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 }