mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-03 01:01:06 +00:00
Make google_compute_project_metadata authoritative. (#2205)
This commit is contained in:
parent
50fe1b6c83
commit
a9b6e3f5e1
@ -111,18 +111,15 @@ func BetaMetadataUpdate(oldMDMap map[string]interface{}, newMDMap map[string]int
|
||||
}
|
||||
}
|
||||
|
||||
// expandComputeMetadata transforms a map representing computing metadata into a list of compute.MetadataItems suitable
|
||||
// for the GCP client.
|
||||
func expandComputeMetadata(m map[string]string) []*compute.MetadataItems {
|
||||
func expandComputeMetadata(m map[string]interface{}) []*compute.MetadataItems {
|
||||
metadata := make([]*compute.MetadataItems, len(m))
|
||||
|
||||
idx := 0
|
||||
for key, value := range m {
|
||||
// Make a copy of value as we need a ptr type; if we directly use 'value' then all items will reference the same
|
||||
// memory address
|
||||
vtmp := value
|
||||
metadata[idx] = &compute.MetadataItems{Key: key, Value: &vtmp}
|
||||
idx++
|
||||
// Append new metadata to existing metadata
|
||||
for key, val := range m {
|
||||
v := val.(string)
|
||||
metadata = append(metadata, &compute.MetadataItems{
|
||||
Key: key,
|
||||
Value: &v,
|
||||
})
|
||||
}
|
||||
|
||||
return metadata
|
||||
@ -140,8 +137,8 @@ func flattenMetadataBeta(metadata *computeBeta.Metadata) map[string]string {
|
||||
// compute.metadata rather than computeBeta.metadata as an argument. It should
|
||||
// be removed in favour of flattenMetadataBeta if/when all resources using it get
|
||||
// beta support.
|
||||
func flattenMetadata(metadata *compute.Metadata) map[string]string {
|
||||
metadataMap := make(map[string]string)
|
||||
func flattenMetadata(metadata *compute.Metadata) map[string]interface{} {
|
||||
metadataMap := make(map[string]interface{})
|
||||
for _, item := range metadata.Items {
|
||||
metadataMap[item.Key] = *item.Value
|
||||
}
|
||||
|
@ -10,9 +10,9 @@ import (
|
||||
|
||||
func resourceComputeProjectMetadata() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceComputeProjectMetadataCreate,
|
||||
Create: resourceComputeProjectMetadataCreateOrUpdate,
|
||||
Read: resourceComputeProjectMetadataRead,
|
||||
Update: resourceComputeProjectMetadataUpdate,
|
||||
Update: resourceComputeProjectMetadataCreateOrUpdate,
|
||||
Delete: resourceComputeProjectMetadataDelete,
|
||||
|
||||
SchemaVersion: 0,
|
||||
@ -34,7 +34,7 @@ func resourceComputeProjectMetadata() *schema.Resource {
|
||||
}
|
||||
}
|
||||
|
||||
func resourceComputeProjectMetadataCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
func resourceComputeProjectMetadataCreateOrUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
|
||||
projectID, err := getProject(d, config)
|
||||
@ -42,49 +42,15 @@ func resourceComputeProjectMetadataCreate(d *schema.ResourceData, meta interface
|
||||
return err
|
||||
}
|
||||
|
||||
createMD := func() error {
|
||||
// Load project service
|
||||
log.Printf("[DEBUG] Loading project service: %s", projectID)
|
||||
project, err := config.clientCompute.Projects.Get(projectID).Do()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error loading project '%s': %s", projectID, err)
|
||||
md := &compute.Metadata{
|
||||
Items: expandComputeMetadata(d.Get("metadata").(map[string]interface{})),
|
||||
}
|
||||
|
||||
md := project.CommonInstanceMetadata
|
||||
|
||||
newMDMap := d.Get("metadata").(map[string]interface{})
|
||||
// Ensure that we aren't overwriting entries that already exist
|
||||
for _, kv := range md.Items {
|
||||
if _, ok := newMDMap[kv.Key]; ok {
|
||||
return fmt.Errorf("Error, key '%s' already exists in project '%s'", kv.Key, projectID)
|
||||
}
|
||||
}
|
||||
|
||||
// Append new metadata to existing metadata
|
||||
for key, val := range newMDMap {
|
||||
v := val.(string)
|
||||
md.Items = append(md.Items, &compute.MetadataItems{
|
||||
Key: key,
|
||||
Value: &v,
|
||||
})
|
||||
}
|
||||
|
||||
op, err := config.clientCompute.Projects.SetCommonInstanceMetadata(projectID, md).Do()
|
||||
|
||||
err = resourceComputeProjectMetadataSet(projectID, config, md)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SetCommonInstanceMetadata failed: %s", err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] SetCommonMetadata: %d (%s)", op.Id, op.SelfLink)
|
||||
|
||||
return computeOperationWait(config.clientCompute, op, project.Name, "SetCommonMetadata")
|
||||
}
|
||||
|
||||
err = MetadataRetryWrapper(createMD)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceComputeProjectMetadataRead(d, meta)
|
||||
}
|
||||
|
||||
@ -103,70 +69,13 @@ func resourceComputeProjectMetadataRead(d *schema.ResourceData, meta interface{}
|
||||
return handleNotFoundError(err, d, fmt.Sprintf("Project metadata for project %q", projectID))
|
||||
}
|
||||
|
||||
md := flattenMetadata(project.CommonInstanceMetadata)
|
||||
existingMetadata := d.Get("metadata").(map[string]interface{})
|
||||
// Remove all keys not explicitly mentioned in the terraform config
|
||||
for k := range md {
|
||||
if _, ok := existingMetadata[k]; !ok {
|
||||
delete(md, k)
|
||||
}
|
||||
}
|
||||
|
||||
if err = d.Set("metadata", md); err != nil {
|
||||
err = d.Set("metadata", flattenMetadata(project.CommonInstanceMetadata))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error setting metadata: %s", err)
|
||||
}
|
||||
|
||||
d.Set("project", projectID)
|
||||
d.SetId("common_metadata")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceComputeProjectMetadataUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
|
||||
projectID, err := getProject(d, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if d.HasChange("metadata") {
|
||||
o, n := d.GetChange("metadata")
|
||||
|
||||
updateMD := func() error {
|
||||
// Load project service
|
||||
log.Printf("[DEBUG] Loading project service: %s", projectID)
|
||||
project, err := config.clientCompute.Projects.Get(projectID).Do()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error loading project '%s': %s", projectID, err)
|
||||
}
|
||||
|
||||
md := project.CommonInstanceMetadata
|
||||
|
||||
MetadataUpdate(o.(map[string]interface{}), n.(map[string]interface{}), md)
|
||||
|
||||
op, err := config.clientCompute.Projects.SetCommonInstanceMetadata(projectID, md).Do()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("SetCommonInstanceMetadata failed: %s", err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] SetCommonMetadata: %d (%s)", op.Id, op.SelfLink)
|
||||
|
||||
// Optimistic locking requires the fingerprint received to match
|
||||
// the fingerprint we send the server, if there is a mismatch then we
|
||||
// are working on old data, and must retry
|
||||
return computeOperationWait(config.clientCompute, op, project.Name, "SetCommonMetadata")
|
||||
}
|
||||
|
||||
err := MetadataRetryWrapper(updateMD)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceComputeProjectMetadataRead(d, meta)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -178,30 +87,33 @@ func resourceComputeProjectMetadataDelete(d *schema.ResourceData, meta interface
|
||||
return err
|
||||
}
|
||||
|
||||
// Load project service
|
||||
md := &compute.Metadata{}
|
||||
err = resourceComputeProjectMetadataSet(projectID, config, md)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SetCommonInstanceMetadata failed: %s", err)
|
||||
}
|
||||
|
||||
return resourceComputeProjectMetadataRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceComputeProjectMetadataSet(projectID string, config *Config, md *compute.Metadata) error {
|
||||
createMD := func() error {
|
||||
log.Printf("[DEBUG] Loading project service: %s", projectID)
|
||||
project, err := config.clientCompute.Projects.Get(projectID).Do()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error loading project '%s': %s", projectID, err)
|
||||
}
|
||||
|
||||
md := project.CommonInstanceMetadata
|
||||
|
||||
// Remove all items
|
||||
md.Items = nil
|
||||
|
||||
md.Fingerprint = project.CommonInstanceMetadata.Fingerprint
|
||||
op, err := config.clientCompute.Projects.SetCommonInstanceMetadata(projectID, md).Do()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error removing metadata from project %s: %s", projectID, err)
|
||||
return fmt.Errorf("SetCommonInstanceMetadata failed: %s", err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] SetCommonMetadata: %d (%s)", op.Id, op.SelfLink)
|
||||
|
||||
err = computeOperationWait(config.clientCompute, op, project.Name, "SetCommonMetadata")
|
||||
if err != nil {
|
||||
return err
|
||||
return computeOperationWait(config.clientCompute, op, project.Name, "SetCommonMetadata")
|
||||
}
|
||||
|
||||
return resourceComputeProjectMetadataRead(d, meta)
|
||||
err := MetadataRetryWrapper(createMD)
|
||||
return err
|
||||
}
|
||||
|
@ -8,13 +8,14 @@ description: |-
|
||||
|
||||
# google\_compute\_project\_metadata
|
||||
|
||||
Manages metadata common to all instances for a project in GCE. For more information see
|
||||
Authoritatively manages metadata common to all instances for a project in GCE. For more information see
|
||||
[the official documentation](https://cloud.google.com/compute/docs/storing-retrieving-metadata)
|
||||
and
|
||||
[API](https://cloud.google.com/compute/docs/reference/latest/projects/setCommonInstanceMetadata).
|
||||
|
||||
~> **Note:** If you want to manage only single key/value pairs within the project metadata
|
||||
rather than the entire set, then use
|
||||
~> **Note:** This resource manages all project-level metadata including project-level ssh keys.
|
||||
Keys unset in config but set on the server will be removed. If you want to manage only single
|
||||
key/value pairs within the project metadata rather than the entire set, then use
|
||||
[google_compute_project_metadata_item](compute_project_metadata_item.html).
|
||||
|
||||
## Example Usage
|
||||
@ -33,8 +34,7 @@ resource "google_compute_project_metadata" "default" {
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `metadata` - (Required) A series of key value pairs. Changing this resource
|
||||
updates the GCE state.
|
||||
* `metadata` - (Required) A series of key value pairs.
|
||||
|
||||
- - -
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user