Extend support for tag bindings to more modules (#2307)

* fix kms tag bindings

* bigquery dataset

* fix bigquery

* cloud run

* normalize variable type

* rename gcs heading

* kms example test

* fix bigquery

* fix cloud run

* cloud run v2
This commit is contained in:
Ludovico Magnocavallo 2024-05-25 10:42:45 +02:00 committed by GitHub
parent 735fd79cce
commit c80af8de66
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 335 additions and 84 deletions

View File

@ -2,14 +2,19 @@
This module allows managing a single BigQuery dataset, including access configuration, tables and views.
## TODO
<!-- BEGIN TOC -->
- [Simple dataset with access configuration](#simple-dataset-with-access-configuration)
- [IAM roles](#iam-roles)
- [Authorized Views, Datasets, and Routines](#authorized-views-datasets-and-routines)
- [Dataset options](#dataset-options)
- [Tables and views](#tables-and-views)
- [Tag bindings](#tag-bindings)
- [TODO](#todo)
- [Variables](#variables)
- [Outputs](#outputs)
<!-- END TOC -->
- [ ] check for dynamic values in tables and views
- [ ] add support for external tables
## Examples
### Simple dataset with access configuration
## Simple dataset with access configuration
Access configuration defaults to using the separate `google_bigquery_dataset_access` resource, so as to leave the default dataset access rules untouched.
@ -38,7 +43,7 @@ module "bigquery-dataset" {
# tftest modules=1 resources=5 inventory=simple.yaml
```
### IAM roles
## IAM roles
Access configuration can also be specified via IAM instead of basic roles via the `iam` variable. When using IAM, basic roles cannot be used via the `access` family variables.
@ -54,7 +59,7 @@ module "bigquery-dataset" {
# tftest modules=1 resources=2 inventory=iam.yaml
```
### Authorized Views, Datasets, and Routines
## Authorized Views, Datasets, and Routines
You can specify authorized [views](https://cloud.google.com/bigquery/docs/authorized-views), [datasets](https://cloud.google.com/bigquery/docs/authorized-datasets?hl=en), and [routines](https://cloud.google.com/bigquery/docs/authorized-routines) via the `authorized_views`, `authorized_datasets` and `authorized_routines` variables, respectively.
@ -168,7 +173,7 @@ module "bigquery-dataset" {
# tftest modules=1 resources=4 inventory=authorized_resources_views.yaml
```
### Dataset options
## Dataset options
Dataset options are set via the `options` variable. all options must be specified, but a `null` value can be set to options that need to use defaults.
@ -187,7 +192,7 @@ module "bigquery-dataset" {
# tftest modules=1 resources=1 inventory=options.yaml
```
### Tables and views
## Tables and views
Tables are created via the `tables` variable, or the `view` variable for views. Support for external tables will be added in a future release.
@ -275,6 +280,42 @@ module "bigquery-dataset" {
# tftest modules=1 resources=3 inventory=views.yaml
```
## Tag bindings
Refer to the [Creating and managing tags](https://cloud.google.com/resource-manager/docs/tags/tags-creating-and-managing) documentation for details on usage.
```hcl
module "org" {
source = "./fabric/modules/organization"
organization_id = var.organization_id
tags = {
environment = {
description = "Environment specification."
values = {
dev = {}
prod = {}
sandbox = {}
}
}
}
}
module "bigquery-dataset" {
source = "./fabric/modules/bigquery-dataset"
project_id = "my-project"
id = "my_dataset"
tag_bindings = {
env-sandbox = module.org.tag_values["environment/sandbox"].id
}
}
# tftest modules=2 resources=6
```
## TODO
- [ ] check for dynamic values in tables and views
- [ ] add support for external tables
<!-- BEGIN TFDOC -->
## Variables
@ -297,7 +338,8 @@ module "bigquery-dataset" {
| [materialized_views](variables.tf#L115) | Materialized views definitions. | <code title="map&#40;object&#40;&#123;&#10; query &#61; string&#10; allow_non_incremental_definition &#61; optional&#40;bool&#41;&#10; deletion_protection &#61; optional&#40;bool&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; enable_refresh &#61; optional&#40;bool&#41;&#10; friendly_name &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; refresh_interval_ms &#61; optional&#40;bool&#41;&#10; require_partition_filter &#61; optional&#40;bool&#41;&#10; options &#61; optional&#40;object&#40;&#123;&#10; clustering &#61; optional&#40;list&#40;string&#41;&#41;&#10; expiration_time &#61; optional&#40;number&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; partitioning &#61; optional&#40;object&#40;&#123;&#10; field &#61; optional&#40;string&#41;&#10; range &#61; optional&#40;object&#40;&#123;&#10; end &#61; number&#10; interval &#61; number&#10; start &#61; number&#10; &#125;&#41;&#41;&#10; time &#61; optional&#40;object&#40;&#123;&#10; type &#61; string&#10; expiration_ms &#61; optional&#40;number&#41;&#10; field &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [options](variables.tf#L148) | Dataset options. | <code title="object&#40;&#123;&#10; default_collation &#61; optional&#40;string&#41;&#10; default_table_expiration_ms &#61; optional&#40;number&#41;&#10; default_partition_expiration_ms &#61; optional&#40;number&#41;&#10; delete_contents_on_destroy &#61; optional&#40;bool, false&#41;&#10; is_case_insensitive &#61; optional&#40;bool&#41;&#10; max_time_travel_hours &#61; optional&#40;number, 168&#41;&#10; storage_billing_model &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [tables](variables.tf#L167) | Table definitions. Options and partitioning default to null. Partitioning can only use `range` or `time`, set the unused one to null. | <code title="map&#40;object&#40;&#123;&#10; deletion_protection &#61; optional&#40;bool&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; friendly_name &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; require_partition_filter &#61; optional&#40;bool&#41;&#10; schema &#61; optional&#40;string&#41;&#10; external_data_configuration &#61; optional&#40;object&#40;&#123;&#10; autodetect &#61; bool&#10; source_uris &#61; list&#40;string&#41;&#10; avro_logical_types &#61; optional&#40;bool&#41;&#10; compression &#61; optional&#40;string&#41;&#10; connection_id &#61; optional&#40;string&#41;&#10; file_set_spec_type &#61; optional&#40;string&#41;&#10; ignore_unknown_values &#61; optional&#40;bool&#41;&#10; metadata_cache_mode &#61; optional&#40;string&#41;&#10; object_metadata &#61; optional&#40;string&#41;&#10; json_options_encoding &#61; optional&#40;string&#41;&#10; reference_file_schema_uri &#61; optional&#40;string&#41;&#10; schema &#61; optional&#40;string&#41;&#10; source_format &#61; optional&#40;string&#41;&#10; max_bad_records &#61; optional&#40;number&#41;&#10; csv_options &#61; optional&#40;object&#40;&#123;&#10; quote &#61; string&#10; allow_jagged_rows &#61; optional&#40;bool&#41;&#10; allow_quoted_newlines &#61; optional&#40;bool&#41;&#10; encoding &#61; optional&#40;string&#41;&#10; field_delimiter &#61; optional&#40;string&#41;&#10; skip_leading_rows &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; google_sheets_options &#61; optional&#40;object&#40;&#123;&#10; range &#61; optional&#40;string&#41;&#10; skip_leading_rows &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; hive_partitioning_options &#61; optional&#40;object&#40;&#123;&#10; mode &#61; optional&#40;string&#41;&#10; require_partition_filter &#61; optional&#40;bool&#41;&#10; source_uri_prefix &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; parquet_options &#61; optional&#40;object&#40;&#123;&#10; enum_as_string &#61; optional&#40;bool&#41;&#10; enable_list_inference &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10;&#10;&#10; &#125;&#41;&#41;&#10; options &#61; optional&#40;object&#40;&#123;&#10; clustering &#61; optional&#40;list&#40;string&#41;&#41;&#10; encryption_key &#61; optional&#40;string&#41;&#10; expiration_time &#61; optional&#40;number&#41;&#10; max_staleness &#61; optional&#40;string&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; partitioning &#61; optional&#40;object&#40;&#123;&#10; field &#61; optional&#40;string&#41;&#10; range &#61; optional&#40;object&#40;&#123;&#10; end &#61; number&#10; interval &#61; number&#10; start &#61; number&#10; &#125;&#41;&#41;&#10; time &#61; optional&#40;object&#40;&#123;&#10; type &#61; string&#10; expiration_ms &#61; optional&#40;number&#41;&#10; field &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; table_constraints &#61; optional&#40;object&#40;&#123;&#10; primary_key_columns &#61; optional&#40;list&#40;string&#41;&#41;&#10; foreign_keys &#61; optional&#40;object&#40;&#123;&#10; referenced_table &#61; object&#40;&#123;&#10; project_id &#61; string&#10; dataset_id &#61; string&#10; table_id &#61; string&#10; &#125;&#41;&#10; column_references &#61; object&#40;&#123;&#10; referencing_column &#61; string&#10; referenced_column &#61; string&#10; &#125;&#41;&#10; name &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [views](variables.tf#L252) | View definitions. | <code title="map&#40;object&#40;&#123;&#10; query &#61; string&#10; deletion_protection &#61; optional&#40;bool&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; friendly_name &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; use_legacy_sql &#61; optional&#40;bool&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [tag_bindings](variables.tf#L252) | Tag bindings for this dataset, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [views](variables.tf#L259) | View definitions. | <code title="map&#40;object&#40;&#123;&#10; query &#61; string&#10; deletion_protection &#61; optional&#40;bool&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; friendly_name &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; use_legacy_sql &#61; optional&#40;bool&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
## Outputs

View File

@ -0,0 +1,22 @@
/**
* 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.
*/
resource "google_tags_location_tag_binding" "binding" {
for_each = var.tag_bindings
parent = "//bigquery.googleapis.com/${google_bigquery_dataset.default.id}"
tag_value = each.value
location = var.location
}

View File

@ -249,6 +249,13 @@ variable "tables" {
default = {}
}
variable "tag_bindings" {
description = "Tag bindings for this dataset, in key => tag value id format."
type = map(string)
nullable = false
default = {}
}
variable "views" {
description = "View definitions."
type = map(object({

View File

@ -3,26 +3,24 @@
Cloud Run Services and Jobs, with support for IAM roles and Eventarc trigger creation.
<!-- BEGIN TOC -->
- [Examples](#examples)
- [IAM and environment variables](#iam-and-environment-variables)
- [Mounting secrets as volumes](#mounting-secrets-as-volumes)
- [Beta features](#beta-features)
- [VPC Access Connector](#vpc-access-connector)
- [Using Customer-Managed Encryption Key](#using-customer-managed-encryption-key)
- [Eventarc triggers](#eventarc-triggers)
- [PubSub](#pubsub)
- [Audit logs](#audit-logs)
- [Using custom service accounts for triggers](#using-custom-service-accounts-for-triggers)
- [Cloud Run Service Account](#cloud-run-service-account)
- [Creating Cloud Run Jobs](#creating-cloud-run-jobs)
- [IAM and environment variables](#iam-and-environment-variables)
- [Mounting secrets as volumes](#mounting-secrets-as-volumes)
- [Beta features](#beta-features)
- [VPC Access Connector](#vpc-access-connector)
- [Using Customer-Managed Encryption Key](#using-customer-managed-encryption-key)
- [Eventarc triggers](#eventarc-triggers)
- [PubSub](#pubsub)
- [Audit logs](#audit-logs)
- [Using custom service accounts for triggers](#using-custom-service-accounts-for-triggers)
- [Cloud Run Service Account](#cloud-run-service-account)
- [Creating Cloud Run Jobs](#creating-cloud-run-jobs)
- [Tag bindings](#tag-bindings)
- [Variables](#variables)
- [Outputs](#outputs)
- [Fixtures](#fixtures)
<!-- END TOC -->
## Examples
### IAM and environment variables
## IAM and environment variables
IAM bindings support the usual syntax. Container environment values can be declared as key-value strings or as references to Secret Manager secrets. Both can be combined as long as there is no duplication of keys:
@ -54,7 +52,7 @@ module "cloud_run" {
# tftest modules=2 resources=5 fixtures=fixtures/secret-credentials.tf inventory=service-iam-env.yaml e2e
```
### Mounting secrets as volumes
## Mounting secrets as volumes
```hcl
module "cloud_run" {
@ -83,7 +81,7 @@ module "cloud_run" {
# tftest modules=2 resources=4 fixtures=fixtures/secret-credentials.tf inventory=service-volume-secretes.yaml e2e
```
### Beta features
## Beta features
To use beta features like Direct VPC Egress, set the launch stage to a preview stage.
@ -112,7 +110,7 @@ module "cloud_run" {
# tftest modules=1 resources=1 inventory=service-beta-features.yaml
```
### VPC Access Connector
## VPC Access Connector
You can use an existing [VPC Access Connector](https://cloud.google.com/vpc/docs/serverless-vpc-access) to connect to a VPC from Cloud Run.
@ -186,7 +184,7 @@ module "cloud_run" {
# tftest modules=4 resources=40 fixtures=fixtures/shared-vpc.tf inventory=service-vpc-access-connector-create-sharedvpc.yaml e2e
```
### Using Customer-Managed Encryption Key
## Using Customer-Managed Encryption Key
Deploy a Cloud Run service with environment variables encrypted using a Customer-Managed Encryption Key (CMEK). Ensure you specify the encryption_key with the full resource identifier of your Cloud KMS CryptoKey and that Cloud Run Service agent (`service-<PROJECT_NUMBER>@serverless-robot-prod.iam.gserviceaccount.com`) has permission to use the key, for example `roles/cloudkms.cryptoKeyEncrypterDecrypter` IAM role. This setup adds an extra layer of security by utilizing your own encryption keys.
@ -206,9 +204,9 @@ module "cloud_run" {
# tftest modules=1 resources=2 fixtures=fixtures/cloud-run-kms-iam-grant.tf e2e
```
### Eventarc triggers
## Eventarc triggers
#### PubSub
### PubSub
This deploys a Cloud Run service that will be triggered when messages are published to Pub/Sub topics.
@ -232,7 +230,7 @@ module "cloud_run" {
# tftest modules=2 resources=4 fixtures=fixtures/pubsub.tf inventory=service-eventarc-pubsub.yaml e2e
```
#### Audit logs
### Audit logs
This deploys a Cloud Run service that will be triggered when specific log events are written to Google Cloud audit logs.
@ -260,7 +258,7 @@ module "cloud_run" {
# tftest modules=1 resources=4 inventory=service-eventarc-auditlogs-sa-create.yaml
```
#### Using custom service accounts for triggers
### Using custom service accounts for triggers
By default `Compute default service account` is used to trigger Cloud Run. If you want to use custom Service Accounts you can either provide your own in `eventarc_triggers.service_account_email` or set `eventarc_triggers.service_account_create` to true and service account named `tf-cr-trigger-${var.name}` will be created with `roles/run.invoker` granted on this Cloud Run service.
@ -313,7 +311,7 @@ module "cloud_run" {
# tftest modules=2 resources=6 fixtures=fixtures/pubsub.tf inventory=service-eventarc-pubsub-sa-create.yaml e2e
```
### Cloud Run Service Account
## Cloud Run Service Account
To use a custom service account managed by the module, set `service_account_create` to `true` and leave `service_account` set to `null` (default).
@ -351,17 +349,19 @@ module "cloud_run" {
# tftest modules=2 resources=2 fixtures=fixtures/iam-service-account.tf inventory=service-external-sa.yaml e2e
```
### Creating Cloud Run Jobs
## Creating Cloud Run Jobs
To create a job instead of service set `create_job` to `true`. Jobs support all functions above apart from triggers.
Unsupported variables / attributes:
* ingress
* revision.gen2_execution_environment (they run by default in gen2)
* revision.name
* containers.liveness_probe
* containers.startup_probe
* containers.resources.cpu_idle
* containers.resources.startup_cpu_boost
- ingress
- revision.gen2_execution_environment (they run by default in gen2)
- revision.name
- containers.liveness_probe
- containers.startup_probe
- containers.resources.cpu_idle
- containers.resources.startup_cpu_boost
```hcl
module "cloud_run" {
@ -386,6 +386,50 @@ module "cloud_run" {
# tftest modules=1 resources=2 inventory=job-iam-env.yaml e2e
```
## Tag bindings
Tag bindings are not yet supported for jobs. Refer to the [Creating and managing tags](https://cloud.google.com/resource-manager/docs/tags/tags-creating-and-managing) documentation for details on usage.
```hcl
module "org" {
source = "./fabric/modules/organization"
organization_id = var.organization_id
tags = {
environment = {
description = "Environment specification."
values = {
dev = {}
prod = {}
sandbox = {}
}
}
}
}
module "cloud_run" {
source = "./fabric/modules/cloud-run-v2"
project_id = var.project_id
name = "hello"
region = var.region
containers = {
hello = {
image = "us-docker.pkg.dev/cloudrun/container/hello"
env = {
VAR1 = "VALUE1"
VAR2 = "VALUE2"
}
}
}
iam = {
"roles/run.invoker" = ["allUsers"]
}
tag_bindings = {
env-sandbox = module.org.tag_values["environment/sandbox"].id
}
}
# tftest modules=2 resources=7
```
<!-- BEGIN TFDOC -->
## Variables
@ -406,7 +450,8 @@ module "cloud_run" {
| [revision](variables.tf#L178) | Revision template configurations. | <code title="object&#40;&#123;&#10; name &#61; optional&#40;string&#41;&#10; gen2_execution_environment &#61; optional&#40;bool&#41;&#10; max_concurrency &#61; optional&#40;number&#41;&#10; max_instance_count &#61; optional&#40;number&#41;&#10; min_instance_count &#61; optional&#40;number&#41;&#10; vpc_access &#61; optional&#40;object&#40;&#123;&#10; connector &#61; optional&#40;string&#41;&#10; egress &#61; optional&#40;string&#41;&#10; subnet &#61; optional&#40;string&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; timeout &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_account](variables.tf#L205) | Service account email. Unused if service account is auto-created. | <code>string</code> | | <code>null</code> |
| [service_account_create](variables.tf#L211) | Auto-create service account. | <code>bool</code> | | <code>false</code> |
| [volumes](variables.tf#L217) | Named volumes in containers in name => attributes format. | <code title="map&#40;object&#40;&#123;&#10; secret &#61; optional&#40;object&#40;&#123;&#10; name &#61; string&#10; default_mode &#61; optional&#40;string&#41;&#10; path &#61; optional&#40;string&#41;&#10; version &#61; optional&#40;string&#41;&#10; mode &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; cloud_sql_instances &#61; optional&#40;list&#40;string&#41;&#41;&#10; empty_dir_size &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [tag_bindings](variables.tf#L217) | Tag bindings for this service, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [volumes](variables.tf#L224) | Named volumes in containers in name => attributes format. | <code title="map&#40;object&#40;&#123;&#10; secret &#61; optional&#40;object&#40;&#123;&#10; name &#61; string&#10; default_mode &#61; optional&#40;string&#41;&#10; path &#61; optional&#40;string&#41;&#10; version &#61; optional&#40;string&#41;&#10; mode &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; cloud_sql_instances &#61; optional&#40;list&#40;string&#41;&#41;&#10; empty_dir_size &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [vpc_connector_create](variables-vpcconnector.tf#L17) | Populate this to create a Serverless VPC Access connector. | <code title="object&#40;&#123;&#10; ip_cidr_range &#61; optional&#40;string&#41;&#10; machine_type &#61; optional&#40;string&#41;&#10; name &#61; optional&#40;string&#41;&#10; network &#61; optional&#40;string&#41;&#10; instances &#61; optional&#40;object&#40;&#123;&#10; max &#61; optional&#40;number&#41;&#10; min &#61; optional&#40;number&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; throughput &#61; optional&#40;object&#40;&#123;&#10; max &#61; optional&#40;number, 1000&#41; &#35; workaround for a wrong default in provider&#10; min &#61; optional&#40;number&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; subnet &#61; optional&#40;object&#40;&#123;&#10; name &#61; optional&#40;string&#41;&#10; project_id &#61; optional&#40;string&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

View File

@ -0,0 +1,24 @@
/**
* 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.
*/
resource "google_tags_location_tag_binding" "binding" {
for_each = var.create_job ? {} : var.tag_bindings
parent = (
"//run.googleapis.com/projects/${var.project_id}/locations/europe-west1/services/${google_cloud_run_v2_service.service[0].name}"
)
tag_value = each.value
location = var.region
}

View File

@ -214,6 +214,13 @@ variable "service_account_create" {
default = false
}
variable "tag_bindings" {
description = "Tag bindings for this service, in key => tag value id format."
type = map(string)
nullable = false
default = {}
}
variable "volumes" {
description = "Named volumes in containers in name => attributes format."
type = map(object({

View File

@ -2,26 +2,24 @@
Cloud Run management, with support for IAM roles, revision annotations and optional Eventarc trigger creation.
## Examples
<!-- BEGIN TOC -->
- [Examples](#examples)
- [IAM and environment variables](#iam-and-environment-variables)
- [Mounting secrets as volumes](#mounting-secrets-as-volumes)
- [Revision annotations](#revision-annotations)
- [Second generation execution environment](#second-generation-execution-environment)
- [VPC Access Connector creation](#vpc-access-connector-creation)
- [Traffic split](#traffic-split)
- [Eventarc triggers](#eventarc-triggers)
- [PubSub](#pubsub)
- [Audit logs](#audit-logs)
- [Using custom service accounts for triggers](#using-custom-service-accounts-for-triggers)
- [Service account](#service-account)
- [IAM and environment variables](#iam-and-environment-variables)
- [Mounting secrets as volumes](#mounting-secrets-as-volumes)
- [Revision annotations](#revision-annotations)
- [Second generation execution environment](#second-generation-execution-environment)
- [VPC Access Connector creation](#vpc-access-connector-creation)
- [Traffic split](#traffic-split)
- [Eventarc triggers](#eventarc-triggers)
- [PubSub](#pubsub)
- [Audit logs](#audit-logs)
- [Using custom service accounts for triggers](#using-custom-service-accounts-for-triggers)
- [Service account](#service-account)
- [Tag bindings](#tag-bindings)
- [Variables](#variables)
- [Outputs](#outputs)
<!-- END TOC -->
### IAM and environment variables
## IAM and environment variables
IAM bindings support the usual syntax. Container environment values can be declared as key-value strings or as references to Secret Manager secrets. Both can be combined as long as there's no duplication of keys:
@ -68,7 +66,7 @@ module "cloud_run" {
# tftest modules=2 resources=5 inventory=simple.yaml e2e
```
### Mounting secrets as volumes
## Mounting secrets as volumes
```hcl
module "secret-manager" {
@ -117,7 +115,7 @@ module "cloud_run" {
# tftest modules=2 resources=5 inventory=secrets.yaml e2e
```
### Revision annotations
## Revision annotations
Annotations can be specified via the `revision_annotations` variable:
@ -145,7 +143,7 @@ module "cloud_run" {
# tftest modules=1 resources=1 inventory=revision-annotations.yaml
```
### Second generation execution environment
## Second generation execution environment
Second generation execution environment (gen2) can be enabled by setting the `gen2_execution_environment` variable to true:
@ -165,7 +163,7 @@ module "cloud_run" {
# tftest modules=1 resources=1 inventory=gen2.yaml e2e
```
### VPC Access Connector creation
## VPC Access Connector creation
If creation of a [VPC Access Connector](https://cloud.google.com/vpc/docs/serverless-vpc-access) is required, use the `vpc_connector_create` variable which also support optional attributes for number of instances, machine type, and throughput (not shown here). The annotation to use the connector will be added automatically.
@ -211,7 +209,7 @@ module "cloud_run" {
# tftest modules=1 resources=2 inventory=connector-shared.yaml
```
### Traffic split
## Traffic split
This deploys a Cloud Run service with traffic split between two revisions.
@ -235,9 +233,9 @@ module "cloud_run" {
# tftest modules=1 resources=1 inventory=traffic.yaml
```
### Eventarc triggers
## Eventarc triggers
#### PubSub
### PubSub
This deploys a Cloud Run service that will be triggered when messages are published to Pub/Sub topics.
@ -267,7 +265,7 @@ module "cloud_run" {
# tftest modules=2 resources=3 inventory=eventarc.yaml e2e
```
#### Audit logs
### Audit logs
This deploys a Cloud Run service that will be triggered when specific log events are written to Google Cloud audit logs.
@ -307,7 +305,7 @@ module "cloud_run" {
# tftest modules=2 resources=5 inventory=audit-logs.yaml
```
#### Using custom service accounts for triggers
### Using custom service accounts for triggers
By default `Compute default service account` is used to trigger Cloud Run. If you want to use custom Service Account you can either provide your own in `eventarc_triggers.service_account_email` or set `eventarc_triggers.service_account_create` to true and service account named `tf-cr-trigger-${var.name}` will be created with `roles/run.invoker` granted on this Cloud Run service.
@ -342,7 +340,7 @@ module "cloud_run" {
# tftest modules=2 resources=5 inventory=trigger-service-account.yaml e2e
```
### Service account
## Service account
To use a custom service account managed by the module, set `service_account_create` to `true` and leave `service_account` set to `null` value (default).
@ -379,6 +377,43 @@ module "cloud_run" {
}
# tftest modules=1 resources=1 inventory=service-account-external.yaml e2e
```
## Tag bindings
Refer to the [Creating and managing tags](https://cloud.google.com/resource-manager/docs/tags/tags-creating-and-managing) documentation for details on usage.
```hcl
module "org" {
source = "./fabric/modules/organization"
organization_id = var.organization_id
tags = {
environment = {
description = "Environment specification."
values = {
dev = {}
prod = {}
sandbox = {}
}
}
}
}
module "cloud_run" {
source = "./fabric/modules/cloud-run"
project_id = var.project_id
region = var.region
name = "hello"
containers = {
hello = {
image = "us-docker.pkg.dev/cloudrun/container/hello"
}
}
tag_bindings = {
env-sandbox = module.org.tag_values["environment/sandbox"].id
}
}
# tftest modules=2 resources=6
```
<!-- BEGIN TFDOC -->
## Variables
@ -400,10 +435,11 @@ module "cloud_run" {
| [service_account](variables.tf#L190) | Service account email. Unused if service account is auto-created. | <code>string</code> | | <code>null</code> |
| [service_account_create](variables.tf#L196) | Auto-create service account. | <code>bool</code> | | <code>false</code> |
| [startup_cpu_boost](variables.tf#L202) | Enable startup cpu boost. | <code>bool</code> | | <code>false</code> |
| [timeout_seconds](variables.tf#L208) | Maximum duration the instance is allowed for responding to a request. | <code>number</code> | | <code>null</code> |
| [traffic](variables.tf#L214) | Traffic steering configuration. If revision name is null the latest revision will be used. | <code title="map&#40;object&#40;&#123;&#10; percent &#61; number&#10; latest &#61; optional&#40;bool&#41;&#10; tag &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [volumes](variables.tf#L225) | Named volumes in containers in name => attributes format. | <code title="map&#40;object&#40;&#123;&#10; secret_name &#61; string&#10; default_mode &#61; optional&#40;string&#41;&#10; items &#61; optional&#40;map&#40;object&#40;&#123;&#10; path &#61; string&#10; mode &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [vpc_connector_create](variables.tf#L239) | Populate this to create a VPC connector. You can then refer to it in the template annotations. | <code title="object&#40;&#123;&#10; ip_cidr_range &#61; optional&#40;string&#41;&#10; vpc_self_link &#61; optional&#40;string&#41;&#10; machine_type &#61; optional&#40;string&#41;&#10; name &#61; optional&#40;string&#41;&#10; instances &#61; optional&#40;object&#40;&#123;&#10; max &#61; optional&#40;number&#41;&#10; min &#61; optional&#40;number&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; throughput &#61; optional&#40;object&#40;&#123;&#10; max &#61; optional&#40;number&#41;&#10; min &#61; optional&#40;number&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; subnet &#61; optional&#40;object&#40;&#123;&#10; name &#61; optional&#40;string&#41;&#10; project_id &#61; optional&#40;string&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L208) | Tag bindings for this service, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [timeout_seconds](variables.tf#L215) | Maximum duration the instance is allowed for responding to a request. | <code>number</code> | | <code>null</code> |
| [traffic](variables.tf#L221) | Traffic steering configuration. If revision name is null the latest revision will be used. | <code title="map&#40;object&#40;&#123;&#10; percent &#61; number&#10; latest &#61; optional&#40;bool&#41;&#10; tag &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [volumes](variables.tf#L232) | Named volumes in containers in name => attributes format. | <code title="map&#40;object&#40;&#123;&#10; secret_name &#61; string&#10; default_mode &#61; optional&#40;string&#41;&#10; items &#61; optional&#40;map&#40;object&#40;&#123;&#10; path &#61; string&#10; mode &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [vpc_connector_create](variables.tf#L246) | Populate this to create a VPC connector. You can then refer to it in the template annotations. | <code title="object&#40;&#123;&#10; ip_cidr_range &#61; optional&#40;string&#41;&#10; vpc_self_link &#61; optional&#40;string&#41;&#10; machine_type &#61; optional&#40;string&#41;&#10; name &#61; optional&#40;string&#41;&#10; instances &#61; optional&#40;object&#40;&#123;&#10; max &#61; optional&#40;number&#41;&#10; min &#61; optional&#40;number&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; throughput &#61; optional&#40;object&#40;&#123;&#10; max &#61; optional&#40;number&#41;&#10; min &#61; optional&#40;number&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; subnet &#61; optional&#40;object&#40;&#123;&#10; name &#61; optional&#40;string&#41;&#10; project_id &#61; optional&#40;string&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

24
modules/cloud-run/tags.tf Normal file
View File

@ -0,0 +1,24 @@
/**
* 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.
*/
resource "google_tags_location_tag_binding" "binding" {
for_each = var.tag_bindings
parent = (
"//run.googleapis.com/projects/${var.project_id}/locations/europe-west1/services/${google_cloud_run_service.service.name}"
)
tag_value = each.value
location = var.region
}

View File

@ -205,6 +205,13 @@ variable "startup_cpu_boost" {
default = false
}
variable "tag_bindings" {
description = "Tag bindings for this service, in key => tag value id format."
type = map(string)
nullable = false
default = {}
}
variable "timeout_seconds" {
description = "Maximum duration the instance is allowed for responding to a request."
type = number

View File

@ -8,7 +8,7 @@
- [GCS notifications](#gcs-notifications)
- [Object upload](#object-upload)
- [IAM](#iam)
- [Tags](#tags)
- [Tag Bindings](#tag-bindings)
- [Variables](#variables)
- [Outputs](#outputs)
<!-- END TOC -->
@ -247,7 +247,7 @@ module "bucket" {
# tftest modules=1 resources=2 inventory=iam-bindings-additive.yaml e2e
```
## Tags
## Tag Bindings
Refer to the [Creating and managing tags](https://cloud.google.com/resource-manager/docs/tags/tags-creating-and-managing) documentation for details on usage.
@ -307,10 +307,10 @@ module "bucket" {
| [retention_policy](variables.tf#L236) | Bucket retention policy. | <code title="object&#40;&#123;&#10; retention_period &#61; number&#10; is_locked &#61; optional&#40;bool&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [soft_delete_retention](variables.tf#L245) | The duration in seconds that soft-deleted objects in the bucket will be retained and cannot be permanently deleted. Set to 0 to override the default and disable. | <code>number</code> | | <code>null</code> |
| [storage_class](variables.tf#L251) | Bucket storage class. | <code>string</code> | | <code>&#34;MULTI_REGIONAL&#34;</code> |
| [tag_bindings](variables.tf#L261) | Tag bindings for this folder, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [uniform_bucket_level_access](variables.tf#L267) | Allow using object ACLs (false) or not (true, this is the recommended behavior) , defaults to true (which is the recommended practice, but not the behavior of storage API). | <code>bool</code> | | <code>true</code> |
| [versioning](variables.tf#L273) | Enable versioning, defaults to false. | <code>bool</code> | | <code>false</code> |
| [website](variables.tf#L279) | Bucket website. | <code title="object&#40;&#123;&#10; main_page_suffix &#61; optional&#40;string&#41;&#10; not_found_page &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L261) | Tag bindings for this folder, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [uniform_bucket_level_access](variables.tf#L268) | Allow using object ACLs (false) or not (true, this is the recommended behavior) , defaults to true (which is the recommended practice, but not the behavior of storage API). | <code>bool</code> | | <code>true</code> |
| [versioning](variables.tf#L274) | Enable versioning, defaults to false. | <code>bool</code> | | <code>false</code> |
| [website](variables.tf#L280) | Bucket website. | <code title="object&#40;&#123;&#10; main_page_suffix &#61; optional&#40;string&#41;&#10; not_found_page &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

View File

@ -15,7 +15,7 @@
*/
resource "google_tags_location_tag_binding" "binding" {
for_each = coalesce(var.tag_bindings, {})
for_each = var.tag_bindings
parent = "//storage.googleapis.com/projects/_/buckets/${local.prefix}${lower(var.name)}"
tag_value = each.value
location = var.location

View File

@ -261,7 +261,8 @@ variable "storage_class" {
variable "tag_bindings" {
description = "Tag bindings for this folder, in key => tag value id format."
type = map(string)
default = null
nullable = false
default = {}
}
variable "uniform_bucket_level_access" {

View File

@ -11,6 +11,7 @@ When using an existing keyring be mindful about applying IAM bindings, as all bi
- [Using an existing keyring](#using-an-existing-keyring)
- [Crypto key purpose](#crypto-key-purpose)
- [Import job](#import-job)
- [Tag Bindings](#tag-bindings)
- [Variables](#variables)
- [Outputs](#outputs)
<!-- END TOC -->
@ -114,6 +115,41 @@ module "kms" {
}
# tftest modules=1 resources=2 inventory=import-job.yaml e2e
```
### Tag Bindings
Refer to the [Creating and managing tags](https://cloud.google.com/resource-manager/docs/tags/tags-creating-and-managing) documentation for details on usage.
```hcl
module "org" {
source = "./fabric/modules/organization"
organization_id = var.organization_id
tags = {
environment = {
description = "Environment specification."
values = {
dev = {}
prod = {}
sandbox = {}
}
}
}
}
module "kms" {
source = "./fabric/modules/kms"
project_id = var.project_id
keyring = {
location = var.region
name = "test-3"
}
tag_bindings = {
env-sandbox = module.org.tag_values["environment/sandbox"].id
}
}
# tftest modules=2 resources=6
```
<!-- BEGIN TFDOC -->
## Variables

View File

@ -16,6 +16,6 @@
resource "google_tags_tag_binding" "binding" {
for_each = var.tag_bindings
parent = "//cloudresourcemanager.googleapis.com/${local.keyring.id}"
parent = "//cloudkms.googleapis.com/${local.keyring.id}"
tag_value = each.value
}

View File

@ -119,6 +119,6 @@ variable "project_id" {
variable "tag_bindings" {
description = "Tag bindings for this keyring, in key => tag value id format."
type = map(string)
default = {}
nullable = false
default = {}
}