github.com/ndarilek/terraform@v0.3.8-0.20150320140257-d3135c1b2bac/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 log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes) 28 // Delete old count 29 delete(is.Attributes, "block_device.#") 30 31 oldBds, err := readV0BlockDevices(is) 32 if err != nil { 33 return is, err 34 } 35 // seed count fields for new types 36 is.Attributes["ebs_block_device.#"] = "0" 37 is.Attributes["ephemeral_block_device.#"] = "0" 38 // depending on if state was v0.3.7 or an earlier version, it might have 39 // root_block_device defined already 40 if _, ok := is.Attributes["root_block_device.#"]; !ok { 41 is.Attributes["root_block_device.#"] = "0" 42 } 43 for _, oldBd := range oldBds { 44 if err := writeV1BlockDevice(is, oldBd); err != nil { 45 return is, err 46 } 47 } 48 log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes) 49 return is, nil 50 } 51 52 func readV0BlockDevices(is *terraform.InstanceState) (map[string]map[string]string, error) { 53 oldBds := make(map[string]map[string]string) 54 for k, v := range is.Attributes { 55 if !strings.HasPrefix(k, "block_device.") { 56 continue 57 } 58 path := strings.Split(k, ".") 59 if len(path) != 3 { 60 return oldBds, fmt.Errorf("Found unexpected block_device field: %#v", k) 61 } 62 hashcode, attribute := path[1], path[2] 63 oldBd, ok := oldBds[hashcode] 64 if !ok { 65 oldBd = make(map[string]string) 66 oldBds[hashcode] = oldBd 67 } 68 oldBd[attribute] = v 69 delete(is.Attributes, k) 70 } 71 return oldBds, nil 72 } 73 74 func writeV1BlockDevice( 75 is *terraform.InstanceState, oldBd map[string]string) error { 76 code := hashcode.String(oldBd["device_name"]) 77 bdType := "ebs_block_device" 78 if vn, ok := oldBd["virtual_name"]; ok && strings.HasPrefix(vn, "ephemeral") { 79 bdType = "ephemeral_block_device" 80 } else if dn, ok := oldBd["device_name"]; ok && dn == "/dev/sda1" { 81 bdType = "root_block_device" 82 } 83 84 switch bdType { 85 case "ebs_block_device": 86 delete(oldBd, "virtual_name") 87 case "root_block_device": 88 delete(oldBd, "virtual_name") 89 delete(oldBd, "encrypted") 90 delete(oldBd, "snapshot_id") 91 case "ephemeral_block_device": 92 delete(oldBd, "delete_on_termination") 93 delete(oldBd, "encrypted") 94 delete(oldBd, "iops") 95 delete(oldBd, "volume_size") 96 delete(oldBd, "volume_type") 97 } 98 for attr, val := range oldBd { 99 attrKey := fmt.Sprintf("%s.%d.%s", bdType, code, attr) 100 is.Attributes[attrKey] = val 101 } 102 103 countAttr := fmt.Sprintf("%s.#", bdType) 104 count, _ := strconv.Atoi(is.Attributes[countAttr]) 105 is.Attributes[countAttr] = strconv.Itoa(count + 1) 106 return nil 107 }