github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/google/resource_compute_instance_migrate.go (about)

     1  package google
     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 resourceComputeInstanceMigrateState(
    14  	v int, is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) {
    15  	if is.Empty() {
    16  		log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
    17  		return is, nil
    18  	}
    19  
    20  	switch v {
    21  	case 0:
    22  		log.Println("[INFO] Found Compute Instance State v0; migrating to v1")
    23  		is, err := migrateStateV0toV1(is)
    24  		if err != nil {
    25  			return is, err
    26  		}
    27  		fallthrough
    28  	case 1:
    29  		log.Println("[INFO] Found Compute Instance State v1; migrating to v2")
    30  		is, err := migrateStateV1toV2(is)
    31  		if err != nil {
    32  			return is, err
    33  		}
    34  		return is, nil
    35  	default:
    36  		return is, fmt.Errorf("Unexpected schema version: %d", v)
    37  	}
    38  }
    39  
    40  func migrateStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
    41  	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)
    42  
    43  	// Delete old count
    44  	delete(is.Attributes, "metadata.#")
    45  
    46  	newMetadata := make(map[string]string)
    47  
    48  	for k, v := range is.Attributes {
    49  		if !strings.HasPrefix(k, "metadata.") {
    50  			continue
    51  		}
    52  
    53  		// We have a key that looks like "metadata.*" and we know it's not
    54  		// metadata.# because we deleted it above, so it must be metadata.<N>.<key>
    55  		// from the List of Maps. Just need to convert it to a single Map by
    56  		// ditching the '<N>' field.
    57  		kParts := strings.SplitN(k, ".", 3)
    58  
    59  		// Sanity check: all three parts should be there and <N> should be a number
    60  		badFormat := false
    61  		if len(kParts) != 3 {
    62  			badFormat = true
    63  		} else if _, err := strconv.Atoi(kParts[1]); err != nil {
    64  			badFormat = true
    65  		}
    66  
    67  		if badFormat {
    68  			return is, fmt.Errorf(
    69  				"migration error: found metadata key in unexpected format: %s", k)
    70  		}
    71  
    72  		// Rejoin as "metadata.<key>"
    73  		newK := strings.Join([]string{kParts[0], kParts[2]}, ".")
    74  		newMetadata[newK] = v
    75  		delete(is.Attributes, k)
    76  	}
    77  
    78  	for k, v := range newMetadata {
    79  		is.Attributes[k] = v
    80  	}
    81  
    82  	log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes)
    83  	return is, nil
    84  }
    85  
    86  func migrateStateV1toV2(is *terraform.InstanceState) (*terraform.InstanceState, error) {
    87  	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)
    88  
    89  	// Maps service account index to list of scopes for that sccount
    90  	newScopesMap := make(map[string][]string)
    91  
    92  	for k, v := range is.Attributes {
    93  		if !strings.HasPrefix(k, "service_account.") {
    94  			continue
    95  		}
    96  
    97  		if k == "service_account.#" {
    98  			continue
    99  		}
   100  
   101  		if strings.HasSuffix(k, ".scopes.#") {
   102  			continue
   103  		}
   104  
   105  		if strings.HasSuffix(k, ".email") {
   106  			continue
   107  		}
   108  
   109  		// Key is now of the form service_account.%d.scopes.%d
   110  		kParts := strings.Split(k, ".")
   111  
   112  		// Sanity check: all three parts should be there and <N> should be a number
   113  		badFormat := false
   114  		if len(kParts) != 4 {
   115  			badFormat = true
   116  		} else if _, err := strconv.Atoi(kParts[1]); err != nil {
   117  			badFormat = true
   118  		}
   119  
   120  		if badFormat {
   121  			return is, fmt.Errorf(
   122  				"migration error: found scope key in unexpected format: %s", k)
   123  		}
   124  
   125  		newScopesMap[kParts[1]] = append(newScopesMap[kParts[1]], v)
   126  
   127  		delete(is.Attributes, k)
   128  	}
   129  
   130  	for service_acct_index, newScopes := range newScopesMap {
   131  		for _, newScope := range newScopes {
   132  			hash := hashcode.String(canonicalizeServiceScope(newScope))
   133  			newKey := fmt.Sprintf("service_account.%s.scopes.%d", service_acct_index, hash)
   134  			is.Attributes[newKey] = newScope
   135  		}
   136  	}
   137  
   138  	log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes)
   139  	return is, nil
   140  }