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