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

     1  package google
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/hashicorp/terraform/helper/schema"
     8  	"google.golang.org/api/compute/v1"
     9  	"google.golang.org/api/googleapi"
    10  )
    11  
    12  func resourceComputeProjectMetadata() *schema.Resource {
    13  	return &schema.Resource{
    14  		Create: resourceComputeProjectMetadataCreate,
    15  		Read:   resourceComputeProjectMetadataRead,
    16  		Update: resourceComputeProjectMetadataUpdate,
    17  		Delete: resourceComputeProjectMetadataDelete,
    18  
    19  		SchemaVersion: 0,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"metadata": &schema.Schema{
    23  				Elem:     schema.TypeString,
    24  				Type:     schema.TypeMap,
    25  				Required: true,
    26  			},
    27  
    28  			"project": &schema.Schema{
    29  				Type:     schema.TypeString,
    30  				Optional: true,
    31  				ForceNew: true,
    32  			},
    33  		},
    34  	}
    35  }
    36  
    37  func resourceComputeProjectMetadataCreate(d *schema.ResourceData, meta interface{}) error {
    38  	config := meta.(*Config)
    39  
    40  	projectID, err := getProject(d, config)
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	createMD := func() error {
    46  		// Load project service
    47  		log.Printf("[DEBUG] Loading project service: %s", projectID)
    48  		project, err := config.clientCompute.Projects.Get(projectID).Do()
    49  		if err != nil {
    50  			return fmt.Errorf("Error loading project '%s': %s", projectID, err)
    51  		}
    52  
    53  		md := project.CommonInstanceMetadata
    54  
    55  		newMDMap := d.Get("metadata").(map[string]interface{})
    56  		// Ensure that we aren't overwriting entries that already exist
    57  		for _, kv := range md.Items {
    58  			if _, ok := newMDMap[kv.Key]; ok {
    59  				return fmt.Errorf("Error, key '%s' already exists in project '%s'", kv.Key, projectID)
    60  			}
    61  		}
    62  
    63  		// Append new metadata to existing metadata
    64  		for key, val := range newMDMap {
    65  			v := val.(string)
    66  			md.Items = append(md.Items, &compute.MetadataItems{
    67  				Key:   key,
    68  				Value: &v,
    69  			})
    70  		}
    71  
    72  		op, err := config.clientCompute.Projects.SetCommonInstanceMetadata(projectID, md).Do()
    73  
    74  		if err != nil {
    75  			return fmt.Errorf("SetCommonInstanceMetadata failed: %s", err)
    76  		}
    77  
    78  		log.Printf("[DEBUG] SetCommonMetadata: %d (%s)", op.Id, op.SelfLink)
    79  
    80  		return computeOperationWaitGlobal(config, op, project.Name, "SetCommonMetadata")
    81  	}
    82  
    83  	err = MetadataRetryWrapper(createMD)
    84  	if err != nil {
    85  		return err
    86  	}
    87  
    88  	return resourceComputeProjectMetadataRead(d, meta)
    89  }
    90  
    91  func resourceComputeProjectMetadataRead(d *schema.ResourceData, meta interface{}) error {
    92  	config := meta.(*Config)
    93  
    94  	projectID, err := getProject(d, config)
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	// Load project service
   100  	log.Printf("[DEBUG] Loading project service: %s", projectID)
   101  	project, err := config.clientCompute.Projects.Get(projectID).Do()
   102  	if err != nil {
   103  		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
   104  			log.Printf("[WARN] Removing Project Metadata because it's gone")
   105  			// The resource doesn't exist anymore
   106  			d.SetId("")
   107  
   108  			return nil
   109  		}
   110  
   111  		return fmt.Errorf("Error loading project '%s': %s", projectID, err)
   112  	}
   113  
   114  	md := project.CommonInstanceMetadata
   115  
   116  	if err = d.Set("metadata", MetadataFormatSchema(d.Get("metadata").(map[string]interface{}), md)); err != nil {
   117  		return fmt.Errorf("Error setting metadata: %s", err)
   118  	}
   119  
   120  	d.SetId("common_metadata")
   121  
   122  	return nil
   123  }
   124  
   125  func resourceComputeProjectMetadataUpdate(d *schema.ResourceData, meta interface{}) error {
   126  	config := meta.(*Config)
   127  
   128  	projectID, err := getProject(d, config)
   129  	if err != nil {
   130  		return err
   131  	}
   132  
   133  	if d.HasChange("metadata") {
   134  		o, n := d.GetChange("metadata")
   135  
   136  		updateMD := func() error {
   137  			// Load project service
   138  			log.Printf("[DEBUG] Loading project service: %s", projectID)
   139  			project, err := config.clientCompute.Projects.Get(projectID).Do()
   140  			if err != nil {
   141  				return fmt.Errorf("Error loading project '%s': %s", projectID, err)
   142  			}
   143  
   144  			md := project.CommonInstanceMetadata
   145  
   146  			MetadataUpdate(o.(map[string]interface{}), n.(map[string]interface{}), md)
   147  
   148  			op, err := config.clientCompute.Projects.SetCommonInstanceMetadata(projectID, md).Do()
   149  
   150  			if err != nil {
   151  				return fmt.Errorf("SetCommonInstanceMetadata failed: %s", err)
   152  			}
   153  
   154  			log.Printf("[DEBUG] SetCommonMetadata: %d (%s)", op.Id, op.SelfLink)
   155  
   156  			// Optimistic locking requires the fingerprint received to match
   157  			// the fingerprint we send the server, if there is a mismatch then we
   158  			// are working on old data, and must retry
   159  			return computeOperationWaitGlobal(config, op, project.Name, "SetCommonMetadata")
   160  		}
   161  
   162  		err := MetadataRetryWrapper(updateMD)
   163  		if err != nil {
   164  			return err
   165  		}
   166  
   167  		return resourceComputeProjectMetadataRead(d, meta)
   168  	}
   169  
   170  	return nil
   171  }
   172  
   173  func resourceComputeProjectMetadataDelete(d *schema.ResourceData, meta interface{}) error {
   174  	config := meta.(*Config)
   175  
   176  	projectID, err := getProject(d, config)
   177  	if err != nil {
   178  		return err
   179  	}
   180  
   181  	// Load project service
   182  	log.Printf("[DEBUG] Loading project service: %s", projectID)
   183  	project, err := config.clientCompute.Projects.Get(projectID).Do()
   184  	if err != nil {
   185  		return fmt.Errorf("Error loading project '%s': %s", projectID, err)
   186  	}
   187  
   188  	md := project.CommonInstanceMetadata
   189  
   190  	// Remove all items
   191  	md.Items = nil
   192  
   193  	op, err := config.clientCompute.Projects.SetCommonInstanceMetadata(projectID, md).Do()
   194  
   195  	if err != nil {
   196  		return fmt.Errorf("Error removing metadata from project %s: %s", projectID, err)
   197  	}
   198  
   199  	log.Printf("[DEBUG] SetCommonMetadata: %d (%s)", op.Id, op.SelfLink)
   200  
   201  	err = computeOperationWaitGlobal(config, op, project.Name, "SetCommonMetadata")
   202  	if err != nil {
   203  		return err
   204  	}
   205  
   206  	return resourceComputeProjectMetadataRead(d, meta)
   207  }