diff --git a/examples/instance_template/simple_with_sa_creation/README.md b/examples/instance_template/simple_with_sa_creation/README.md new file mode 100644 index 00000000..70365182 --- /dev/null +++ b/examples/instance_template/simple_with_sa_creation/README.md @@ -0,0 +1,25 @@ +# instance-template-simple + +This is a simple, minimal example of how to use the instance_template module. + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| enable\_nested\_virtualization | Defines whether the instance should have nested virtualization enabled. | `bool` | `false` | no | +| labels | Labels, provided as a map | `map(string)` | n/a | yes | +| project\_id | The GCP project to use for integration tests | `string` | n/a | yes | +| region | The GCP region to create and test resources in | `string` | `"us-central1"` | no | +| subnetwork | The name of the subnetwork create this instance in. | `string` | `""` | no | +| tags | Network tags, provided as a list | `list(string)` | n/a | yes | +| threads\_per\_core | The number of threads per physical core. To disable simultaneous multithreading (SMT) set this to 1. | `string` | `null` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| name | Name of the instance templates | +| self\_link | Self-link to the instance template | + + diff --git a/examples/instance_template/simple_with_sa_creation/main.tf b/examples/instance_template/simple_with_sa_creation/main.tf new file mode 100644 index 00000000..91e0d258 --- /dev/null +++ b/examples/instance_template/simple_with_sa_creation/main.tf @@ -0,0 +1,47 @@ +/** + * Copyright 2019 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. + */ + +provider "google" { + + project = var.project_id + region = var.region +} + +resource "google_compute_address" "ip_address" { + name = "external-ip" +} + +locals { + access_config = { + nat_ip = google_compute_address.ip_address.address + network_tier = "PREMIUM" + } +} + +module "instance_template" { + source = "../../../modules/instance_template" + + project_id = var.project_id + region = var.region + subnetwork = var.subnetwork + stack_type = "IPV4_ONLY" + name_prefix = "simple" + tags = var.tags + labels = var.labels + access_config = [local.access_config] + enable_nested_virtualization = var.enable_nested_virtualization + threads_per_core = var.threads_per_core +} diff --git a/examples/instance_template/simple_with_sa_creation/outputs.tf b/examples/instance_template/simple_with_sa_creation/outputs.tf new file mode 100644 index 00000000..c221e11d --- /dev/null +++ b/examples/instance_template/simple_with_sa_creation/outputs.tf @@ -0,0 +1,26 @@ +/** + * Copyright 2018 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. + */ + +output "self_link" { + description = "Self-link to the instance template" + value = module.instance_template.self_link +} + +output "name" { + description = "Name of the instance templates" + value = module.instance_template.name +} + diff --git a/examples/instance_template/simple_with_sa_creation/variables.tf b/examples/instance_template/simple_with_sa_creation/variables.tf new file mode 100644 index 00000000..001ee606 --- /dev/null +++ b/examples/instance_template/simple_with_sa_creation/variables.tf @@ -0,0 +1,55 @@ +/** + * Copyright 2019 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 "project_id" { + description = "The GCP project to use for integration tests" + type = string +} + +variable "region" { + description = "The GCP region to create and test resources in" + type = string + default = "us-central1" +} + +variable "subnetwork" { + description = "The name of the subnetwork create this instance in." + default = "" +} + +variable "tags" { + type = list(string) + description = "Network tags, provided as a list" +} + +variable "labels" { + type = map(string) + description = "Labels, provided as a map" +} + +variable "enable_nested_virtualization" { + type = bool + description = "Defines whether the instance should have nested virtualization enabled." + default = false +} + +variable "threads_per_core" { + type = string + description = "The number of threads per physical core. To disable simultaneous multithreading (SMT) set this to 1." + default = null +} diff --git a/modules/instance_template/README.md b/modules/instance_template/README.md index d502b066..6e867740 100644 --- a/modules/instance_template/README.md +++ b/modules/instance_template/README.md @@ -21,6 +21,7 @@ See the [simple](../../examples/instance_template/simple) for a usage example. | automatic\_restart | (Optional) Specifies whether the instance should be automatically restarted if it is terminated by Compute Engine (not terminated by a user). | `bool` | `true` | no | | can\_ip\_forward | Enable IP forwarding, for NAT instances for example | `string` | `"false"` | no | | confidential\_instance\_type | Defines the confidential computing technology the instance uses. If this is set to "SEV\_SNP", var.min\_cpu\_platform will be automatically set to "AMD Milan". See https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#confidential_instance_type. | `string` | `null` | no | +| create\_new\_service\_account | Create a new service account to attach to the instance. This is alternate to providing the service\_account input variable. |
object({
enabled = bool
scopes = set(string)
})
|
{
"enabled": true,
"scopes": [
"cloud-platform"
]
}
| no | | description | The template's description | `string` | `""` | no | | disk\_encryption\_key | The id of the encryption key that is stored in Google Cloud KMS to use to encrypt all the disks on this instance | `string` | `null` | no | | disk\_labels | Labels to be assigned to boot disk, provided as a map | `map(string)` | `{}` | no | @@ -47,7 +48,8 @@ See the [simple](../../examples/instance_template/simple) for a usage example. | project\_id | The GCP project ID | `string` | n/a | yes | | region | Region where the instance template should be created. | `string` | n/a | yes | | resource\_policies | A list of self\_links of resource policies to attach to the instance. Modifying this list will cause the instance to recreate. Currently a max of 1 resource policy is supported. | `list(string)` | `[]` | no | -| service\_account | Service account to attach to the instance. See https://www.terraform.io/docs/providers/google/r/compute_instance_template#service_account. |
object({
email = string
scopes = optional(set(string), ["cloud-platform"])
})
| n/a | yes | +| service\_account | Service account to attach to the instance. See https://www.terraform.io/docs/providers/google/r/compute_instance_template#service_account. |
object({
email = string
scopes = optional(set(string), ["cloud-platform"])
})
| `null` | no | +| service\_account\_project\_roles | Roles to grant to the newly created cloud run SA in specified project. Should be used with create\_service\_account set to true and no input for service\_account | `list(string)` | `[]` | no | | shielded\_instance\_config | Not used unless enable\_shielded\_vm is true. Shielded VM configuration for the instance. |
object({
enable_secure_boot = bool
enable_vtpm = bool
enable_integrity_monitoring = bool
})
|
{
"enable_integrity_monitoring": true,
"enable_secure_boot": true,
"enable_vtpm": true
}
| no | | source\_image | Source disk image. If neither source\_image nor source\_image\_family is specified, defaults to the latest public Rocky Linux 9 optimized for GCP image. | `string` | `""` | no | | source\_image\_family | Source image family. If neither source\_image nor source\_image\_family is specified, defaults to the latest public Rocky Linux 9 optimized for GCP image. | `string` | `"rocky-linux-9-optimized-gcp"` | no | @@ -69,6 +71,7 @@ See the [simple](../../examples/instance_template/simple) for a usage example. | name | Name of instance template | | self\_link | Self-link of instance template | | self\_link\_unique | Unique self-link of instance template (recommended output to use instead of self\_link) | +| service\_account\_info | Service account id and email | | tags | Tags that will be associated with instance(s) | diff --git a/modules/instance_template/main.tf b/modules/instance_template/main.tf index 5c5917bb..a3d4a5cc 100644 --- a/modules/instance_template/main.tf +++ b/modules/instance_template/main.tf @@ -63,6 +63,40 @@ locals { # must be true when preemtible or spot is true var.preemptible || var.spot ? true : false ) + + service_account = ( + var.service_account != null + ? var.service_account + : ( + var.create_new_service_account.enabled + ? { email : google_service_account.sa[0].email, scopes : var.create_new_service_account.scopes } + : null + ) + ) + create_service_account = var.create_service_account.enabled ? var.service_account == null : false + + service_account_prefix = substr("${var.name_prefix}-${var.region}", 0, 27) + service_account_output = local.create_service_account ? { + id = google_service_account.sa[0].account_id, + email = google_service_account.sa[0].email, + member = google_service_account.sa[0].member + } : {} +} + +# Service account +resource "google_service_account" "sa" { + count = local.create_service_account ? 1 : 0 + project = var.project_id + account_id = "${local.service_account_prefix}-sa" + display_name = "Service account for ${var.name_prefix} in ${var.region}" +} + +resource "google_project_iam_member" "roles" { + for_each = toset(distinct(var.service_account_project_roles)) + + project = var.project_id + role = each.value + member = "serviceAccount:${local.service_account.email}" } #################### @@ -111,7 +145,7 @@ resource "google_compute_instance_template" "tpl" { } dynamic "service_account" { - for_each = var.service_account == null ? [] : [var.service_account] + for_each = local.service_account == null ? [] : [var.service_account] content { email = lookup(service_account.value, "email", null) scopes = lookup(service_account.value, "scopes", null) diff --git a/modules/instance_template/metadata.display.yaml b/modules/instance_template/metadata.display.yaml index 90917235..88cb0abd 100644 --- a/modules/instance_template/metadata.display.yaml +++ b/modules/instance_template/metadata.display.yaml @@ -58,6 +58,9 @@ spec: confidential_instance_type: name: confidential_instance_type title: Confidential Instance Type + create_new_service_account: + name: create_new_service_account + title: Create New Service Account description: name: description title: Description @@ -158,6 +161,9 @@ spec: service_account: name: service_account title: Service Account + service_account_project_roles: + name: service_account_project_roles + title: Service Account Project Roles shielded_instance_config: name: shielded_instance_config title: Shielded Instance Config diff --git a/modules/instance_template/metadata.yaml b/modules/instance_template/metadata.yaml index 0cb961b6..10a92a42 100644 --- a/modules/instance_template/metadata.yaml +++ b/modules/instance_template/metadata.yaml @@ -74,6 +74,8 @@ spec: location: examples/preemptible_and_regular_instance_templates/simple - name: simple location: examples/umig/simple + - name: simple_with_sa_creation + location: examples/instance_template/simple_with_sa_creation - name: static_ips location: examples/umig/static_ips - name: tags @@ -292,7 +294,6 @@ spec: email = string scopes = optional(set(string), ["cloud-platform"]) }) - required: true connections: - source: source: github.com/terraform-google-modules/terraform-google-service-accounts//modules/simple-sa @@ -300,6 +301,21 @@ spec: spec: outputExpr: email inputPath: email + - name: create_new_service_account + description: Create a new service account to attach to the instance. This is alternate to providing the service_account input variable. + varType: |- + object({ + enabled = bool + scopes = set(string) + }) + defaultValue: + enabled: true + scopes: + - cloud-platform + - name: service_account_project_roles + description: Roles to grant to the newly created cloud run SA in specified project. Should be used with create_service_account set to true and no input for service_account + varType: list(string) + defaultValue: [] - name: enable_shielded_vm description: Whether to enable the Shielded VM configuration on the instance. Note that the instance image must support Shielded VMs. See https://cloud.google.com/compute/docs/images varType: bool @@ -365,6 +381,8 @@ spec: - name: self_link_unique description: Unique self-link of instance template (recommended output to use instead of self_link) type: string + - name: service_account_info + description: Service account id and email - name: tags description: Tags that will be associated with instance(s) type: diff --git a/modules/instance_template/outputs.tf b/modules/instance_template/outputs.tf index aea1b3d7..0171fb9c 100644 --- a/modules/instance_template/outputs.tf +++ b/modules/instance_template/outputs.tf @@ -33,3 +33,8 @@ output "tags" { description = "Tags that will be associated with instance(s)" value = google_compute_instance_template.tpl.tags } + +output "service_account_info" { + description = "Service account id and email" + value = local.service_account_output +} diff --git a/modules/instance_template/variables.tf b/modules/instance_template/variables.tf index 1819c27b..26394ec6 100644 --- a/modules/instance_template/variables.tf +++ b/modules/instance_template/variables.tf @@ -328,6 +328,25 @@ variable "service_account" { scopes = optional(set(string), ["cloud-platform"]) }) description = "Service account to attach to the instance. See https://www.terraform.io/docs/providers/google/r/compute_instance_template#service_account." + default = null +} + +variable "create_new_service_account" { + type = object({ + enabled = bool + scopes = set(string) + }) + description = "Create a new service account to attach to the instance. This is alternate to providing the service_account input variable." + default = { + enabled = true + scopes = ["cloud-platform"] + } +} + +variable "service_account_project_roles" { + type = list(string) + description = "Roles to grant to the newly created cloud run SA in specified project. Should be used with create_service_account set to true and no input for service_account" + default = [] } ###########################