diff --git a/README.md b/README.md
index 08907864fb..5840a8f852 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@ Currently available modules:
- **networking** - [DNS](./modules/dns), [DNS Response Policy](./modules/dns-response-policy/), [Cloud Endpoints](./modules/endpoints), [address reservation](./modules/net-address), [NAT](./modules/net-cloudnat), [VLAN Attachment](./modules/net-vlan-attachment/), [External Application LB](./modules/net-lb-app-ext/), [External Passthrough Network LB](./modules/net-lb-ext), [Firewall policy](./modules/net-firewall-policy), [Internal Application LB](./modules/net-lb-app-int), [Internal Passthrough Network LB](./modules/net-lb-int), [Internal Proxy Network LB](./modules/net-lb-proxy-int), [IPSec over Interconnect](./modules/net-ipsec-over-interconnect), [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC peering](./modules/net-vpc-peering), [VPN dynamic](./modules/net-vpn-dynamic), [HA VPN](./modules/net-vpn-ha), [VPN static](./modules/net-vpn-static), [Service Directory](./modules/service-directory), [Secure Web Proxy](./modules/net-swp)
- **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [COS container](./modules/cloud-config-container/cos-generic-metadata/) (coredns, mysql, onprem, squid), [GKE cluster](./modules/gke-cluster-standard), [GKE hub](./modules/gke-hub), [GKE nodepool](./modules/gke-nodepool), [GCVE private cloud](./modules/gcve-private-cloud)
- **data** - [BigQuery dataset](./modules/bigquery-dataset), [Bigtable instance](./modules/bigtable-instance), [Dataplex](./modules/dataplex), [Dataplex DataScan](./modules/dataplex-datascan/), [Cloud SQL instance](./modules/cloudsql-instance), [Data Catalog Policy Tag](./modules/data-catalog-policy-tag), [Datafusion](./modules/datafusion), [Dataproc](./modules/dataproc), [GCS](./modules/gcs), [Pub/Sub](./modules/pubsub)
-- **development** - [API Gateway](./modules/api-gateway), [Apigee](./modules/apigee), [Artifact Registry](./modules/artifact-registry), [Container Registry](./modules/container-registry), [Cloud Source Repository](./modules/source-repository)
+- **development** - [API Gateway](./modules/api-gateway), [Apigee](./modules/apigee), [Artifact Registry](./modules/artifact-registry), [Container Registry](./modules/container-registry), [Cloud Source Repository](./modules/source-repository), [Workstation cluster](./modules/workstation-cluster)
- **security** - [Binauthz](./modules/binauthz/), [KMS](./modules/kms), [SecretManager](./modules/secret-manager), [VPC Service Control](./modules/vpc-sc)
- **serverless** - [Cloud Function v1](./modules/cloud-function-v1), [Cloud Function v2](./modules/cloud-function-v2), [Cloud Run](./modules/cloud-run)
diff --git a/default-versions.tf b/default-versions.tf
index 3adb51d3bd..4d3bd967e1 100644
--- a/default-versions.tf
+++ b/default-versions.tf
@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
- version = ">= 5.4.0, < 6.0.0" # tftest
+ version = ">= 5.6.0, < 6.0.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
- version = ">= 5.4.0, < 6.0.0" # tftest
+ version = ">= 5.6.0, < 6.0.0" # tftest
}
}
}
diff --git a/modules/README.md b/modules/README.md
index cefc5e5592..fa54a68c46 100644
--- a/modules/README.md
+++ b/modules/README.md
@@ -92,6 +92,7 @@ These modules are used in the examples included in this repository. If you are u
- [Artifact Registry](./artifact-registry)
- [Container Registry](./container-registry)
- [Cloud Source Repository](./source-repository)
+- [Workstation cluster](./workstation-cluster)
## Security
diff --git a/modules/workstation-cluster/README.md b/modules/workstation-cluster/README.md
new file mode 100644
index 0000000000..20d5e2d029
--- /dev/null
+++ b/modules/workstation-cluster/README.md
@@ -0,0 +1,158 @@
+# Workstation cluster
+
+This module allows to create a workstation cluster with associated workstation configs and workstations. In addition to this it allows to set up IAM bindings for the workstation configs and the workstations.
+
+## Examples
+
+## Simple example
+```hcl
+module "workstation-cluster" {
+ source = "./fabric/modules/workstation-cluster"
+ project_id = var.project_id
+ workstation_cluster_id = "my-workstation-cluster"
+ location = var.region
+ network = var.vpc.self_link
+ subnetwork = var.subnet.self_link
+ workstation_configs = {
+ my-workstation-config = {
+ workstations = {
+ my-workstation = {
+ labels = {
+ team = "my-team"
+ }
+ }
+ }
+ }
+ }
+}
+# tftest modules=1 resources=3 inventory=simple.yaml
+```
+
+## Private Cluster
+```hcl
+module "workstation-cluster" {
+ source = "./fabric/modules/workstation-cluster"
+ project_id = var.project_id
+ workstation_cluster_id = "my-workstation-cluster"
+ location = var.region
+ network = var.vpc.self_link
+ subnetwork = var.subnet.self_link
+ private_cluster_config = {
+ enable_private_endpoint = true
+ }
+ workstation_configs = {
+ my-workstation-config = {
+ workstations = {
+ my-workstation = {
+ labels = {
+ team = "my-team"
+ }
+ }
+ }
+ }
+ }
+}
+# tftest modules=1 resources=3 inventory=private-cluster.yaml
+```
+
+## Custom container
+
+```hcl
+module "workstation-cluster" {
+ source = "./fabric/modules/workstation-cluster"
+ project_id = var.project_id
+ workstation_cluster_id = "my-workstation-cluster"
+ location = var.region
+ network = var.vpc.self_link
+ subnetwork = var.subnet.self_link
+ workstation_configs = {
+ my-workstation-config = {
+ container = {
+ image = "repo/my-image:v10.0.0"
+ args = ["--arg1", "value1", "--arg2", "value2"]
+ env = {
+ VAR1 = "VALUE1"
+ VAR2 = "VALUE2"
+ }
+ working_dir = "/my-dir"
+ }
+ workstations = {
+ my-workstation = {
+ labels = {
+ team = "my-team"
+ }
+ }
+ }
+ }
+ }
+}
+# tftest modules=1 resources=3 inventory=custom-container.yaml
+```
+
+## IAM
+
+```hcl
+module "workstation-cluster" {
+ source = "./fabric/modules/workstation-cluster"
+ project_id = var.project_id
+ workstation_cluster_id = "my-workstation-cluster"
+ location = var.region
+ network = var.vpc.self_link
+ subnetwork = var.subnet.self_link
+ workstation_configs = {
+ my-workstation-config = {
+ workstations = {
+ my-workstation = {
+ labels = {
+ team = "my-team"
+ }
+ iam = {
+ "roles/workstations.user" = ["user:user1@my-org.com"]
+ }
+ }
+ }
+ iam = {
+ "roles/viewer" = ["group:group1@my-org.com"]
+ }
+ iam_bindings = {
+ workstations-config-viewer = {
+ role = "roles/viewer"
+ members = ["group:group2@my-org.com"]
+ condition = {
+ title = "limited-access"
+ expression = "resource.name.startsWith('my-')"
+ }
+ }
+ }
+ iam_bindings_additive = {
+ workstations-config-editor = {
+ role = "roles/editor"
+ member = "group:group3@my-org.com"
+ condition = {
+ title = "limited-access"
+ expression = "resource.name.startsWith('my-')"
+ }
+ }
+ }
+ }
+ }
+}
+# tftest modules=1 resources=7 inventory=iam.yaml
+```
+
+## Variables
+
+| name | description | type | required | default |
+|---|---|:---:|:---:|:---:|
+| [network](variables.tf#L47) | Network ID. | string
| ✓ | |
+| [project_id](variables.tf#L62) | Cluster ID. | string
| ✓ | |
+| [subnetwork](variables.tf#L67) | Subnet ID. | string
| ✓ | |
+| [workstation_cluster_id](variables.tf#L72) | Workstation cluster ID. | string
| ✓ | |
+| [workstation_configs](variables.tf#L77) | Workstation configurations. | map(object({…}))
| ✓ | |
+| [annotations](variables.tf#L17) | Annotations. | map(string)
| | {}
|
+| [display_name](variables.tf#L23) | Display name. | string
| | null
|
+| [domain](variables.tf#L29) | Domain. | string
| | null
|
+| [labels](variables.tf#L35) | Labels. | map(string)
| | {}
|
+| [location](variables.tf#L41) | Location. | string
| | null
|
+| [private_cluster_config](variables.tf#L52) | Private cluster config. | object({…})
| | {}
|
+
diff --git a/modules/workstation-cluster/iam.tf b/modules/workstation-cluster/iam.tf
new file mode 100644
index 0000000000..3319912fa3
--- /dev/null
+++ b/modules/workstation-cluster/iam.tf
@@ -0,0 +1,122 @@
+/**
+ * Copyright 2023 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Copyright 2023 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+# tfdoc:file:description IAM bindings
+
+resource "google_workstations_workstation_config_iam_binding" "authoritative" {
+ provider = google-beta
+ for_each = merge(flatten([for k1, v1 in var.workstation_configs : { for k2, v2 in v1.iam : "${k1}-${k2}" => {
+ workstation_config_id = k1
+ role = k2
+ members = v2
+ } }])...)
+ project = google_workstations_workstation_config.configs[each.value.workstation_config_id].project
+ location = google_workstations_workstation_config.configs[each.value.workstation_config_id].location
+ workstation_cluster_id = google_workstations_workstation_config.configs[each.value.workstation_config_id].workstation_cluster_id
+ workstation_config_id = google_workstations_workstation_config.configs[each.value.workstation_config_id].workstation_config_id
+ role = each.value.role
+ members = each.value.members
+}
+
+resource "google_workstations_workstation_config_iam_binding" "bindings" {
+ provider = google-beta
+ for_each = merge(flatten([for k1, v1 in var.workstation_configs : { for k2, v2 in v1.iam_bindings : "${k1}-${k2}" => merge(v2, {
+ workstation_config_id = k1
+ }) }])...)
+ project = google_workstations_workstation_config.configs[each.value.workstation_config_id].project
+ location = google_workstations_workstation_config.configs[each.value.workstation_config_id].location
+ workstation_cluster_id = google_workstations_workstation_config.configs[each.value.workstation_config_id].workstation_cluster_id
+ workstation_config_id = google_workstations_workstation_config.configs[each.value.workstation_config_id].workstation_config_id
+ role = each.value.role
+ members = each.value.members
+}
+
+resource "google_workstations_workstation_config_iam_member" "bindings" {
+ provider = google-beta
+ for_each = merge(flatten([for k1, v1 in var.workstation_configs : { for k2, v2 in v1.iam_bindings_additive : "${k1}-${k2}" => merge(v2, {
+ workstation_config_id = k1
+ }) }])...)
+ project = google_workstations_workstation_config.configs[each.value.workstation_config_id].project
+ location = google_workstations_workstation_config.configs[each.value.workstation_config_id].location
+ workstation_cluster_id = google_workstations_workstation_config.configs[each.value.workstation_config_id].workstation_cluster_id
+ workstation_config_id = google_workstations_workstation_config.configs[each.value.workstation_config_id].workstation_config_id
+ role = each.value.role
+ member = each.value.member
+}
+
+resource "google_workstations_workstation_iam_binding" "authoritative" {
+ provider = google-beta
+ for_each = merge(flatten([for k1, v1 in var.workstation_configs : [for k2, v2 in v1.workstations : { for k3, v3 in v2.iam : "${k1}-${k2}-${k3}" => {
+ workstation_config_id = k1
+ workstation_id = k2
+ role = k3
+ members = v3
+ } }]])...)
+ project = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].project
+ location = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].location
+ workstation_cluster_id = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].workstation_cluster_id
+ workstation_config_id = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].workstation_config_id
+ workstation_id = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].workstation_id
+ role = each.value.role
+ members = each.value.members
+}
+
+resource "google_workstations_workstation_iam_binding" "bindings" {
+ provider = google-beta
+ for_each = merge(flatten([for k1, v1 in var.workstation_configs : [for k2, v2 in v1.workstations : { for k3, v3 in v2.iam_bindings : "${k1}-${k2}-${k3}" => merge(v3, {
+ workstation_config_id = k1
+ workstation_id = k2
+ }) }]])...)
+ project = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].project
+ location = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].location
+ workstation_cluster_id = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].workstation_cluster_id
+ workstation_config_id = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].workstation_config_id
+ workstation_id = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].workstation_id
+ role = each.value.role
+ members = each.value.members
+}
+
+resource "google_workstations_workstation_iam_member" "bindings" {
+ provider = google-beta
+ for_each = merge(flatten([for k1, v1 in var.workstation_configs : [for k2, v2 in v1.workstations : { for k3, v3 in v2.iam_bindings_additive : "${k1}-${k2}-${k3}" => merge(v3, {
+ workstation_config_id = k1
+ workstation_id = k2
+ }) }]])...)
+ project = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].project
+ location = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].location
+ workstation_cluster_id = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].workstation_cluster_id
+ workstation_config_id = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].workstation_config_id
+ workstation_id = google_workstations_workstation.workstations["${each.value.workstation_config_id}-${each.value.workstation_id}"].workstation_id
+ role = each.value.role
+ member = each.value.member
+}
+
diff --git a/modules/workstation-cluster/main.tf b/modules/workstation-cluster/main.tf
new file mode 100644
index 0000000000..a2318d3ed0
--- /dev/null
+++ b/modules/workstation-cluster/main.tf
@@ -0,0 +1,129 @@
+/**
+ * Copyright 2023 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+locals {
+ workstations = merge(flatten([for k1, v1 in var.workstation_configs : { for k2, v2 in v1.workstations : "${k1}-${k2}" => merge({
+ workstation_config_id = k1
+ workstation_id = k2
+ }, v2) }])...)
+}
+
+resource "google_workstations_workstation_cluster" "cluster" {
+ provider = google-beta
+ workstation_cluster_id = var.workstation_cluster_id
+ project = var.project_id
+ display_name = var.display_name
+ network = var.network
+ subnetwork = var.subnetwork
+ location = var.location
+ annotations = var.annotations
+ labels = var.labels
+ dynamic "private_cluster_config" {
+ for_each = var.private_cluster_config == null ? [] : [""]
+ content {
+ enable_private_endpoint = var.private_cluster_config.enable_private_endpoint
+ allowed_projects = var.private_cluster_config.allowed_projects
+ }
+ }
+ dynamic "domain_config" {
+ for_each = var.domain == null ? [] : [""]
+ content {
+ domain = var.domain
+ }
+ }
+}
+
+resource "google_workstations_workstation_config" "configs" {
+ for_each = var.workstation_configs
+ provider = google-beta
+ project = google_workstations_workstation_cluster.cluster.project
+ workstation_config_id = each.key
+ workstation_cluster_id = google_workstations_workstation_cluster.cluster.workstation_cluster_id
+ location = google_workstations_workstation_cluster.cluster.location
+ idle_timeout = each.value.idle_timeout
+ running_timeout = each.value.running_timeout
+ replica_zones = each.value.replica_zones
+ annotations = each.value.annotations
+ labels = each.value.labels
+ dynamic "host" {
+ for_each = each.value.gce_instance == null ? [] : [""]
+ content {
+ gce_instance {
+ machine_type = each.value.gce_instance.machine_type
+ service_account = each.value.gce_instance.service_account
+ service_account_scopes = each.value.gce_instance.service_account_scopes
+ pool_size = each.value.gce_instance.pool_size
+ boot_disk_size_gb = each.value.gce_instance.boot_disk_size_gb
+ tags = each.value.gce_instance.tags
+ disable_public_ip_addresses = each.value.disable_public_ip_addresses
+ enable_nested_virtualization = each.value.enable_nested_virtualization
+ dynamic "shielded_instance_config" {
+ for_each = each.value.gce_instance.shielded_instance_config == null ? [] : [""]
+ content {
+ enable_secure_boot = each.value.gce_instance.shielded_instance_config.enable_secure_boot
+ enable_vtpm = each.value.gce_instance.shielded_instance_config.enable_vtpm
+ enable_integrity_monitoring = each.value.gce_instance.shielded_instance_config.enable_integrity_monitoring
+ }
+ }
+ dynamic "confidential_instance_config" {
+ for_each = each.value.gce_instance.enable_confidential_compute ? [] : [""]
+ content {
+ enable_confidential_compute = true
+ }
+ }
+ dynamic "accelerators" {
+ for_each = each.value.gce_instance.accelerators
+ content {
+ type = accelerators.value.type
+ count = accelerators.value.count
+ }
+ }
+ }
+ }
+ }
+ dynamic "container" {
+ for_each = each.value.container == null ? [] : [""]
+ content {
+ image = each.value.container.image
+ command = each.value.container.command
+ args = each.value.container.args
+ working_dir = each.value.container.working_dir
+ env = each.value.container.env
+ run_as_user = each.value.container.run_as_user
+ }
+ }
+ dynamic "encryption_key" {
+ for_each = each.value.encryption_key == null ? [] : [""]
+ content {
+ kms_key = each.value.encryption_key.kms_key
+ kms_key_service_account = each.value.encryption_key.kms_key_service_account
+ }
+ }
+}
+
+resource "google_workstations_workstation" "workstations" {
+ provider = google-beta
+ for_each = local.workstations
+ project = google_workstations_workstation_cluster.cluster.project
+ workstation_id = each.value.workstation_id
+ workstation_config_id = google_workstations_workstation_config.configs[each.value.workstation_config_id].workstation_config_id
+ workstation_cluster_id = google_workstations_workstation_cluster.cluster.workstation_cluster_id
+ location = google_workstations_workstation_cluster.cluster.location
+ labels = each.value.labels
+ env = each.value.env
+ annotations = each.value.annotations
+}
+
diff --git a/modules/workstation-cluster/outputs.tf b/modules/workstation-cluster/outputs.tf
new file mode 100644
index 0000000000..8190cc901e
--- /dev/null
+++ b/modules/workstation-cluster/outputs.tf
@@ -0,0 +1,15 @@
+/**
+ * Copyright 2023 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
diff --git a/modules/workstation-cluster/variables.tf b/modules/workstation-cluster/variables.tf
new file mode 100644
index 0000000000..e631beece6
--- /dev/null
+++ b/modules/workstation-cluster/variables.tf
@@ -0,0 +1,154 @@
+/**
+ * Copyright 2023 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+variable "annotations" {
+ description = "Annotations."
+ type = map(string)
+ default = {}
+}
+
+variable "display_name" {
+ description = "Display name."
+ type = string
+ default = null
+}
+
+variable "domain" {
+ description = "Domain."
+ type = string
+ default = null
+}
+
+variable "labels" {
+ description = "Labels."
+ type = map(string)
+ default = {}
+}
+
+variable "location" {
+ description = "Location."
+ type = string
+ default = null
+}
+
+variable "network" {
+ description = "Network ID."
+ type = string
+}
+
+variable "private_cluster_config" {
+ description = "Private cluster config."
+ type = object({
+ enable_private_endpoint = optional(bool, false)
+ allowed_projects = optional(list(string))
+ })
+ nullable = false
+ default = {}
+}
+
+variable "project_id" {
+ description = "Cluster ID."
+ type = string
+}
+
+variable "subnetwork" {
+ description = "Subnet ID."
+ type = string
+}
+
+variable "workstation_cluster_id" {
+ description = "Workstation cluster ID."
+ type = string
+}
+
+variable "workstation_configs" {
+ description = "Workstation configurations."
+ type = map(object({
+ annotations = optional(map(string))
+ container = optional(object({
+ image = optional(string)
+ command = optional(list(string), [])
+ args = optional(list(string), [])
+ working_dir = optional(string)
+ env = optional(map(string), {})
+ run_as_user = optional(string)
+ }))
+ display_name = optional(string)
+ enable_audit_agent = optional(bool)
+ encryption_key = optional(object({
+ kms_key = string
+ kms_key_service_account = string
+ }))
+ gce_instance = optional(object({
+ machine_type = optional(string)
+ service_account = optional(string)
+ service_account_scopes = optional(list(string), [])
+ pool_size = optional(number)
+ boot_disk_size_gb = optional(number)
+ tags = optional(list(string))
+ disable_public_ip_addresses = optional(bool, false)
+ enable_nested_virtualization = optional(bool, false)
+ shielded_instance_config = optional(object({
+ enable_secure_boot = optional(bool, false)
+ enable_vtpm = optional(bool, false)
+ enable_integrity_monitoring = optional(bool, false)
+ }))
+ enable_confidential_compute = optional(bool, false)
+ accelerators = optional(list(object({
+ type = optional(string)
+ count = optional(number)
+ })), [])
+ }))
+ iam = optional(map(list(string)), {})
+ iam_bindings = optional(map(object({
+ role = string
+ members = list(string)
+ })), {})
+ iam_bindings_additive = optional(map(object({
+ role = string
+ member = string
+ })), {})
+ idle_timeout = optional(string)
+ labels = optional(map(string))
+ persistent_directories = optional(list(object({
+ mount_path = optional(string)
+ gce_pd = optional(object({
+ size_gb = optional(number)
+ fs_type = optional(string)
+ disk_type = optional(string)
+ source_snapshot = optional(string)
+ reclaim_policy = optional(string)
+ }))
+ })), [])
+ running_timeout = optional(string)
+ replica_zones = optional(list(string))
+ workstations = optional(map(object({
+ annotations = optional(map(string))
+ display_name = optional(string)
+ env = optional(map(string))
+ iam = optional(map(list(string)), {})
+ iam_bindings = optional(map(object({
+ role = string
+ members = list(string)
+ })), {})
+ iam_bindings_additive = optional(map(object({
+ role = string
+ member = string
+ })), {})
+ labels = optional(map(string))
+ })), {})
+ }))
+}
\ No newline at end of file
diff --git a/modules/workstation-cluster/versions.tf b/modules/workstation-cluster/versions.tf
new file mode 100644
index 0000000000..4d3bd967e1
--- /dev/null
+++ b/modules/workstation-cluster/versions.tf
@@ -0,0 +1,29 @@
+# Copyright 2023 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+terraform {
+ required_version = ">= 1.4.4"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 5.6.0, < 6.0.0" # tftest
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 5.6.0, < 6.0.0" # tftest
+ }
+ }
+}
+
+
diff --git a/tests/modules/workstation_cluster/examples/custom-container.yaml b/tests/modules/workstation_cluster/examples/custom-container.yaml
new file mode 100644
index 0000000000..ed3c7eb3e8
--- /dev/null
+++ b/tests/modules/workstation_cluster/examples/custom-container.yaml
@@ -0,0 +1,77 @@
+# Copyright 2023 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+values:
+ module.workstation-cluster.google_workstations_workstation.workstations["my-workstation-config-my-workstation"]:
+ annotations: null
+ display_name: null
+ effective_labels:
+ team: my-team
+ env: null
+ labels:
+ team: my-team
+ location: region
+ project: project-id
+ terraform_labels:
+ team: my-team
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+ workstation_id: my-workstation
+ module.workstation-cluster.google_workstations_workstation_cluster.cluster:
+ annotations: null
+ display_name: null
+ domain_config: []
+ labels: null
+ location: region
+ network: projects/xxx/global/networks/aaa
+ private_cluster_config:
+ - enable_private_endpoint: false
+ project: project-id
+ subnetwork: subnet_self_link
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ module.workstation-cluster.google_workstations_workstation_config.configs["my-workstation-config"]:
+ annotations: null
+ container:
+ - args:
+ - --arg1
+ - value1
+ - --arg2
+ - value2
+ command: []
+ env:
+ VAR1: VALUE1
+ VAR2: VALUE2
+ image: repo/my-image:v10.0.0
+ run_as_user: null
+ working_dir: /my-dir
+ display_name: null
+ enable_audit_agent: null
+ encryption_key: []
+ idle_timeout: 1200s
+ labels: null
+ location: region
+ project: project-id
+ running_timeout: 43200s
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+
+counts:
+ google_workstations_workstation: 1
+ google_workstations_workstation_cluster: 1
+ google_workstations_workstation_config: 1
+ modules: 1
+ resources: 3
\ No newline at end of file
diff --git a/tests/modules/workstation_cluster/examples/iam.yaml b/tests/modules/workstation_cluster/examples/iam.yaml
new file mode 100644
index 0000000000..be6c00efe9
--- /dev/null
+++ b/tests/modules/workstation_cluster/examples/iam.yaml
@@ -0,0 +1,103 @@
+# Copyright 2023 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+values:
+ module.workstation-cluster.google_workstations_workstation.workstations["my-workstation-config-my-workstation"]:
+ annotations: null
+ display_name: null
+ effective_labels:
+ team: my-team
+ env: null
+ labels:
+ team: my-team
+ location: region
+ project: project-id
+ terraform_labels:
+ team: my-team
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+ workstation_id: my-workstation
+ module.workstation-cluster.google_workstations_workstation_cluster.cluster:
+ annotations: null
+ display_name: null
+ domain_config: []
+ labels: null
+ location: region
+ network: projects/xxx/global/networks/aaa
+ private_cluster_config:
+ - enable_private_endpoint: false
+ project: project-id
+ subnetwork: subnet_self_link
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ module.workstation-cluster.google_workstations_workstation_config.configs["my-workstation-config"]:
+ annotations: null
+ display_name: null
+ enable_audit_agent: null
+ encryption_key: []
+ idle_timeout: 1200s
+ labels: null
+ location: region
+ project: project-id
+ running_timeout: 43200s
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+ ? module.workstation-cluster.google_workstations_workstation_config_iam_binding.authoritative["my-workstation-config-roles/viewer"]
+ : condition: []
+ location: region
+ members:
+ - group:group1@my-org.com
+ project: project-id
+ role: roles/viewer
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+ ? module.workstation-cluster.google_workstations_workstation_config_iam_binding.bindings["my-workstation-config-workstations-config-viewer"]
+ : condition: []
+ location: region
+ members:
+ - group:group2@my-org.com
+ project: project-id
+ role: roles/viewer
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+ ? module.workstation-cluster.google_workstations_workstation_config_iam_member.bindings["my-workstation-config-workstations-config-editor"]
+ : condition: []
+ location: region
+ member: group:group3@my-org.com
+ project: project-id
+ role: roles/editor
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+ ? module.workstation-cluster.google_workstations_workstation_iam_binding.authoritative["my-workstation-config-my-workstation-roles/workstations.user"]
+ : condition: []
+ location: region
+ members:
+ - user:user1@my-org.com
+ project: project-id
+ role: roles/workstations.user
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+ workstation_id: my-workstation
+
+counts:
+ google_workstations_workstation: 1
+ google_workstations_workstation_cluster: 1
+ google_workstations_workstation_config: 1
+ google_workstations_workstation_config_iam_binding: 2
+ google_workstations_workstation_config_iam_member: 1
+ google_workstations_workstation_iam_binding: 1
+ modules: 1
+ resources: 7
\ No newline at end of file
diff --git a/tests/modules/workstation_cluster/examples/private-cluster.yaml b/tests/modules/workstation_cluster/examples/private-cluster.yaml
new file mode 100644
index 0000000000..08b08d0229
--- /dev/null
+++ b/tests/modules/workstation_cluster/examples/private-cluster.yaml
@@ -0,0 +1,64 @@
+# Copyright 2023 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+values:
+ module.workstation-cluster.google_workstations_workstation.workstations["my-workstation-config-my-workstation"]:
+ annotations: null
+ display_name: null
+ effective_labels:
+ team: my-team
+ env: null
+ labels:
+ team: my-team
+ location: region
+ project: project-id
+ terraform_labels:
+ team: my-team
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+ workstation_id: my-workstation
+ module.workstation-cluster.google_workstations_workstation_cluster.cluster:
+ annotations: null
+ display_name: null
+ domain_config: []
+ labels: null
+ location: region
+ network: projects/xxx/global/networks/aaa
+ private_cluster_config:
+ - enable_private_endpoint: true
+ project: project-id
+ subnetwork: subnet_self_link
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ module.workstation-cluster.google_workstations_workstation_config.configs["my-workstation-config"]:
+ annotations: null
+ display_name: null
+ enable_audit_agent: null
+ encryption_key: []
+ idle_timeout: 1200s
+ labels: null
+ location: region
+ project: project-id
+ running_timeout: 43200s
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+
+counts:
+ google_workstations_workstation: 1
+ google_workstations_workstation_cluster: 1
+ google_workstations_workstation_config: 1
+ modules: 1
+ resources: 3
\ No newline at end of file
diff --git a/tests/modules/workstation_cluster/examples/simple.yaml b/tests/modules/workstation_cluster/examples/simple.yaml
new file mode 100644
index 0000000000..8f5307380f
--- /dev/null
+++ b/tests/modules/workstation_cluster/examples/simple.yaml
@@ -0,0 +1,64 @@
+# Copyright 2023 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+values:
+ module.workstation-cluster.google_workstations_workstation.workstations["my-workstation-config-my-workstation"]:
+ annotations: null
+ display_name: null
+ effective_labels:
+ team: my-team
+ env: null
+ labels:
+ team: my-team
+ location: region
+ project: project-id
+ terraform_labels:
+ team: my-team
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+ workstation_id: my-workstation
+ module.workstation-cluster.google_workstations_workstation_cluster.cluster:
+ annotations: null
+ display_name: null
+ domain_config: []
+ labels: null
+ location: region
+ network: projects/xxx/global/networks/aaa
+ private_cluster_config:
+ - enable_private_endpoint: false
+ project: project-id
+ subnetwork: subnet_self_link
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ module.workstation-cluster.google_workstations_workstation_config.configs["my-workstation-config"]:
+ annotations: null
+ display_name: null
+ enable_audit_agent: null
+ encryption_key: []
+ idle_timeout: 1200s
+ labels: null
+ location: region
+ project: project-id
+ running_timeout: 43200s
+ timeouts: null
+ workstation_cluster_id: my-workstation-cluster
+ workstation_config_id: my-workstation-config
+
+counts:
+ google_workstations_workstation: 1
+ google_workstations_workstation_cluster: 1
+ google_workstations_workstation_config: 1
+ modules: 1
+ resources: 3
\ No newline at end of file