diff --git a/google-beta/resource_compute_image.go b/google-beta/resource_compute_image.go index a599cad1fa..b656fac245 100644 --- a/google-beta/resource_compute_image.go +++ b/google-beta/resource_compute_image.go @@ -65,6 +65,21 @@ func resourceComputeImage() *schema.Resource { Optional: true, ForceNew: true, }, + "guest_os_features": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"MULTI_IP_SUBNET", "SECURE_BOOT", "UEFI_COMPATIBLE", "VIRTIO_SCSI_MULTIQUEUE", "WINDOWS", ""}, false), + }, + }, + }, + }, "labels": { Type: schema.TypeMap, Optional: true, @@ -161,6 +176,12 @@ func resourceComputeImageCreate(d *schema.ResourceData, meta interface{}) error } else if v, ok := d.GetOkExists("family"); !isEmptyValue(reflect.ValueOf(familyProp)) && (ok || !reflect.DeepEqual(v, familyProp)) { obj["family"] = familyProp } + guestOsFeaturesProp, err := expandComputeImageGuestOsFeatures(d.Get("guest_os_features"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("guest_os_features"); !isEmptyValue(reflect.ValueOf(guestOsFeaturesProp)) && (ok || !reflect.DeepEqual(v, guestOsFeaturesProp)) { + obj["guestOsFeatures"] = guestOsFeaturesProp + } labelsProp, err := expandComputeImageLabels(d.Get("labels"), d, config) if err != nil { return err @@ -277,6 +298,9 @@ func resourceComputeImageRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("family", flattenComputeImageFamily(res["family"], d)); err != nil { return fmt.Errorf("Error reading Image: %s", err) } + if err := d.Set("guest_os_features", flattenComputeImageGuestOsFeatures(res["guestOsFeatures"], d)); err != nil { + return fmt.Errorf("Error reading Image: %s", err) + } if err := d.Set("labels", flattenComputeImageLabels(res["labels"], d)); err != nil { return fmt.Errorf("Error reading Image: %s", err) } @@ -447,6 +471,28 @@ func flattenComputeImageFamily(v interface{}, d *schema.ResourceData) interface{ return v } +func flattenComputeImageGuestOsFeatures(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + 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 = append(transformed, map[string]interface{}{ + "type": flattenComputeImageGuestOsFeaturesType(original["type"], d), + }) + } + return transformed +} +func flattenComputeImageGuestOsFeaturesType(v interface{}, d *schema.ResourceData) interface{} { + return v +} + func flattenComputeImageLabels(v interface{}, d *schema.ResourceData) interface{} { return v } @@ -485,6 +531,32 @@ func expandComputeImageFamily(v interface{}, d TerraformResourceData, config *Co return v, nil } +func expandComputeImageGuestOsFeatures(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + 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 := expandComputeImageGuestOsFeaturesType(original["type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedType); val.IsValid() && !isEmptyValue(val) { + transformed["type"] = transformedType + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeImageGuestOsFeaturesType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeImageLabels(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) { if v == nil { return map[string]string{}, nil diff --git a/google-beta/resource_compute_image_generated_test.go b/google-beta/resource_compute_image_generated_test.go index 0f30d8b812..df0b6632ca 100644 --- a/google-beta/resource_compute_image_generated_test.go +++ b/google-beta/resource_compute_image_generated_test.go @@ -61,6 +61,51 @@ resource "google_compute_image" "example" { `, context) } +func TestAccComputeImage_imageGuestOsExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeImageDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeImage_imageGuestOsExample(context), + }, + { + ResourceName: "google_compute_image.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"raw_disk"}, + }, + }, + }) +} + +func testAccComputeImage_imageGuestOsExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_image" "example" { + name = "example-image%{random_suffix}" + + raw_disk { + source = "https://storage.googleapis.com/bosh-cpi-artifacts/bosh-stemcell-3262.4-google-kvm-ubuntu-trusty-go_agent-raw.tar.gz" + } + + guest_os_features { + type = "SECURE_BOOT" + } + + guest_os_features { + type = "MULTI_IP_SUBNET" + } +} +`, context) +} + func testAccCheckComputeImageDestroy(s *terraform.State) error { for name, rs := range s.RootModule().Resources { if rs.Type != "google_compute_image" { diff --git a/website/docs/r/compute_image.html.markdown b/website/docs/r/compute_image.html.markdown index af2bfa6187..771d47a80c 100644 --- a/website/docs/r/compute_image.html.markdown +++ b/website/docs/r/compute_image.html.markdown @@ -62,6 +62,31 @@ resource "google_compute_image" "example" { } } ``` +
+## Example Usage - Image Guest Os + + +```hcl +resource "google_compute_image" "example" { + name = "example-image" + + raw_disk { + source = "https://storage.googleapis.com/bosh-cpi-artifacts/bosh-stemcell-3262.4-google-kvm-ubuntu-trusty-go_agent-raw.tar.gz" + } + + guest_os_features { + type = "SECURE_BOOT" + } + + guest_os_features { + type = "MULTI_IP_SUBNET" + } +} +``` ## Argument Reference @@ -99,6 +124,11 @@ The following arguments are supported: not deprecated. The name of the image family must comply with RFC1035. +* `guest_os_features` - + (Optional) + A list of features to enable on the guest operating system. + Applicable only for bootable images. Structure is documented below. + * `labels` - (Optional) Labels to apply to this Image. @@ -121,6 +151,12 @@ The following arguments are supported: If it is not provided, the provider project is used. +The `guest_os_features` block supports: + +* `type` - + (Optional) + 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. + The `raw_disk` block supports: * `container_type` -