Skip to content

Commit

Permalink
add support for partner metadata field on instance and instance templ…
Browse files Browse the repository at this point in the history
  • Loading branch information
muhammedkamal97 authored Jun 3, 2024
1 parent a1e28b5 commit 5449997
Show file tree
Hide file tree
Showing 12 changed files with 1,024 additions and 3 deletions.
69 changes: 69 additions & 0 deletions mmv1/third_party/terraform/services/compute/metadata.go.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@
package compute

import (
<% unless version == 'ga' -%>
"encoding/json"
<% end -%>
"errors"
<% unless version == 'ga' -%>
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"google.golang.org/api/googleapi"
"reflect"
<% end -%>
"sort"

<% if version == "ga" -%>
Expand Down Expand Up @@ -161,3 +169,64 @@ func resourceInstanceMetadata(d tpgresource.TerraformResourceData) (*compute.Met

return m, nil
}
<% unless version == 'ga' -%>

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
}
<% end -%>
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,17 @@ func ResourceComputeInstance() *schema.Resource {
Description: `Metadata key/value pairs made available within the instance.`,
},

<% unless version == 'ga' -%>
"partner_metadata": {
Type: schema.TypeMap,
Optional: true,
DiffSuppressFunc: ComparePartnerMetadataDiff,
DiffSuppressOnRefresh: true,
Elem: &schema.Schema{Type: schema.TypeString},
Description: `Partner Metadata Map made available within the instance.`,
},
<% end -%>

"metadata_startup_script": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -1198,7 +1209,11 @@ func getInstance(config *transport_tpg.Config, d *schema.ResourceData) (*compute
if err != nil {
return nil, err
}
<% if version == "ga" -%>
instance, err := config.NewComputeClient(userAgent).Instances.Get(project, zone, d.Get("name").(string)).Do()
<% else -%>
instance, err := config.NewComputeClient(userAgent).Instances.Get(project, zone, d.Get("name").(string)).View("FULL").Do()
<% end -%>
if err != nil {
return nil, transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Instance %s", d.Get("name").(string)))
}
Expand Down Expand Up @@ -1283,6 +1298,13 @@ func expandComputeInstance(project string, d *schema.ResourceData, config *trans
return nil, fmt.Errorf("Error creating metadata: %s", err)
}

<% unless version == 'ga' -%>
PartnerMetadata, err := resourceInstancePartnerMetadata(d)
if err != nil {
return nil, fmt.Errorf("Error creating partner metadata: %s", err)
}
<% end -%>

networkInterfaces, err := expandNetworkInterfaces(d, config)
if err != nil {
return nil, fmt.Errorf("Error creating network interfaces: %s", err)
Expand All @@ -1308,6 +1330,9 @@ func expandComputeInstance(project string, d *schema.ResourceData, config *trans
Disks: disks,
MachineType: machineTypeUrl,
Metadata: metadata,
<% unless version == 'ga' -%>
PartnerMetadata: PartnerMetadata,
<% end -%>
Name: d.Get("name").(string),
NetworkInterfaces: networkInterfaces,
NetworkPerformanceConfig: networkPerformanceConfig,
Expand Down Expand Up @@ -1484,6 +1509,19 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
if err := d.Set("metadata_fingerprint", instance.Metadata.Fingerprint); err != nil {
return fmt.Errorf("Error setting metadata_fingerprint: %s", err)
}

<% unless version == 'ga' -%>
if instance.PartnerMetadata != nil {
partnerMetadata, err := flattenPartnerMetadata(instance.PartnerMetadata)
if err != nil {
return fmt.Errorf("Error parsing partner metadata: %s", err)
}
if err = d.Set("partner_metadata", partnerMetadata); err != nil {
return fmt.Errorf("Error setting partner metadata: %s", err)
}
}
<% end -%>

if err := d.Set("can_ip_forward", instance.CanIpForward); err != nil {
return fmt.Errorf("Error setting can_ip_forward: %s", err)
}
Expand Down Expand Up @@ -1815,6 +1853,37 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err
}
}

<% unless version == 'ga' -%>
if d.HasChange("partner_metadata") {
err = transport_tpg.Retry(transport_tpg.RetryOptions{
RetryFunc: func() error {
instance, err := config.NewComputeClient(userAgent).Instances.Get(project, zone, instance.Name).View("FULL").Do()
if err != nil {
return fmt.Errorf("Error retrieving partner_metadata: %s", err)
}
instance.Fingerprint = instance.Fingerprint
instance.PartnerMetadata = resourceInstancePatchPartnerMetadata(d, instance.PartnerMetadata)
instance.NullFields = []string{"partnerMetadata"}

op, err := config.NewComputeClient(userAgent).Instances.Update(project, zone, instance.Name, instance).Do()
if err != nil {
return fmt.Errorf("Error updating partner_metadata: %s", err)
}

opErr := ComputeOperationWaitTime(config, op, project, "partner metadata to update", userAgent, d.Timeout(schema.TimeoutUpdate))
if opErr != nil {
return opErr
}
return nil
},
})

if err != nil {
return err
}
}

<% end -%>
if d.HasChange("tags") {
tags := resourceInstanceTags(d)
tagsV1 := &compute.Tags{}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import (
<% else -%>
compute "google.golang.org/api/compute/v0.beta"
<% end -%>
<% unless version == 'ga' -%>
"google.golang.org/api/googleapi"
<% end -%>
)

func TestAccComputeInstanceFromMachineImage_basic(t *testing.T) {
Expand Down Expand Up @@ -135,6 +138,37 @@ func TestAccComputeInstanceFromMachineImageWithOverride_localSsdRecoveryTimeout(
})
}

<% unless version == 'ga' -%>
func TestAccComputeInstanceFromMachineImageWithOverride_partnerMetadata(t *testing.T) {
t.Parallel()

var instance compute.Instance
instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10))
generatedInstanceName := fmt.Sprintf("tf-test-generated-%s", acctest.RandString(t, 10))
resourceName := "google_compute_instance_from_machine_image.foobar"
var namespace = "test.compute.googleapis.com"
expectedPartnerMetadata := make(map[string]compute.StructuredEntries)
expectedPartnerMetadata[namespace] = compute.StructuredEntries{
Entries: googleapi.RawMessage(`{"key1": "value1", "key2": 2,"key3": {"key31":"value31"}}`),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t),
CheckDestroy: testAccCheckComputeInstanceFromMachineImageDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeInstanceFromMachineImageWithOverride_partnerMetadata(instanceName, generatedInstanceName),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceExists(t, resourceName, &instance),
testAccCheckComputeInstancePartnerMetadata(&instance, expectedPartnerMetadata),
),
},
},
})
}
<% end -%>

