2023-06-19 03:50:36 -07:00
# Cloud Function Module (V1)
2020-06-28 23:05:44 -07:00
Cloud Function management, with support for IAM roles and optional bucket creation.
The GCS object used for deployment uses a hash of the bundle zip contents in its name, which ensures change tracking and avoids recreating the function if the GCS object is deleted and needs recreating.
2023-09-25 07:15:22 -07:00
<!-- BEGIN TOC -->
- [TODO ](#todo )
- [Examples ](#examples )
- [HTTP trigger ](#http-trigger )
- [PubSub and non-HTTP triggers ](#pubsub-and-non-http-triggers )
- [Controlling HTTP access ](#controlling-http-access )
- [GCS bucket creation ](#gcs-bucket-creation )
- [Service account management ](#service-account-management )
- [Custom bundle config ](#custom-bundle-config )
- [Private Cloud Build Pool ](#private-cloud-build-pool )
- [Multiple Cloud Functions within project ](#multiple-cloud-functions-within-project )
- [Mounting secrets from Secret Manager ](#mounting-secrets-from-secret-manager )
- [Variables ](#variables )
- [Outputs ](#outputs )
<!-- END TOC -->
2020-06-28 23:05:44 -07:00
## TODO
- [ ] add support for `source_repository`
## Examples
### HTTP trigger
This deploys a Cloud Function with an HTTP endpoint, using a pre-existing GCS bucket for deployment, setting the service account to the Cloud Function default one, and delegating access control to the containing project.
```hcl
module "cf-http" {
2023-06-19 03:50:36 -07:00
source = "./fabric/modules/cloud-function-v1"
2023-10-20 00:59:52 -07:00
project_id = var.project_id
2024-01-24 02:23:40 -08:00
region = "europe-west1"
2022-12-16 03:53:56 -08:00
name = "test-cf-http"
2023-10-20 00:59:52 -07:00
bucket_name = var.bucket
2022-11-08 23:53:23 -08:00
bundle_config = {
2023-10-20 00:59:52 -07:00
source_dir = "assets/sample-function/"
2022-11-08 23:53:23 -08:00
output_path = "bundle.zip"
}
}
2023-10-20 00:59:52 -07:00
# tftest modules=1 resources=2 e2e
2020-06-28 23:05:44 -07:00
```
2020-07-04 01:04:53 -07:00
### PubSub and non-HTTP triggers
2020-06-28 23:05:44 -07:00
Other trigger types other than HTTP are configured via the `trigger_config` variable. This example shows a PubSub trigger.
```hcl
module "cf-http" {
2023-06-19 03:50:36 -07:00
source = "./fabric/modules/cloud-function-v1"
2022-11-12 03:34:09 -08:00
project_id = "my-project"
2024-01-24 02:23:40 -08:00
region = "europe-west1"
2022-11-12 03:34:09 -08:00
name = "test-cf-http"
bucket_name = "test-cf-bundles"
2020-06-28 23:05:44 -07:00
bundle_config = {
2022-11-08 23:53:23 -08:00
source_dir = "fabric/assets/"
2021-11-07 01:46:22 -08:00
output_path = "bundle.zip"
2020-06-28 23:05:44 -07:00
}
trigger_config = {
2023-06-19 03:50:36 -07:00
event = "google.pubsub.topic.publish"
resource = "local.my-topic"
2020-06-28 23:05:44 -07:00
}
}
2022-11-08 23:53:23 -08:00
# tftest modules=1 resources=2
2020-06-28 23:05:44 -07:00
```
### Controlling HTTP access
To allow anonymous access to the function, grant the `roles/cloudfunctions.invoker` role to the special `allUsers` identifier. Use specific identities (service accounts, groups, etc.) instead of `allUsers` to only allow selective access.
```hcl
module "cf-http" {
2023-06-19 03:50:36 -07:00
source = "./fabric/modules/cloud-function-v1"
2022-12-16 03:53:56 -08:00
project_id = "my-project"
2024-01-24 02:23:40 -08:00
region = "europe-west1"
2022-12-16 03:53:56 -08:00
name = "test-cf-http"
bucket_name = "test-cf-bundles"
2020-06-28 23:05:44 -07:00
bundle_config = {
2022-11-08 23:53:23 -08:00
source_dir = "fabric/assets/"
2021-11-07 01:46:22 -08:00
output_path = "bundle.zip"
2020-06-28 23:05:44 -07:00
}
2022-12-16 03:53:56 -08:00
iam = {
2020-06-28 23:05:44 -07:00
"roles/cloudfunctions.invoker" = ["allUsers"]
}
}
2023-06-19 03:50:36 -07:00
# tftest modules=1 resources=3 inventory=iam.yaml
2020-06-28 23:05:44 -07:00
```
### GCS bucket creation
You can have the module auto-create the GCS bucket used for deployment via the `bucket_config` variable. Setting `bucket_config.location` to `null` will also use the function region for GCS.
```hcl
module "cf-http" {
2023-06-19 03:50:36 -07:00
source = "./fabric/modules/cloud-function-v1"
2022-12-16 03:53:56 -08:00
project_id = "my-project"
2024-01-24 02:23:40 -08:00
region = "europe-west1"
2023-09-28 03:17:53 -07:00
prefix = "my-prefix"
2022-12-16 03:53:56 -08:00
name = "test-cf-http"
bucket_name = "test-cf-bundles"
2020-06-28 23:05:44 -07:00
bucket_config = {
2022-11-16 00:31:43 -08:00
lifecycle_delete_age_days = 1
2020-06-28 23:05:44 -07:00
}
bundle_config = {
2022-12-16 03:53:56 -08:00
source_dir = "fabric/assets/"
2020-06-28 23:05:44 -07:00
}
}
2023-09-28 03:17:53 -07:00
# tftest modules=1 resources=3 inventory=bucket-creation.yaml
2020-06-28 23:05:44 -07:00
```
### Service account management
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).
```hcl
module "cf-http" {
2023-06-19 03:50:36 -07:00
source = "./fabric/modules/cloud-function-v1"
2022-12-16 03:53:56 -08:00
project_id = "my-project"
2024-01-24 02:23:40 -08:00
region = "europe-west1"
2022-12-16 03:53:56 -08:00
name = "test-cf-http"
bucket_name = "test-cf-bundles"
2020-06-28 23:05:44 -07:00
bundle_config = {
2022-11-08 23:53:23 -08:00
source_dir = "fabric/assets/"
2021-11-07 01:46:22 -08:00
output_path = "bundle.zip"
2020-06-28 23:05:44 -07:00
}
service_account_create = true
}
2022-11-08 23:53:23 -08:00
# tftest modules=1 resources=3
2020-06-28 23:05:44 -07:00
```
To use an externally managed service account, pass its email in `service_account` and leave `service_account_create` to `false` (the default).
```hcl
module "cf-http" {
2023-06-19 03:50:36 -07:00
source = "./fabric/modules/cloud-function-v1"
2022-12-16 03:53:56 -08:00
project_id = "my-project"
2024-01-24 02:23:40 -08:00
region = "europe-west1"
2022-12-16 03:53:56 -08:00
name = "test-cf-http"
bucket_name = "test-cf-bundles"
2020-06-28 23:05:44 -07:00
bundle_config = {
2022-11-08 23:53:23 -08:00
source_dir = "fabric/assets/"
2021-11-07 01:46:22 -08:00
output_path = "bundle.zip"
2020-06-28 23:05:44 -07:00
}
2022-11-08 23:53:23 -08:00
service_account = "non-existent@serice.account.email"
2020-06-28 23:05:44 -07:00
}
2022-11-08 23:53:23 -08:00
# tftest modules=1 resources=2
2020-06-28 23:05:44 -07:00
```
2021-11-06 06:48:22 -07:00
### Custom bundle config
2021-11-07 01:46:22 -08:00
In order to help prevent `archive_zip.output_md5` from changing cross platform (e.g. Cloud Build vs your local development environment), you'll have to make sure that the files included in the zip are always the same.
2021-11-06 06:48:22 -07:00
```hcl
module "cf-http" {
2023-06-19 03:50:36 -07:00
source = "./fabric/modules/cloud-function-v1"
2022-12-16 03:53:56 -08:00
project_id = "my-project"
2024-01-24 02:23:40 -08:00
region = "europe-west1"
2022-12-16 03:53:56 -08:00
name = "test-cf-http"
bucket_name = "test-cf-bundles"
2021-11-06 06:48:22 -07:00
bundle_config = {
2022-11-08 23:53:23 -08:00
source_dir = "fabric/assets"
2021-11-07 01:46:22 -08:00
output_path = "bundle.zip"
excludes = ["__pycache__"]
2021-11-06 06:48:22 -07:00
}
}
2022-11-08 23:53:23 -08:00
# tftest modules=1 resources=2
2021-11-06 06:48:22 -07:00
```
2022-11-15 03:23:44 -08:00
### Private Cloud Build Pool
2023-06-19 03:50:36 -07:00
This deploys a Cloud Function with an HTTP endpoint, using a pre-existing GCS bucket for deployment using a pre existing private Cloud Build worker pool.
2022-11-15 03:23:44 -08:00
```hcl
module "cf-http" {
2023-06-19 03:50:36 -07:00
source = "./fabric/modules/cloud-function-v1"
2022-12-16 03:53:56 -08:00
project_id = "my-project"
2024-01-24 02:23:40 -08:00
region = "europe-west1"
2022-12-16 03:53:56 -08:00
name = "test-cf-http"
bucket_name = "test-cf-bundles"
2022-11-15 03:23:44 -08:00
build_worker_pool = "projects/my-project/locations/europe-west1/workerPools/my_build_worker_pool"
bundle_config = {
2022-11-16 00:55:45 -08:00
source_dir = "fabric/assets"
2022-11-15 03:23:44 -08:00
output_path = "bundle.zip"
}
}
2022-11-16 00:55:45 -08:00
# tftest modules=1 resources=2
2023-03-27 03:18:04 -07:00
```
### Multiple Cloud Functions within project
When deploying multiple functions do not reuse `bundle_config.output_path` between instances as the result is undefined. Default `output_path` creates file in `/tmp` folder using project Id and function name to avoid name conflicts.
```hcl
module "cf-http-one" {
2023-06-19 03:50:36 -07:00
source = "./fabric/modules/cloud-function-v1"
2023-03-27 03:18:04 -07:00
project_id = "my-project"
2024-01-24 02:23:40 -08:00
region = "europe-west1"
2023-03-27 03:18:04 -07:00
name = "test-cf-http-one"
bucket_name = "test-cf-bundles"
bundle_config = {
source_dir = "fabric/assets"
}
}
module "cf-http-two" {
2023-06-19 03:50:36 -07:00
source = "./fabric/modules/cloud-function-v1"
2023-03-27 03:18:04 -07:00
project_id = "my-project"
2024-01-24 02:23:40 -08:00
region = "europe-west1"
2023-03-27 03:18:04 -07:00
name = "test-cf-http-two"
bucket_name = "test-cf-bundles"
bundle_config = {
source_dir = "fabric/assets"
}
}
# tftest modules=2 resources=4 inventory=multiple_functions.yaml
2022-11-15 03:23:44 -08:00
```
2023-06-19 03:50:36 -07:00
2023-09-25 07:15:22 -07:00
### Mounting secrets from Secret Manager
This provides the latest value of the secret `var_secret` as `VARIABLE_SECRET` environment variable and three values of `path_secret` mounted in filesystem:
* `/app/secret/first` contains version 1
* `/app/secret/second` contains version 2
* `/app/secret/latest` contains latest version of the secret
```hcl
module "cf-http" {
source = "./fabric/modules/cloud-function-v1"
project_id = "my-project"
2024-01-24 02:23:40 -08:00
region = "europe-west1"
2023-09-25 07:15:22 -07:00
name = "test-cf-http"
bucket_name = "test-cf-bundles"
bundle_config = {
source_dir = "fabric/assets"
output_path = "bundle.zip"
}
secrets = {
VARIABLE_SECRET = {
is_volume = false
project_id = 1234567890
secret = "var_secret"
versions = [
"latest"
]
}
"/app/secret" = {
is_volume = true
project_id = 1234567890
secret = "path_secret"
versions = [
"1:first",
"2:second",
"latest:latest"
]
}
}
}
# tftest modules=1 resources=2 inventory=secrets.yaml
```
2020-06-28 23:05:44 -07:00
<!-- BEGIN TFDOC -->
## Variables
| name | description | type | required | default |
2021-12-20 23:51:51 -08:00
|---|---|:---:|:---:|:---:|
2022-01-22 04:34:35 -08:00
| [bucket_name ](variables.tf#L26 ) | Name of the bucket that will be used for the function code. It will be created with prefix prepended if bucket_config is not null. | < code > string</ code > | ✓ | |
2023-09-28 03:17:53 -07:00
| [bundle_config ](variables.tf#L38 ) | Cloud function source folder and generated zip bundle paths. Output path defaults to '/tmp/bundle.zip' if null. | < code title = "object({ source_dir = string output_path = optional(string) excludes = optional(list(string)) })" > object({…}) </ code > | ✓ | |
2024-02-28 12:20:56 -08:00
| [name ](variables.tf#L103 ) | Name used for cloud function and associated resources. | < code > string</ code > | ✓ | |
| [project_id ](variables.tf#L118 ) | Project id used for all resources. | < code > string</ code > | ✓ | |
| [region ](variables.tf#L123 ) | Region used for all resources. | < code > string</ code > | ✓ | |
2022-11-16 00:55:45 -08:00
| [bucket_config ](variables.tf#L17 ) | Enable and configure auto-created bucket. Set fields to null to use defaults. | < code title = "object({ location = optional(string) lifecycle_delete_age_days = optional(number) })" > object({…}) </ code > | | < code > null</ code > |
2023-09-28 03:17:53 -07:00
| [build_worker_pool ](variables.tf#L32 ) | Build worker pool, in projects/< PROJECT-ID > /locations/< REGION > /workerPools/< POOL_NAME > format. | < code > string</ code > | | < code > null</ code > |
| [description ](variables.tf#L47 ) | Optional description. | < code > string</ code > | | < code > " Terraform managed." </ code > |
| [environment_variables ](variables.tf#L53 ) | Cloud function environment variables. | < code > map( string) </ code > | | < code > {} </ code > |
| [function_config ](variables.tf#L59 ) | Cloud function configuration. Defaults to using main as entrypoint, 1 instance with 256MiB of memory, and 180 second timeout. | < code title = "object({ entry_point = optional(string, "main") instance_count = optional(number, 1) memory_mb = optional(number, 256) # Memory in MB cpu = optional(string, "0.166") runtime = optional(string, "python310") timeout_seconds = optional(number, 180) })" > object({…}) </ code > | | < code title = "{ entry_point = "main" instance_count = 1 memory_mb = 256 cpu = "0.166" runtime = "python310" timeout_seconds = 180 }" > {…} </ code > |
2024-02-28 12:20:56 -08:00
| [https_security_level ](variables.tf#L79 ) | The security level for the function: Allowed values are SECURE_ALWAYS, SECURE_OPTIONAL. | < code > string</ code > | | < code > null</ code > |
| [iam ](variables.tf#L85 ) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | < code > map( list( string)) </ code > | | < code > {} </ code > |
| [ingress_settings ](variables.tf#L91 ) | Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL, ALLOW_INTERNAL_AND_GCLB and ALLOW_INTERNAL_ONLY . | < code > string</ code > | | < code > null</ code > |
| [labels ](variables.tf#L97 ) | Resource labels. | < code > map( string) </ code > | | < code > {} </ code > |
| [prefix ](variables.tf#L108 ) | Optional prefix used for resource names. | < code > string</ code > | | < code > null</ code > |
| [secrets ](variables.tf#L128 ) | Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format. | < code title = "map(object({ is_volume = bool project_id = number secret = string versions = list(string) }))" > map( object({…})) </ code > | | < code > {} </ code > |
| [service_account ](variables.tf#L140 ) | Service account email. Unused if service account is auto-created. | < code > string</ code > | | < code > null</ code > |
| [service_account_create ](variables.tf#L146 ) | Auto-create service account. | < code > bool</ code > | | < code > false</ code > |
| [trigger_config ](variables.tf#L152 ) | Function trigger configuration. Leave null for HTTP trigger. | < code title = "object({ event = string resource = string retry = optional(bool) })" > object({…}) </ code > | | < code > null</ code > |
| [vpc_connector ](variables.tf#L162 ) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | < code title = "object({ create = bool name = string egress_settings = string })" > object({…}) </ code > | | < code > null</ code > |
| [vpc_connector_config ](variables.tf#L172 ) | VPC connector network configuration. Must be provided if new VPC connector is being created. | < code title = "object({ ip_cidr_range = string network = string })" > object({…}) </ code > | | < code > null</ code > |
2020-06-28 23:05:44 -07:00
## Outputs
| name | description | sensitive |
|---|---|:---:|
2022-01-22 04:34:35 -08:00
| [bucket ](outputs.tf#L17 ) | Bucket resource (only if auto-created). | |
| [bucket_name ](outputs.tf#L24 ) | Bucket name. | |
| [function ](outputs.tf#L29 ) | Cloud function resources. | |
| [function_name ](outputs.tf#L34 ) | Cloud function name. | |
2023-06-02 07:07:22 -07:00
| [id ](outputs.tf#L39 ) | Fully qualified function id. | |
| [service_account ](outputs.tf#L44 ) | Service account resource. | |
| [service_account_email ](outputs.tf#L49 ) | Service account email. | |
| [service_account_iam_email ](outputs.tf#L54 ) | Service account email. | |
2023-06-19 03:50:36 -07:00
| [vpc_connector ](outputs.tf#L62 ) | VPC connector resource if created. | |
2024-01-24 02:23:40 -08:00
<!-- END TFDOC -->