tfplan2cai/converters/google/resources/services/compute/metadata.go (174 lines of code) (raw):
package compute
import (
"encoding/json"
"errors"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"google.golang.org/api/googleapi"
"reflect"
"sort"
compute "google.golang.org/api/compute/v0.beta"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport"
)
// Since the google compute API uses optimistic locking, there is a chance
// we need to resubmit our updated metadata. To do this, you need to provide
// an update function that attempts to submit your metadata
func MetadataRetryWrapper(update func() error) error {
return transport_tpg.MetadataRetryWrapper(update)
}
// Update the metadata (serverMD) according to the provided diff (oldMDMap v
// newMDMap).
func MetadataUpdate(oldMDMap map[string]interface{}, newMDMap map[string]interface{}, serverMD *compute.Metadata) {
curMDMap := make(map[string]string)
// Load metadata on server into map
for _, kv := range serverMD.Items {
// If the server state has a key that we had in our old
// state, but not in our new state, we should delete it
_, okOld := oldMDMap[kv.Key]
_, okNew := newMDMap[kv.Key]
if okOld && !okNew {
continue
} else {
curMDMap[kv.Key] = *kv.Value
}
}
// Insert new metadata into existing metadata (overwriting when needed)
for key, val := range newMDMap {
curMDMap[key] = val.(string)
}
// Reformat old metadata into a list
serverMD.Items = nil
for key, val := range curMDMap {
v := val
serverMD.Items = append(serverMD.Items, &compute.MetadataItems{
Key: key,
Value: &v,
})
}
}
// Update the beta metadata (serverMD) according to the provided diff (oldMDMap v
// newMDMap).
func BetaMetadataUpdate(oldMDMap map[string]interface{}, newMDMap map[string]interface{}, serverMD *compute.Metadata) {
curMDMap := make(map[string]string)
// Load metadata on server into map
for _, kv := range serverMD.Items {
// If the server state has a key that we had in our old
// state, but not in our new state, we should delete it
_, okOld := oldMDMap[kv.Key]
_, okNew := newMDMap[kv.Key]
if okOld && !okNew {
continue
} else {
curMDMap[kv.Key] = *kv.Value
}
}
// Insert new metadata into existing metadata (overwriting when needed)
for key, val := range newMDMap {
curMDMap[key] = val.(string)
}
// Reformat old metadata into a list
serverMD.Items = nil
for key, val := range curMDMap {
v := val
serverMD.Items = append(serverMD.Items, &compute.MetadataItems{
Key: key,
Value: &v,
})
}
}
func expandComputeMetadata(m map[string]interface{}) []*compute.MetadataItems {
metadata := make([]*compute.MetadataItems, 0, len(m))
var keys []string
for key := range m {
keys = append(keys, key)
}
sort.Strings(keys)
// Append new metadata to existing metadata
for _, key := range keys {
v := m[key].(string)
metadata = append(metadata, &compute.MetadataItems{
Key: key,
Value: &v,
})
}
return metadata
}
func flattenMetadataBeta(metadata *compute.Metadata) map[string]string {
metadataMap := make(map[string]string)
for _, item := range metadata.Items {
metadataMap[item.Key] = *item.Value
}
return metadataMap
}
// This function differs from flattenMetadataBeta only in that it takes
// compute.metadata rather than compute.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]interface{} {
metadataMap := make(map[string]interface{})
for _, item := range metadata.Items {
metadataMap[item.Key] = *item.Value
}
return metadataMap
}
func resourceInstanceMetadata(d tpgresource.TerraformResourceData) (*compute.Metadata, error) {
m := &compute.Metadata{}
mdMap := d.Get("metadata").(map[string]interface{})
if v, ok := d.GetOk("metadata_startup_script"); ok && v.(string) != "" {
if w, ok := mdMap["startup-script"]; ok {
// metadata.startup-script could be from metadata_startup_script in the first place
if v != w {
return nil, errors.New("Cannot provide both metadata_startup_script and metadata.startup-script.")
}
}
mdMap["startup-script"] = v
}
if len(mdMap) > 0 {
m.Items = make([]*compute.MetadataItems, 0, len(mdMap))
var keys []string
for k := range mdMap {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
v := mdMap[k].(string)
m.Items = append(m.Items, &compute.MetadataItems{
Key: k,
Value: &v,
})
}
// Set the fingerprint. If the metadata has never been set before
// then this will just be blank.
m.Fingerprint = d.Get("metadata_fingerprint").(string)
}
return m, nil
}
func resourceInstancePartnerMetadata(d tpgresource.TerraformResourceData) (map[string]compute.StructuredEntries, error) {
partnerMetadata := make(map[string]compute.StructuredEntries)
partnerMetadataMap := d.Get("partner_metadata").(map[string]interface{})
if len(partnerMetadataMap) > 0 {
for key, value := range partnerMetadataMap {
var jsonMap map[string]interface{}
err := json.Unmarshal([]byte(value.(string)), &jsonMap)
if err != nil {
return nil, err
}
structuredEntries := jsonMap["entries"].(map[string]interface{})
structuredEntriesJson, err := json.Marshal(&structuredEntries)
if err != nil {
return nil, err
}
partnerMetadata[key] = compute.StructuredEntries{
Entries: googleapi.RawMessage(structuredEntriesJson),
}
}
}
return partnerMetadata, nil
}
func resourceInstancePatchPartnerMetadata(d tpgresource.TerraformResourceData, currentPartnerMetadata map[string]compute.StructuredEntries) map[string]compute.StructuredEntries {
partnerMetadata, _ := resourceInstancePartnerMetadata(d)
for key := range currentPartnerMetadata {
if _, ok := partnerMetadata[key]; !ok {
partnerMetadata[key] = compute.StructuredEntries{}
}
}
return partnerMetadata
}
func flattenPartnerMetadata(partnerMetadata map[string]compute.StructuredEntries) (map[string]string, error) {
partnerMetadataMap := make(map[string]string)
for key, value := range partnerMetadata {
jsonString, err := json.Marshal(&value)
if err != nil {
return nil, err
}
if value.Entries != nil {
partnerMetadataMap[key] = string(jsonString)
}
}
return partnerMetadataMap, nil
}
func ComparePartnerMetadataDiff(_, old, new string, d *schema.ResourceData) bool {
var oldJson map[string]interface{}
var newJson map[string]interface{}
json.Unmarshal([]byte(old), &oldJson)
json.Unmarshal([]byte(new), &newJson)
if reflect.DeepEqual(oldJson, newJson) {
return true
}
return false
}