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  }