github.com/simonswine/terraform@v0.9.0-beta2/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 "github.com/aws/aws-sdk-go/private/waiter" 12 dms "github.com/aws/aws-sdk-go/service/databasemigrationservice" 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.TypeInt, 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 }, 64 "source_endpoint_arn": { 65 Type: schema.TypeString, 66 Required: true, 67 ForceNew: true, 68 ValidateFunc: validateArn, 69 }, 70 "table_mappings": { 71 Type: schema.TypeString, 72 Required: true, 73 ValidateFunc: validateJsonString, 74 }, 75 "tags": { 76 Type: schema.TypeMap, 77 Optional: true, 78 }, 79 "target_endpoint_arn": { 80 Type: schema.TypeString, 81 Required: true, 82 ForceNew: true, 83 ValidateFunc: validateArn, 84 }, 85 }, 86 } 87 } 88 89 func resourceAwsDmsReplicationTaskCreate(d *schema.ResourceData, meta interface{}) error { 90 conn := meta.(*AWSClient).dmsconn 91 92 request := &dms.CreateReplicationTaskInput{ 93 MigrationType: aws.String(d.Get("migration_type").(string)), 94 ReplicationInstanceArn: aws.String(d.Get("replication_instance_arn").(string)), 95 ReplicationTaskIdentifier: aws.String(d.Get("replication_task_id").(string)), 96 SourceEndpointArn: aws.String(d.Get("source_endpoint_arn").(string)), 97 TableMappings: aws.String(d.Get("table_mappings").(string)), 98 Tags: dmsTagsFromMap(d.Get("tags").(map[string]interface{})), 99 TargetEndpointArn: aws.String(d.Get("target_endpoint_arn").(string)), 100 } 101 102 if v, ok := d.GetOk("cdc_start_time"); ok { 103 seconds, err := strconv.ParseInt(v.(string), 10, 64) 104 if err != nil { 105 return fmt.Errorf("[ERROR] DMS create replication task. Invalid CDC Unix timestamp: %s", err) 106 } 107 request.CdcStartTime = aws.Time(time.Unix(seconds, 0)) 108 } 109 110 if v, ok := d.GetOk("replication_task_settings"); ok { 111 request.ReplicationTaskSettings = aws.String(v.(string)) 112 } 113 114 log.Println("[DEBUG] DMS create replication task:", request) 115 116 _, err := conn.CreateReplicationTask(request) 117 if err != nil { 118 return err 119 } 120 121 taskId := d.Get("replication_task_id").(string) 122 123 err = waitForTaskCreated(conn, taskId, 30, 10) 124 if err != nil { 125 return err 126 } 127 128 d.SetId(taskId) 129 return resourceAwsDmsReplicationTaskRead(d, meta) 130 } 131 132 func resourceAwsDmsReplicationTaskRead(d *schema.ResourceData, meta interface{}) error { 133 conn := meta.(*AWSClient).dmsconn 134 135 response, err := conn.DescribeReplicationTasks(&dms.DescribeReplicationTasksInput{ 136 Filters: []*dms.Filter{ 137 { 138 Name: aws.String("replication-task-id"), 139 Values: []*string{aws.String(d.Id())}, // Must use d.Id() to work with import. 140 }, 141 }, 142 }) 143 if err != nil { 144 if dmserr, ok := err.(awserr.Error); ok && dmserr.Code() == "ResourceNotFoundFault" { 145 d.SetId("") 146 return nil 147 } 148 return err 149 } 150 151 err = resourceAwsDmsReplicationTaskSetState(d, response.ReplicationTasks[0]) 152 if err != nil { 153 return err 154 } 155 156 tagsResp, err := conn.ListTagsForResource(&dms.ListTagsForResourceInput{ 157 ResourceArn: aws.String(d.Get("replication_task_arn").(string)), 158 }) 159 if err != nil { 160 return err 161 } 162 d.Set("tags", dmsTagsToMap(tagsResp.TagList)) 163 164 return nil 165 } 166 167 func resourceAwsDmsReplicationTaskUpdate(d *schema.ResourceData, meta interface{}) error { 168 conn := meta.(*AWSClient).dmsconn 169 170 request := &dms.ModifyReplicationTaskInput{ 171 ReplicationTaskArn: aws.String(d.Get("replication_task_arn").(string)), 172 } 173 hasChanges := false 174 175 if d.HasChange("cdc_start_time") { 176 seconds, err := strconv.ParseInt(d.Get("cdc_start_time").(string), 10, 64) 177 if err != nil { 178 return fmt.Errorf("[ERROR] DMS update replication task. Invalid CRC Unix timestamp: %s", err) 179 } 180 request.CdcStartTime = aws.Time(time.Unix(seconds, 0)) 181 hasChanges = true 182 } 183 184 if d.HasChange("migration_type") { 185 request.MigrationType = aws.String(d.Get("migration_type").(string)) 186 hasChanges = true 187 } 188 189 if d.HasChange("replication_task_settings") { 190 request.ReplicationTaskSettings = aws.String(d.Get("replication_task_settings").(string)) 191 hasChanges = true 192 } 193 194 if d.HasChange("table_mappings") { 195 request.TableMappings = aws.String(d.Get("table_mappings").(string)) 196 hasChanges = true 197 } 198 199 if d.HasChange("tags") { 200 err := dmsSetTags(d.Get("replication_task_arn").(string), d, meta) 201 if err != nil { 202 return err 203 } 204 } 205 206 if hasChanges { 207 log.Println("[DEBUG] DMS update replication task:", request) 208 209 _, err := conn.ModifyReplicationTask(request) 210 if err != nil { 211 return err 212 } 213 214 err = waitForTaskUpdated(conn, d.Get("replication_task_id").(string), 30, 10) 215 if err != nil { 216 return err 217 } 218 219 return resourceAwsDmsReplicationTaskRead(d, meta) 220 } 221 222 return nil 223 } 224 225 func resourceAwsDmsReplicationTaskDelete(d *schema.ResourceData, meta interface{}) error { 226 conn := meta.(*AWSClient).dmsconn 227 228 request := &dms.DeleteReplicationTaskInput{ 229 ReplicationTaskArn: aws.String(d.Get("replication_task_arn").(string)), 230 } 231 232 log.Printf("[DEBUG] DMS delete replication task: %#v", request) 233 234 _, err := conn.DeleteReplicationTask(request) 235 if err != nil { 236 return err 237 } 238 239 waitErr := waitForTaskDeleted(conn, d.Get("replication_task_id").(string), 30, 10) 240 if waitErr != nil { 241 return waitErr 242 } 243 244 return nil 245 } 246 247 func resourceAwsDmsReplicationTaskSetState(d *schema.ResourceData, task *dms.ReplicationTask) error { 248 d.SetId(*task.ReplicationTaskIdentifier) 249 250 d.Set("migration_type", task.MigrationType) 251 d.Set("replication_instance_arn", task.ReplicationInstanceArn) 252 d.Set("replication_task_arn", task.ReplicationTaskArn) 253 d.Set("replication_task_id", task.ReplicationTaskIdentifier) 254 d.Set("replication_task_settings", task.ReplicationTaskSettings) 255 d.Set("source_endpoint_arn", task.SourceEndpointArn) 256 d.Set("table_mappings", task.TableMappings) 257 d.Set("target_endpoint_arn", task.TargetEndpointArn) 258 259 return nil 260 } 261 262 func waitForTaskCreated(client *dms.DatabaseMigrationService, id string, delay int, maxAttempts int) error { 263 input := &dms.DescribeReplicationTasksInput{ 264 Filters: []*dms.Filter{ 265 { 266 Name: aws.String("replication-task-id"), 267 Values: []*string{aws.String(id)}, 268 }, 269 }, 270 } 271 272 config := waiter.Config{ 273 Operation: "DescribeReplicationTasks", 274 Delay: delay, 275 MaxAttempts: maxAttempts, 276 Acceptors: []waiter.WaitAcceptor{ 277 { 278 State: "retry", 279 Matcher: "pathAll", 280 Argument: "ReplicationTasks[].Status", 281 Expected: "creating", 282 }, 283 { 284 State: "success", 285 Matcher: "pathAll", 286 Argument: "ReplicationTasks[].Status", 287 Expected: "ready", 288 }, 289 }, 290 } 291 292 w := waiter.Waiter{ 293 Client: client, 294 Input: input, 295 Config: config, 296 } 297 298 return w.Wait() 299 } 300 301 func waitForTaskUpdated(client *dms.DatabaseMigrationService, id string, delay int, maxAttempts int) error { 302 input := &dms.DescribeReplicationTasksInput{ 303 Filters: []*dms.Filter{ 304 { 305 Name: aws.String("replication-task-id"), 306 Values: []*string{aws.String(id)}, 307 }, 308 }, 309 } 310 311 config := waiter.Config{ 312 Operation: "DescribeReplicationTasks", 313 Delay: delay, 314 MaxAttempts: maxAttempts, 315 Acceptors: []waiter.WaitAcceptor{ 316 { 317 State: "retry", 318 Matcher: "pathAll", 319 Argument: "ReplicationTasks[].Status", 320 Expected: "modifying", 321 }, 322 { 323 State: "success", 324 Matcher: "pathAll", 325 Argument: "ReplicationTasks[].Status", 326 Expected: "ready", 327 }, 328 }, 329 } 330 331 w := waiter.Waiter{ 332 Client: client, 333 Input: input, 334 Config: config, 335 } 336 337 return w.Wait() 338 } 339 340 func waitForTaskDeleted(client *dms.DatabaseMigrationService, id string, delay int, maxAttempts int) error { 341 input := &dms.DescribeReplicationTasksInput{ 342 Filters: []*dms.Filter{ 343 { 344 Name: aws.String("replication-task-id"), 345 Values: []*string{aws.String(id)}, 346 }, 347 }, 348 } 349 350 config := waiter.Config{ 351 Operation: "DescribeReplicationTasks", 352 Delay: delay, 353 MaxAttempts: maxAttempts, 354 Acceptors: []waiter.WaitAcceptor{ 355 { 356 State: "retry", 357 Matcher: "pathAll", 358 Argument: "ReplicationTasks[].Status", 359 Expected: "deleting", 360 }, 361 { 362 State: "success", 363 Matcher: "path", 364 Argument: "length(ReplicationTasks[]) > `0`", 365 Expected: false, 366 }, 367 }, 368 } 369 370 w := waiter.Waiter{ 371 Client: client, 372 Input: input, 373 Config: config, 374 } 375 376 return w.Wait() 377 }