func TestAccComputeInstanceFromMachineImage_overrideMetadataDotStartupScript(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -440,6 +474,78 @@ resource "google_compute_instance_from_machine_image" "foobar" {
`, instance, instance, newInstance)
}

<% unless version == 'ga' -%>
func testAccComputeInstanceFromMachineImageWithOverride_partnerMetadata(instance, newInstance string) string {
return fmt.Sprintf(`
resource "google_compute_instance" "vm" {
provider = google-beta

boot_disk {
initialize_params {
image = "debian-cloud/debian-10"
}
}

name = "%s"
machine_type = "n1-standard-1"

network_interface {
network = "default"
}

metadata = {
foo = "bar"
}

scheduling {
automatic_restart = true
}

partner_metadata = {
"test.compute.googleapis.com" = jsonencode({
entries = {
key = "value"
}
})
}
}

resource "google_compute_machine_image" "foobar" {
provider = google-beta
name = "%s"
source_instance = google_compute_instance.vm.self_link
}

resource "google_compute_instance_from_machine_image" "foobar" {
provider = google-beta
name = "%s"
zone = "us-central1-a"

source_machine_image = google_compute_machine_image.foobar.self_link

labels = {
my_key = "my_value"
}
scheduling {
automatic_restart = false
}

partner_metadata = {
"test.compute.googleapis.com" = jsonencode({
entries = {
key1 = "value1"
key2 = 2
key3 = {
key31 = "value31"
}
}
})
}
}
`, instance, instance, newInstance)
}
<% end -%>

func testAccComputeInstanceFromMachineImage_overrideMetadataDotStartupScript(instanceName, generatedInstanceName string) string {
return fmt.Sprintf(`
resource "google_compute_instance" "vm" {
Expand Down
Loading

0 comments on commit 5449997

Please sign in to comment.