2020-06-28 23:05:44 -07:00
# Cloud Function Module
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.
## 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" {
2022-12-16 03:53:56 -08:00
source = "./fabric/modules/cloud-function"
project_id = "my-project"
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
# tftest modules=1 resources=2
```
Analogous example using 2nd generation Cloud Functions
```hcl
module "cf-http" {
2022-12-16 03:53:56 -08:00
source = "./fabric/modules/cloud-function"
v2 = true
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
2022-11-08 23:53:23 -08:00
bundle_config = {
source_dir = "fabric/assets/"
output_path = "bundle.zip"
}
}
# tftest modules=1 resources=2
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" {
2022-11-12 03:34:09 -08:00
source = "./fabric/modules/cloud-function"
project_id = "my-project"
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 = {
2022-11-12 03:34:09 -08:00
v1 = {
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
```
2022-11-12 03:34:09 -08:00
Cloud Functions 2nd gen support only [Eventarc ](https://cloud.google.com/eventarc/docs ) and uses separate structure
2022-11-08 23:53:23 -08:00
to configure:
```hcl
module "trigger-service-account" {
source = "./fabric/modules/iam-service-account"
project_id = "my-project"
name = "sa-cloudfunction"
iam_project_roles = {
"my-project" = [
"roles/run.invoker"
]
}
}
module "cf-http" {
2022-11-12 03:34:09 -08:00
source = "./fabric/modules/cloud-function"
project_id = "my-project"
v2 = true
name = "test-cf-http"
bucket_name = "test-cf-bundles"
2022-11-08 23:53:23 -08:00
bundle_config = {
source_dir = "fabric/assets/"
output_path = "bundle.zip"
}
2022-11-12 03:34:09 -08:00
trigger_config = {
v2 = {
event_type = "google.cloud.pubsub.topic.v1.messagePublished"
pubsub_topic = "local.my-topic"
service_account_email = module.trigger-service-account.email
}
2022-11-08 23:53:23 -08:00
}
}
# tftest modules=2 resources=4
```
Ensure that pubsub robo-account `service-%s@gcp-sa-pubsub.iam.gserviceaccount.com` has `roles/iam.serviceAccountTokenCreatator`
as documented [here ](https://cloud.google.com/eventarc/docs/roles-permissions#pubsub-topic )
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" {
2022-12-16 03:53:56 -08:00
source = "./fabric/modules/cloud-function"
project_id = "my-project"
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"]
}
}
2022-11-08 23:53:23 -08:00
# tftest modules=1 resources=3
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" {
2022-12-16 03:53:56 -08:00
source = "./fabric/modules/cloud-function"
project_id = "my-project"
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
}
}
2022-11-08 23:53:23 -08:00
# tftest modules=1 resources=3
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" {
2022-12-16 03:53:56 -08:00
source = "./fabric/modules/cloud-function"
project_id = "my-project"
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" {
2022-12-16 03:53:56 -08:00
source = "./fabric/modules/cloud-function"
project_id = "my-project"
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" {
2022-12-16 03:53:56 -08:00
source = "./fabric/modules/cloud-function"
project_id = "my-project"
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
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.
```hcl
module "cf-http" {
2022-12-16 03:53:56 -08:00
source = "./fabric/modules/cloud-function"
project_id = "my-project"
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
2022-11-15 03:23:44 -08:00
```
2020-06-28 23:05:44 -07:00
<!-- BEGIN TFDOC -->
2021-12-20 23:51:51 -08:00
2020-06-28 23:05:44 -07:00
## 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 > | ✓ | |
2022-11-08 23:53:23 -08:00
| [bundle_config ](variables.tf#L37 ) | 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, "/tmp/bundle.zip") excludes = optional(list(string)) })" > object({…}) </ code > | ✓ | |
2022-11-15 05:47:11 -08:00
| [name ](variables.tf#L94 ) | Name used for cloud function and associated resources. | < code > string</ code > | ✓ | |
2022-11-15 06:12:50 -08:00
| [project_id ](variables.tf#L109 ) | Project id 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 > |
2022-11-24 09:56:01 -08:00
| [build_worker_pool ](variables.tf#L31 ) | Build worker pool, in projects/< PROJECT-ID > /locations/< REGION > /workerPools/< POOL_NAME > format. | < code > string</ code > | | < code > null</ code > |
2022-11-15 05:47:11 -08:00
| [description ](variables.tf#L46 ) | Optional description. | < code > string</ code > | | < code > " Terraform managed." </ code > |
| [environment_variables ](variables.tf#L52 ) | Cloud function environment variables. | < code > map( string) </ code > | | < code > {} </ code > |
2022-11-24 09:56:01 -08:00
| [function_config ](variables.tf#L58 ) | 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 runtime = optional(string, "python310") timeout_seconds = optional(number, 180) })" > object({…}) </ code > | | < code title = "{ entry_point = "main" instance_count = 1 memory_mb = 256 runtime = "python310" timeout_seconds = 180 }" > {…} </ code > |
2022-11-15 05:47:11 -08:00
| [iam ](variables.tf#L76 ) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | < code > map( list( string)) </ code > | | < code > {} </ code > |
| [ingress_settings ](variables.tf#L82 ) | 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#L88 ) | Resource labels. | < code > map( string) </ code > | | < code > {} </ code > |
| [prefix ](variables.tf#L99 ) | Optional prefix used for resource names. | < code > string</ code > | | < code > null</ code > |
2022-11-15 06:12:50 -08:00
| [region ](variables.tf#L114 ) | Region used for all resources. | < code > string</ code > | | < code > " europe-west1" </ code > |
| [secrets ](variables.tf#L120 ) | 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 > |
2022-11-12 03:34:09 -08:00
| [service_account ](variables.tf#L132 ) | Service account email. Unused if service account is auto-created. | < code > string</ code > | | < code > null</ code > |
2022-11-15 06:12:50 -08:00
| [service_account_create ](variables.tf#L138 ) | Auto-create service account. | < code > bool</ code > | | < code > false</ code > |
2022-11-15 08:03:56 -08:00
| [trigger_config ](variables.tf#L144 ) | Function trigger configuration. Leave null for HTTP trigger. | < code title = "object({ v1 = optional(object({ event = string resource = string retry = optional(bool) })), v2 = optional(object({ region = optional(string) event_type = optional(string) pubsub_topic = optional(string) event_filters = optional(list(object({ attribute = string value = string operator = string }))) service_account_email = optional(string) service_account_create = optional(bool) retry_policy = optional(string) })) })" > object({…}) </ code > | | < code > { v1 = null, v2 = null } </ code > |
2022-11-18 08:48:16 -08:00
| [v2 ](variables.tf#L173 ) | Whether to use Cloud Function version 2nd Gen or 1st Gen. | < code > bool</ code > | | < code > false</ code > |
| [vpc_connector ](variables.tf#L179 ) | 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#L189 ) | 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. | |
2022-11-18 08:48:16 -08:00
| [service_account ](outputs.tf#L39 ) | Service account resource. | |
| [service_account_email ](outputs.tf#L44 ) | Service account email. | |
| [service_account_iam_email ](outputs.tf#L49 ) | Service account email. | |
| [trigger_service_account ](outputs.tf#L57 ) | Service account resource. | |
| [trigger_service_account_email ](outputs.tf#L62 ) | Service account email. | |
| [trigger_service_account_iam_email ](outputs.tf#L67 ) | Service account email. | |
| [uri ](outputs.tf#L75 ) | Cloud function service uri. | |
| [vpc_connector ](outputs.tf#L80 ) | VPC connector resource if created. | |
2021-12-20 23:51:51 -08:00
2020-06-28 23:05:44 -07:00
<!-- END TFDOC -->