Skip to content

Commit

Permalink
Add guest_os_features and licenses to disk and regional disk (#7970) (#…
Browse files Browse the repository at this point in the history
…14660)

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored May 19, 2023
1 parent 2574fbb commit a43f641
Show file tree
Hide file tree
Showing 9 changed files with 604 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/7970.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
compute: added `guest_os_features` and `licenses` fields to `google_compute_disk` and `google_compute_region_disk`
```
126 changes: 126 additions & 0 deletions google/resource_compute_disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (

"github.com/hashicorp/terraform-provider-google/google/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
"github.com/hashicorp/terraform-provider-google/google/verify"
)

// diffsupress for beta and to check change in source_disk attribute
Expand Down Expand Up @@ -375,6 +376,16 @@ encryption key that protects this resource.`,
},
},
},
"guest_os_features": {
Type: schema.TypeSet,
Computed: true,
Optional: true,
ForceNew: true,
Description: `A list of features to enable on the guest operating system.
Applicable only for bootable disks.`,
Elem: computeDiskGuestOsFeaturesSchema(),
// Default schema.HashSchema is used.
},
"image": {
Type: schema.TypeString,
Optional: true,
Expand All @@ -396,6 +407,17 @@ These images can be referred by family name here.`,
Description: `Labels to apply to this disk. A list of key->value pairs.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"licenses": {
Type: schema.TypeList,
Computed: true,
Optional: true,
ForceNew: true,
Description: `Any applicable license URI.`,
Elem: &schema.Schema{
Type: schema.TypeString,
DiffSuppressFunc: compareSelfLinkOrResourceName,
},
},
"physical_block_size_bytes": {
Type: schema.TypeInt,
Computed: true,
Expand Down Expand Up @@ -638,6 +660,20 @@ project/zones/zone/instances/instance`,
}
}

func computeDiskGuestOsFeaturesSchema() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: verify.ValidateEnum([]string{"MULTI_IP_SUBNET", "SECURE_BOOT", "SEV_CAPABLE", "UEFI_COMPATIBLE", "VIRTIO_SCSI_MULTIQUEUE", "WINDOWS", "GVNIC", "SEV_LIVE_MIGRATABLE", "SEV_SNP_CAPABLE", "SUSPEND_RESUME_COMPATIBLE", "TDX_CAPABLE"}),
Description: `The type of supported feature. Read [Enabling guest operating system features](https://cloud.google.com/compute/docs/images/create-delete-deprecate-private-images#guest-os-features) to see a list of available options. Possible values: ["MULTI_IP_SUBNET", "SECURE_BOOT", "SEV_CAPABLE", "UEFI_COMPATIBLE", "VIRTIO_SCSI_MULTIQUEUE", "WINDOWS", "GVNIC", "SEV_LIVE_MIGRATABLE", "SEV_SNP_CAPABLE", "SUSPEND_RESUME_COMPATIBLE", "TDX_CAPABLE"]`,
},
},
}
}

func resourceComputeDiskCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
Expand Down Expand Up @@ -706,6 +742,18 @@ func resourceComputeDiskCreate(d *schema.ResourceData, meta interface{}) error {
} else if v, ok := d.GetOkExists("provisioned_iops"); !tpgresource.IsEmptyValue(reflect.ValueOf(provisionedIopsProp)) && (ok || !reflect.DeepEqual(v, provisionedIopsProp)) {
obj["provisionedIops"] = provisionedIopsProp
}
guestOsFeaturesProp, err := expandComputeDiskGuestOsFeatures(d.Get("guest_os_features"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("guest_os_features"); !tpgresource.IsEmptyValue(reflect.ValueOf(guestOsFeaturesProp)) && (ok || !reflect.DeepEqual(v, guestOsFeaturesProp)) {
obj["guestOsFeatures"] = guestOsFeaturesProp
}
licensesProp, err := expandComputeDiskLicenses(d.Get("licenses"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("licenses"); !tpgresource.IsEmptyValue(reflect.ValueOf(licensesProp)) && (ok || !reflect.DeepEqual(v, licensesProp)) {
obj["licenses"] = licensesProp
}
zoneProp, err := expandComputeDiskZone(d.Get("zone"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -893,6 +941,12 @@ func resourceComputeDiskRead(d *schema.ResourceData, meta interface{}) error {
if err := d.Set("provisioned_iops", flattenComputeDiskProvisionedIops(res["provisionedIops"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("guest_os_features", flattenComputeDiskGuestOsFeatures(res["guestOsFeatures"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("licenses", flattenComputeDiskLicenses(res["licenses"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("zone", flattenComputeDiskZone(res["zone"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
Expand Down Expand Up @@ -1273,6 +1327,35 @@ func flattenComputeDiskProvisionedIops(v interface{}, d *schema.ResourceData, co
return v // let terraform core handle it otherwise
}

func flattenComputeDiskGuestOsFeatures(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
l := v.([]interface{})
transformed := schema.NewSet(schema.HashResource(computeDiskGuestOsFeaturesSchema()), []interface{}{})
for _, raw := range l {
original := raw.(map[string]interface{})
if len(original) < 1 {
// Do not include empty json objects coming back from the api
continue
}
transformed.Add(map[string]interface{}{
"type": flattenComputeDiskGuestOsFeaturesType(original["type"], d, config),
})
}
return transformed
}
func flattenComputeDiskGuestOsFeaturesType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenComputeDiskLicenses(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
return convertAndMapStringArr(v.([]interface{}), tpgresource.ConvertSelfLinkToV1)
}

func flattenComputeDiskZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
Expand Down Expand Up @@ -1457,6 +1540,49 @@ func expandComputeDiskProvisionedIops(v interface{}, d tpgresource.TerraformReso
return v, nil
}

func expandComputeDiskGuestOsFeatures(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
v = v.(*schema.Set).List()
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
continue
}
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedType, err := expandComputeDiskGuestOsFeaturesType(original["type"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedType); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["type"] = transformedType
}

req = append(req, transformed)
}
return req, nil
}

func expandComputeDiskGuestOsFeaturesType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandComputeDiskLicenses(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
return nil, fmt.Errorf("Invalid value for licenses: nil")
}
f, err := tpgresource.ParseGlobalFieldValue("licenses", raw.(string), "project", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for licenses: %s", err)
}
req = append(req, f.RelativeLink())
}
return req, nil
}

func expandComputeDiskZone(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
f, err := tpgresource.ParseGlobalFieldValue("zones", v.(string), "project", d, config, true)
if err != nil {
Expand Down
54 changes: 54 additions & 0 deletions google/resource_compute_disk_generated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,60 @@ resource "google_compute_disk" "default" {
`, context)
}

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

context := map[string]interface{}{
"random_suffix": RandString(t, 10),
}

VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckComputeDiskDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeDisk_diskFeaturesExample(context),
},
{
ResourceName: "google_compute_disk.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"type", "zone", "snapshot"},
},
},
})
}

func testAccComputeDisk_diskFeaturesExample(context map[string]interface{}) string {
return Nprintf(`
resource "google_compute_disk" "default" {
name = "tf-test-test-disk-features%{random_suffix}"
type = "pd-ssd"
zone = "us-central1-a"
labels = {
environment = "dev"
}
guest_os_features {
type = "SECURE_BOOT"
}
guest_os_features {
type = "MULTI_IP_SUBNET"
}
guest_os_features {
type = "WINDOWS"
}
licenses = ["https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-core"]
physical_block_size_bytes = 4096
}
`, context)
}

func testAccCheckComputeDiskDestroyProducer(t *testing.T) func(s *terraform.State) error {
return func(s *terraform.State) error {
for name, rs := range s.RootModule().Resources {
Expand Down
69 changes: 69 additions & 0 deletions google/resource_compute_disk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,35 @@ func TestAccComputeDisk_cloneDisk(t *testing.T) {
})
}

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

diskName := fmt.Sprintf("tf-test-%s", RandString(t, 10))

VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: ProtoV5ProviderFactories(t),
Steps: []resource.TestStep{
{
Config: testAccComputeDisk_features(diskName),
},
{
ResourceName: "google_compute_disk.foobar",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccComputeDisk_featuresUpdated(diskName),
},
{
ResourceName: "google_compute_disk.foobar",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccComputeDisk_basic(diskName string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
Expand Down Expand Up @@ -920,3 +949,43 @@ resource "google_compute_disk" "foobar-1" {
}
`, diskName)
}

func testAccComputeDisk_features(diskName string) string {
return fmt.Sprintf(`
resource "google_compute_disk" "foobar" {
name = "%s"
size = 50
type = "pd-ssd"
zone = "us-central1-a"
labels = {
my-label = "my-label-value"
}
guest_os_features {
type = "SECURE_BOOT"
}
}
`, diskName)
}

func testAccComputeDisk_featuresUpdated(diskName string) string {
return fmt.Sprintf(`
resource "google_compute_disk" "foobar" {
name = "%s"
size = 50
type = "pd-ssd"
zone = "us-central1-a"
labels = {
my-label = "my-label-value"
}
guest_os_features {
type = "SECURE_BOOT"
}
guest_os_features {
type = "MULTI_IP_SUBNET"
}
}
`, diskName)
}
Loading

0 comments on commit a43f641

Please sign in to comment.