github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/google/metadata.go (about)

     1  package google
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"google.golang.org/api/compute/v1"
     7  )
     8  
     9  const FINGERPRINT_RETRIES = 10
    10  const FINGERPRINT_FAIL = "Invalid fingerprint."
    11  
    12  // Since the google compute API uses optimistic locking, there is a chance
    13  // we need to resubmit our updated metadata. To do this, you need to provide
    14  // an update function that attempts to submit your metadata
    15  func MetadataRetryWrapper(update func() error) error {
    16  	attempt := 0
    17  	for attempt < FINGERPRINT_RETRIES {
    18  		err := update()
    19  		if err != nil && err.Error() == FINGERPRINT_FAIL {
    20  			attempt++
    21  		} else {
    22  			return err
    23  		}
    24  	}
    25  
    26  	return fmt.Errorf("Failed to update metadata after %d retries", attempt)
    27  }
    28  
    29  // Update the metadata (serverMD) according to the provided diff (oldMDMap v
    30  // newMDMap).
    31  func MetadataUpdate(oldMDMap map[string]interface{}, newMDMap map[string]interface{}, serverMD *compute.Metadata) {
    32  	curMDMap := make(map[string]string)
    33  	// Load metadata on server into map
    34  	for _, kv := range serverMD.Items {
    35  		// If the server state has a key that we had in our old
    36  		// state, but not in our new state, we should delete it
    37  		_, okOld := oldMDMap[kv.Key]
    38  		_, okNew := newMDMap[kv.Key]
    39  		if okOld && !okNew {
    40  			continue
    41  		} else {
    42  			curMDMap[kv.Key] = *kv.Value
    43  		}
    44  	}
    45  
    46  	// Insert new metadata into existing metadata (overwriting when needed)
    47  	for key, val := range newMDMap {
    48  		curMDMap[key] = val.(string)
    49  	}
    50  
    51  	// Reformat old metadata into a list
    52  	serverMD.Items = nil
    53  	for key, val := range curMDMap {
    54  		v := val
    55  		serverMD.Items = append(serverMD.Items, &compute.MetadataItems{
    56  			Key:   key,
    57  			Value: &v,
    58  		})
    59  	}
    60  }
    61  
    62  // Format metadata from the server data format -> schema data format
    63  func MetadataFormatSchema(curMDMap map[string]interface{}, md *compute.Metadata) map[string]interface{} {
    64  	newMD := make(map[string]interface{})
    65  
    66  	for _, kv := range md.Items {
    67  		if _, ok := curMDMap[kv.Key]; ok {
    68  			newMD[kv.Key] = *kv.Value
    69  		}
    70  	}
    71  
    72  	return newMD
    73  }