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