mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-07-09 03:28:29 +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
|
func expandComputeMetadata(m map[string]interface{}) []*compute.MetadataItems {
|
||||||
// for the GCP client.
|
|
||||||
func expandComputeMetadata(m map[string]string) []*compute.MetadataItems {
|
|
||||||
metadata := make([]*compute.MetadataItems, len(m))
|
metadata := make([]*compute.MetadataItems, len(m))
|
||||||
|
// Append new metadata to existing metadata
|
||||||
idx := 0
|
for key, val := range m {
|
||||||
for key, value := range m {
|
v := val.(string)
|
||||||
// Make a copy of value as we need a ptr type; if we directly use 'value' then all items will reference the same
|
metadata = append(metadata, &compute.MetadataItems{
|
||||||
// memory address
|
Key: key,
|
||||||
vtmp := value
|
Value: &v,
|
||||||
metadata[idx] = &compute.MetadataItems{Key: key, Value: &vtmp}
|
})
|
||||||
idx++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return metadata
|
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
|
// compute.metadata rather than computeBeta.metadata as an argument. It should
|
||||||
// be removed in favour of flattenMetadataBeta if/when all resources using it get
|
// be removed in favour of flattenMetadataBeta if/when all resources using it get
|
||||||
// beta support.
|
// beta support.
|
||||||
func flattenMetadata(metadata *compute.Metadata) map[string]string {
|
func flattenMetadata(metadata *compute.Metadata) map[string]interface{} {
|
||||||
metadataMap := make(map[string]string)
|
metadataMap := make(map[string]interface{})
|
||||||
for _, item := range metadata.Items {
|
for _, item := range metadata.Items {
|
||||||
metadataMap[item.Key] = *item.Value
|
metadataMap[item.Key] = *item.Value
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@ import (
|
||||||
|
|
||||||
func resourceComputeProjectMetadata() *schema.Resource {
|
func resourceComputeProjectMetadata() *schema.Resource {
|
||||||
return &schema.Resource{
|
return &schema.Resource{
|
||||||
Create: resourceComputeProjectMetadataCreate,
|
Create: resourceComputeProjectMetadataCreateOrUpdate,
|
||||||
Read: resourceComputeProjectMetadataRead,
|
Read: resourceComputeProjectMetadataRead,
|
||||||
Update: resourceComputeProjectMetadataUpdate,
|
Update: resourceComputeProjectMetadataCreateOrUpdate,
|
||||||
Delete: resourceComputeProjectMetadataDelete,
|
Delete: resourceComputeProjectMetadataDelete,
|
||||||
|
|
||||||
SchemaVersion: 0,
|
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)
|
config := meta.(*Config)
|
||||||
|
|
||||||
projectID, err := getProject(d, config)
|
projectID, err := getProject(d, config)
|
||||||
|
@ -42,49 +42,15 @@ func resourceComputeProjectMetadataCreate(d *schema.ResourceData, meta interface
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
createMD := func() error {
|
md := &compute.Metadata{
|
||||||
// Load project service
|
Items: expandComputeMetadata(d.Get("metadata").(map[string]interface{})),
|
||||||
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
|
err = resourceComputeProjectMetadataSet(projectID, config, md)
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("SetCommonInstanceMetadata failed: %s", err)
|
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)
|
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))
|
return handleNotFoundError(err, d, fmt.Sprintf("Project metadata for project %q", projectID))
|
||||||
}
|
}
|
||||||
|
|
||||||
md := flattenMetadata(project.CommonInstanceMetadata)
|
err = d.Set("metadata", flattenMetadata(project.CommonInstanceMetadata))
|
||||||
existingMetadata := d.Get("metadata").(map[string]interface{})
|
if err != nil {
|
||||||
// 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 {
|
|
||||||
return fmt.Errorf("Error setting metadata: %s", err)
|
return fmt.Errorf("Error setting metadata: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Set("project", projectID)
|
d.Set("project", projectID)
|
||||||
d.SetId("common_metadata")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,30 +87,33 @@ func resourceComputeProjectMetadataDelete(d *schema.ResourceData, meta interface
|
||||||
return err
|
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)
|
log.Printf("[DEBUG] Loading project service: %s", projectID)
|
||||||
project, err := config.clientCompute.Projects.Get(projectID).Do()
|
project, err := config.clientCompute.Projects.Get(projectID).Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error loading project '%s': %s", projectID, err)
|
return fmt.Errorf("Error loading project '%s': %s", projectID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
md := project.CommonInstanceMetadata
|
md.Fingerprint = project.CommonInstanceMetadata.Fingerprint
|
||||||
|
|
||||||
// Remove all items
|
|
||||||
md.Items = nil
|
|
||||||
|
|
||||||
op, err := config.clientCompute.Projects.SetCommonInstanceMetadata(projectID, md).Do()
|
op, err := config.clientCompute.Projects.SetCommonInstanceMetadata(projectID, md).Do()
|
||||||
|
|
||||||
if err != nil {
|
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)
|
log.Printf("[DEBUG] SetCommonMetadata: %d (%s)", op.Id, op.SelfLink)
|
||||||
|
return computeOperationWait(config.clientCompute, op, project.Name, "SetCommonMetadata")
|
||||||
|
}
|
||||||
|
|
||||||
err = computeOperationWait(config.clientCompute, op, project.Name, "SetCommonMetadata")
|
err := MetadataRetryWrapper(createMD)
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return resourceComputeProjectMetadataRead(d, meta)
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,13 +8,14 @@ description: |-
|
||||||
|
|
||||||
# google\_compute\_project\_metadata
|
# 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)
|
[the official documentation](https://cloud.google.com/compute/docs/storing-retrieving-metadata)
|
||||||
and
|
and
|
||||||
[API](https://cloud.google.com/compute/docs/reference/latest/projects/setCommonInstanceMetadata).
|
[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
|
~> **Note:** This resource manages all project-level metadata including project-level ssh keys.
|
||||||
rather than the entire set, then use
|
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).
|
[google_compute_project_metadata_item](compute_project_metadata_item.html).
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
@ -33,8 +34,7 @@ resource "google_compute_project_metadata" "default" {
|
||||||
|
|
||||||
The following arguments are supported:
|
The following arguments are supported:
|
||||||
|
|
||||||
* `metadata` - (Required) A series of key value pairs. Changing this resource
|
* `metadata` - (Required) A series of key value pairs.
|
||||||
updates the GCE state.
|
|
||||||
|
|
||||||
- - -
|
- - -
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user