Skip to content

Commit

Permalink
feat: create service account as part of instance template module (#475)
Browse files Browse the repository at this point in the history
  • Loading branch information
q2w authored Jan 28, 2025
1 parent 11a9137 commit bd21f7b
Show file tree
Hide file tree
Showing 21 changed files with 351 additions and 4 deletions.
19 changes: 19 additions & 0 deletions build/int.cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,25 @@ steps:
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestMigStatefulModule --stage destroy --verbose']
timeout: 1800s
- id: it-simple-sa-apply
waitFor:
- destroy-it-simple-local
- destroy-it-additional-disks-local
- destroy-preemptible-and-regular-instance-templates-simple-local
- go-destroy-instance-simple
- destroy-mig-simple-local
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestInstanceTemplateSimpleSAModule --stage apply --verbose']
- id: it-simple-sa-verify
waitFor:
- it-simple-sa-apply
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestInstanceTemplateSimpleSAModule --stage verify --verbose']
- id: it-simple-sa-destroy
waitFor:
- it-simple-sa-verify
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestInstanceTemplateSimpleSAModule --stage destroy --verbose']
tags:
- 'ci'
- 'integration'
Expand Down
20 changes: 20 additions & 0 deletions examples/it_simple_with_sa_creation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# instance-template-simple

This is a simple, minimal example of how to use the instance_template module.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| project\_id | The GCP project to use for integration tests | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| name | Name of the instance templates |
| project\_id | The GCP project to use for integration tests |
| self\_link | Self-link to the instance template |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
71 changes: 71 additions & 0 deletions examples/it_simple_with_sa_creation/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Copyright 2025 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 = "us-central1"
}

resource "google_compute_address" "ip_address" {
name = "external-ip"
}

locals {
access_config = {
nat_ip = google_compute_address.ip_address.address
network_tier = "PREMIUM"
}
}

resource "random_string" "suffix" {
length = 4
special = "false"
upper = "false"
}

resource "google_compute_network" "main" {
project = var.project_id
name = "cft-vm-test-${random_string.suffix.result}"
auto_create_subnetworks = "false"
}

resource "google_compute_subnetwork" "main" {
project = var.project_id
region = "us-central1"
name = "cft-vm-test-${random_string.suffix.result}"
ip_cidr_range = "10.128.0.0/20"
network = google_compute_network.main.self_link
}

module "instance_template" {
source = "terraform-google-modules/vm/google//modules/instance_template"
version = "~> 13.0"

project_id = var.project_id
region = "us-central1"
subnetwork = google_compute_subnetwork.main.self_link
stack_type = "IPV4_ONLY"
name_prefix = "it-simple-sa"
tags = ["foo", "bar", "sa"]
labels = {
environment = "dev"
}
access_config = [local.access_config]
enable_nested_virtualization = false
threads_per_core = null
service_account_project_roles = ["roles/compute.admin"]
}
30 changes: 30 additions & 0 deletions examples/it_simple_with_sa_creation/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright 2025 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
}

output "project_id" {
description = "The GCP project to use for integration tests"
value = var.project_id
}
22 changes: 22 additions & 0 deletions examples/it_simple_with_sa_creation/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Copyright 2025 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
}
4 changes: 4 additions & 0 deletions metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ spec:
location: examples/umig/full
- name: healthcheck
location: examples/mig/healthcheck
- name: it_simple_with_sa_creation
location: examples/it_simple_with_sa_creation
- name: mig_stateful
location: examples/mig_stateful
- name: multiple_interfaces
Expand Down Expand Up @@ -96,7 +98,9 @@ spec:
- roles/compute.admin
- roles/compute.networkAdmin
- roles/iam.serviceAccountUser
- roles/iam.serviceAccountAdmin
- roles/compute.instanceAdmin
- roles/resourcemanager.projectIamAdmin
services:
- cloudresourcemanager.googleapis.com
- storage-api.googleapis.com
Expand Down
4 changes: 4 additions & 0 deletions modules/compute_disk_snapshot/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ spec:
location: examples/umig/full
- name: healthcheck
location: examples/mig/healthcheck
- name: it_simple_with_sa_creation
location: examples/it_simple_with_sa_creation
- name: mig_stateful
location: examples/mig_stateful
- name: multiple_interfaces
Expand Down Expand Up @@ -162,7 +164,9 @@ spec:
- roles/compute.admin
- roles/compute.networkAdmin
- roles/iam.serviceAccountUser
- roles/iam.serviceAccountAdmin
- roles/compute.instanceAdmin
- roles/resourcemanager.projectIamAdmin
services:
- cloudresourcemanager.googleapis.com
- storage-api.googleapis.com
Expand Down
4 changes: 4 additions & 0 deletions modules/compute_instance/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ spec:
location: examples/umig/full
- name: healthcheck
location: examples/mig/healthcheck
- name: it_simple_with_sa_creation
location: examples/it_simple_with_sa_creation
- name: mig_stateful
location: examples/mig_stateful
- name: multiple_interfaces
Expand Down Expand Up @@ -173,7 +175,9 @@ spec:
- roles/compute.admin
- roles/compute.networkAdmin
- roles/iam.serviceAccountUser
- roles/iam.serviceAccountAdmin
- roles/compute.instanceAdmin
- roles/resourcemanager.projectIamAdmin
services:
- cloudresourcemanager.googleapis.com
- storage-api.googleapis.com
Expand Down
5 changes: 4 additions & 1 deletion modules/instance_template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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\_service\_account | Create a new service account to attach to the instance. This is alternate to providing the service\_account input variable. Please provide the service\_account input if setting this to false. | `bool` | `true` | 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 |
Expand All @@ -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. | <pre>object({<br> email = string<br> scopes = optional(set(string), ["cloud-platform"])<br> })</pre> | 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. | <pre>object({<br> email = string<br> scopes = optional(set(string), ["cloud-platform"])<br> })</pre> | `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. | <pre>object({<br> enable_secure_boot = bool<br> enable_vtpm = bool<br> enable_integrity_monitoring = bool<br> })</pre> | <pre>{<br> "enable_integrity_monitoring": true,<br> "enable_secure_boot": true,<br> "enable_vtpm": true<br>}</pre> | 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 |
Expand All @@ -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) |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
39 changes: 38 additions & 1 deletion modules/instance_template/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,43 @@ 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_service_account
? { email : google_service_account.sa[0].email, scopes : ["cloud-platform"] }
: null
)
)
create_service_account = var.create_service_account ? 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" {
provider = google-beta
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" {
provider = google-beta
for_each = toset(distinct(var.service_account_project_roles))

project = var.project_id
role = each.value
member = "serviceAccount:${local.service_account.email}"
}

####################
Expand Down Expand Up @@ -111,7 +148,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 ? [] : [local.service_account]
content {
email = lookup(service_account.value, "email", null)
scopes = lookup(service_account.value, "scopes", null)
Expand Down
8 changes: 8 additions & 0 deletions modules/instance_template/metadata.display.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ spec:
confidential_instance_type:
name: confidential_instance_type
title: Confidential Instance Type
create_service_account:
name: create_service_account
title: Create Service Account
level: 1
description:
name: description
title: Description
Expand Down Expand Up @@ -158,6 +162,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
Expand All @@ -171,6 +178,7 @@ spec:
source_image_project:
name: source_image_project
title: Source Image Project
level: 1
spot:
name: spot
title: Spot
Expand Down
Loading

0 comments on commit bd21f7b

Please sign in to comment.