github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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 }