diff --git a/mmv1/products/workstations/WorkstationConfig.yaml b/mmv1/products/workstations/WorkstationConfig.yaml index 624e5593fd20..39fada27bca8 100644 --- a/mmv1/products/workstations/WorkstationConfig.yaml +++ b/mmv1/products/workstations/WorkstationConfig.yaml @@ -369,6 +369,48 @@ properties: description: | Name of the snapshot to use as the source for the disk. This can be the snapshot's `self_link`, `id`, or a string in the format of `projects/{project}/global/snapshots/{snapshot}`. If set, `sizeGb` and `fsType` must be empty. Can only be updated if it has an existing value. # TODO(esu): Add conflicting fields once complex lists are supported. + - !ruby/object:Api::Type::Array + name: 'ephemeralDirectories' + description: | + Ephemeral directories which won't persist across workstation sessions. + default_from_api: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'mountPath' + description: | + Location of this directory in the running workstation. + default_from_api: true + - !ruby/object:Api::Type::NestedObject + name: 'gcePd' + description: | + An EphemeralDirectory backed by a Compute Engine persistent disk. + default_from_api: true + properties: + - !ruby/object:Api::Type::String + name: 'diskType' + description: | + Type of the disk to use. Defaults to `"pd-standard"`. + default_from_api: true + - !ruby/object:Api::Type::String + name: 'sourceSnapshot' + description: | + Name of the snapshot to use as the source for the disk. + + Must be empty if `sourceImage` is set. + Must be empty if `read_only` is false. + Updating `source_snapshot` will update content in the ephemeral directory after the workstation is restarted. + - !ruby/object:Api::Type::String + name: 'sourceImage' + description: | + Name of the disk image to use as the source for the disk. + + Must be empty `sourceSnapshot` is set. + Updating `sourceImage` will update content in the ephemeral directory after the workstation is restarted. + - !ruby/object:Api::Type::Boolean + name: 'readOnly' + description: | + Whether the disk is read only. If true, the disk may be shared by multiple VMs and `sourceSnapshot` must be set. - !ruby/object:Api::Type::NestedObject name: 'container' description: | diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb index 72565a7f5219..e29069d6ab11 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb @@ -223,6 +223,184 @@ resource "google_workstations_workstation_config" "default" { `, context) } +func TestAccWorkstationsWorkstationConfig_ephemeralDirectories(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckWorkstationsWorkstationConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkstationsWorkstationConfig_ephemeralDirectories(context), + }, + { + ResourceName: "google_workstations_workstation_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkstationsWorkstationConfig_ephemeralDirectories(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name +} + +resource "google_compute_disk" "test_source_disk" { + provider = google-beta + name = "tf-test-workstation-source-disk%{random_suffix}" + size = 10 + type = "pd-ssd" + zone = "us-central1-a" +} + +resource "google_compute_snapshot" "test_source_snapshot" { + provider = google-beta + name = "tf-test-workstation-source-snapshot%{random_suffix}" + source_disk = google_compute_disk.test_source_disk.name + zone = "us-central1-a" +} + +resource "google_workstations_workstation_cluster" "default" { + provider = google-beta + workstation_cluster_id = "tf-test-workstation-cluster%{random_suffix}" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + + labels = { + foo = "bar" + } +} + +resource "google_workstations_workstation_config" "default" { + provider = google-beta + workstation_config_id = "tf-test-workstation-config%{random_suffix}" + workstation_cluster_id = google_workstations_workstation_cluster.default.workstation_cluster_id + location = "us-central1" + + ephemeral_directories { + mount_path = "/cache" + gce_pd { + source_snapshot = google_compute_snapshot.test_source_snapshot.id + read_only = true + } + } + + labels = { + foo = "bar" + } +} +`, context) +} + +func TestAccWorkstationsWorkstationConfig_ephemeralDirectories_withSourceImage(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckWorkstationsWorkstationConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkstationsWorkstationConfig_ephemeralDirectories_withSourceImage(context), + }, + { + ResourceName: "google_workstations_workstation_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkstationsWorkstationConfig_ephemeralDirectories_withSourceImage(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name +} + +resource "google_compute_disk" "test_source_disk" { + provider = google-beta + name = "tf-test-workstation-source-disk%{random_suffix}" + size = 10 + type = "pd-ssd" + zone = "us-central1-a" +} + +resource "google_compute_image" "test_source_image" { + provider = google-beta + name = "tf-test-workstation-source-image%{random_suffix}" + source_disk = google_compute_disk.test_source_disk.name + storage_locations = ["us-central1"] +} + +resource "google_workstations_workstation_cluster" "default" { + provider = google-beta + workstation_cluster_id = "tf-test-workstation-cluster%{random_suffix}" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + + labels = { + foo = "bar" + } +} + +resource "google_workstations_workstation_config" "default" { + provider = google-beta + workstation_config_id = "tf-test-workstation-config%{random_suffix}" + workstation_cluster_id = google_workstations_workstation_cluster.default.workstation_cluster_id + location = "us-central1" + + ephemeral_directories { + mount_path = "/cache" + gce_pd { + disk_type = "pd-standard" + source_image = google_compute_image.test_source_image.id + read_only = true + } + } + + labels = { + foo = "bar" + } +} +`, context) +} func TestAccWorkstationsWorkstationConfig_serviceAccount(t *testing.T) { t.Parallel()