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  }