github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/aws/resource_aws_instance_migrate.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "strconv" 7 "strings" 8 9 "github.com/hashicorp/terraform/helper/hashcode" 10 "github.com/hashicorp/terraform/terraform" 11 ) 12 13 func resourceAwsInstanceMigrateState( 14 v int, is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) { 15 switch v { 16 case 0: 17 log.Println("[INFO] Found AWS Instance State v0; migrating to v1") 18 return migrateStateV0toV1(is) 19 default: 20 return is, fmt.Errorf("Unexpected schema version: %d", v) 21 } 22 23 return is, nil 24 } 25 26 func migrateStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) { 27 if is.Empty() { 28 log.Println("[DEBUG] Empty InstanceState; nothing to migrate.") 29 return is, nil 30 } 31 32 log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes) 33 34 // Delete old count 35 delete(is.Attributes, "block_device.#") 36 37 oldBds, err := readV0BlockDevices(is) 38 if err != nil { 39 return is, err 40 } 41 // seed count fields for new types 42 is.Attributes["ebs_block_device.#"] = "0" 43 is.Attributes["ephemeral_block_device.#"] = "0" 44 // depending on if state was v0.3.7 or an earlier version, it might have 45 // root_block_device defined already 46 if _, ok := is.Attributes["root_block_device.#"]; !ok { 47 is.Attributes["root_block_device.#"] = "0" 48 } 49 for _, oldBd := range oldBds { 50 if err := writeV1BlockDevice(is, oldBd); err != nil { 51 return is, err 52 } 53 } 54 log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes) 55 return is, nil 56 } 57 58 func readV0BlockDevices(is *terraform.InstanceState) (map[string]map[string]string, error) { 59 oldBds := make(map[string]map[string]string) 60 for k, v := range is.Attributes { 61 if !strings.HasPrefix(k, "block_device.") { 62 continue 63 } 64 path := strings.Split(k, ".") 65 if len(path) != 3 { 66 return oldBds, fmt.Errorf("Found unexpected block_device field: %#v", k) 67 } 68 hashcode, attribute := path[1], path[2] 69 oldBd, ok := oldBds[hashcode] 70 if !ok { 71 oldBd = make(map[string]string) 72 oldBds[hashcode] = oldBd 73 } 74 oldBd[attribute] = v 75 delete(is.Attributes, k) 76 } 77 return oldBds, nil 78 } 79 80 func writeV1BlockDevice( 81 is *terraform.InstanceState, oldBd map[string]string) error { 82 code := hashcode.String(oldBd["device_name"]) 83 bdType := "ebs_block_device" 84 if vn, ok := oldBd["virtual_name"]; ok && strings.HasPrefix(vn, "ephemeral") { 85 bdType = "ephemeral_block_device" 86 } else if dn, ok := oldBd["device_name"]; ok && dn == "/dev/sda1" { 87 bdType = "root_block_device" 88 } 89 90 switch bdType { 91 case "ebs_block_device": 92 delete(oldBd, "virtual_name") 93 case "root_block_device": 94 delete(oldBd, "virtual_name") 95 delete(oldBd, "encrypted") 96 delete(oldBd, "snapshot_id") 97 case "ephemeral_block_device": 98 delete(oldBd, "delete_on_termination") 99 delete(oldBd, "encrypted") 100 delete(oldBd, "iops") 101 delete(oldBd, "volume_size") 102 delete(oldBd, "volume_type") 103 } 104 for attr, val := range oldBd { 105 attrKey := fmt.Sprintf("%s.%d.%s", bdType, code, attr) 106 is.Attributes[attrKey] = val 107 } 108 109 countAttr := fmt.Sprintf("%s.#", bdType) 110 count, _ := strconv.Atoi(is.Attributes[countAttr]) 111 is.Attributes[countAttr] = strconv.Itoa(count + 1) 112 return nil 113 }