Skip to content

Latest commit

 

History

History
 
 

cloud-function-v1

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

Cloud Function Module (V1)

Cloud Function management, with support for IAM roles, optional bucket creation and bundle via GCS URI, local zip, or local source folder.

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.

module "cf-http" {
  source      = "./fabric/modules/cloud-function-v1"
  project_id  = var.project_id
  region      = var.regions.secondary
  name        = "test-cf-http"
  bucket_name = var.bucket
  bundle_config = {
    path = "assets/sample-function/"
  }
  depends_on = [
    google_project_iam_member.bucket_default_compute_account_grant,
  ]
}
# tftest modules=1 resources=5 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e

PubSub and non-HTTP triggers

Other trigger types other than HTTP are configured via the trigger_config variable. This example shows a PubSub trigger.

module "cf-http" {
  source      = "./fabric/modules/cloud-function-v1"
  project_id  = var.project_id
  region      = var.regions.secondary
  name        = "test-cf-http"
  bucket_name = var.bucket
  bundle_config = {
    path = "assets/sample-function/"
  }
  trigger_config = {
    event    = "google.pubsub.topic.publish"
    resource = module.pubsub.topic.name
  }
  depends_on = [
    google_project_iam_member.bucket_default_compute_account_grant,
  ]

}
# tftest modules=2 resources=7 fixtures=fixtures/pubsub.tf,fixtures/functions-default-sa-iam-grants.tf e2e

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.

module "cf-http" {
  source      = "./fabric/modules/cloud-function-v1"
  project_id  = var.project_id
  region      = var.regions.secondary
  name        = "test-cf-http"
  bucket_name = var.bucket
  bundle_config = {
    path = "assets/sample-function/"
  }
  iam = {
    "roles/cloudfunctions.invoker" = ["allUsers"]
  }
  depends_on = [
    google_project_iam_member.bucket_default_compute_account_grant,
  ]
}
# tftest fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=iam.yaml e2e

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.

module "cf-http" {
  source      = "./fabric/modules/cloud-function-v1"
  project_id  = var.project_id
  region      = var.regions.secondary
  prefix      = var.prefix
  name        = "test-cf-http"
  bucket_name = var.bucket
  bucket_config = {
    force_destroy             = true
    lifecycle_delete_age_days = 1
  }
  bundle_config = {
    path = "assets/sample-function/"
  }
  depends_on = [
    google_project_iam_member.bucket_default_compute_account_grant,
  ]
}
# tftest fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=bucket-creation.yaml e2e

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).

module "cf-http" {
  source      = "./fabric/modules/cloud-function-v1"
  project_id  = var.project_id
  region      = var.regions.secondary
  name        = "test-cf-http"
  bucket_name = var.bucket
  bundle_config = {
    path = "assets/sample-function/"
  }
  service_account_create = true
  depends_on = [
    google_project_iam_member.bucket_default_compute_account_grant,
  ]
}
# tftest modules=1 resources=6 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e

To use an externally managed service account, pass its email in service_account and leave service_account_create to false (the default).

module "cf-http" {
  source      = "./fabric/modules/cloud-function-v1"
  project_id  = var.project_id
  region      = var.regions.secondary
  name        = "test-cf-http"
  bucket_name = var.bucket
  bundle_config = {
    path = "assets/sample-function/"
  }
  service_account = var.service_account.email
  depends_on = [
    google_project_iam_member.bucket_default_compute_account_grant,
  ]
}
# tftest modules=1 resources=5 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e

Custom bundle config

The Cloud Function bundle can be configured via the bundle_config variable. The only mandatory argument is bundle_config.path which can point to:

  • a GCS URI of a ZIP archive
  • a local path to a ZIP archive
  • a local path to a source folder

When a GCS URI or a local zip file are used, a change in their names will trigger redeployment. When a local source folder is used a ZIP archive will be automatically generated and its internally derived checksum will drive redeployment. You can optionally control its name and exclusions via the attributes in bundle_config.folder_options.

module "cf-http" {
  source      = "./fabric/modules/cloud-function-v1"
  project_id  = var.project_id
  region      = var.regions.secondary
  name        = "test-cf-http"
  bucket_name = var.bucket
  bundle_config = {
    path = "assets/sample-function/"
    folder_options = {
      archive_path = "bundle.zip"
      excludes     = ["__pycache__"]
    }
  }
  depends_on = [
    google_project_iam_member.bucket_default_compute_account_grant,
  ]
}
# tftest modules=1 resources=5 fixtures=fixtures/functions-default-sa-iam-grants.tf  e2e

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.

module "cf-http" {
  source            = "./fabric/modules/cloud-function-v1"
  project_id        = var.project_id
  region            = var.regions.secondary
  name              = "test-cf-http"
  bucket_name       = var.bucket
  build_worker_pool = google_cloudbuild_worker_pool.pool.id
  bundle_config = {
    path = "assets/sample-function/"
  }
  depends_on = [
    google_project_iam_member.bucket_default_compute_account_grant,
  ]
}
# tftest modules=1 resources=6 fixtures=fixtures/cloudbuild-custom-pool.tf,fixtures/functions-default-sa-iam-grants.tf e2e

Multiple Cloud Functions within project

When deploying multiple functions do not reuse bundle_config.archive_path between instances as the result is undefined. Default archive_path creates file in /tmp folder using project Id and function name to avoid name conflicts.

module "cf-http-one" {
  source      = "./fabric/modules/cloud-function-v1"
  project_id  = var.project_id
  region      = var.regions.secondary
  name        = "test-cf-http-one"
  bucket_name = var.bucket
  bundle_config = {
    path = "assets/sample-function/"
  }
}

module "cf-http-two" {
  source      = "./fabric/modules/cloud-function-v1"
  project_id  = var.project_id
  region      = var.regions.secondary
  name        = "test-cf-http-two"
  bucket_name = var.bucket
  bundle_config = {
    path = "assets/sample-function/"
  }
  depends_on = [
    google_project_iam_member.bucket_default_compute_account_grant,
  ]
}
# tftest fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=multiple_functions.yaml e2e

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/ver1 contains version referenced by module.secret-manager.version_versions["credentials:v1"]
module "cf-http" {
  source      = "./fabric/modules/cloud-function-v1"
  project_id  = var.project_id
  region      = var.regions.secondary
  name        = "test-cf-http"
  bucket_name = var.bucket
  bundle_config = {
    path = "assets/sample-function/"
  }
  secrets = {
    VARIABLE_SECRET = {
      is_volume  = false
      project_id = var.project_number # use project_number  to avoid perm-diff
      secret     = reverse(split("/", module.secret-manager.secrets["credentials"].name))[0]
      versions = [
        "latest"
      ]
    }
    "/app/secret" = {
      is_volume  = true
      project_id = var.project_number # use project_number  to avoid perm-diff
      secret     = reverse(split("/", module.secret-manager.secrets["credentials"].name))[0]
      versions = [
        "${module.secret-manager.version_versions["credentials:v1"]}:/ver1"
      ]
    }
  }
  depends_on = [
    google_project_iam_member.bucket_default_compute_account_grant,
  ]
}
# tftest fixtures=fixtures/secret-credentials.tf,fixtures/functions-default-sa-iam-grants.tf  inventory=secrets.yaml e2e

Using CMEK to encrypt function resources

This encrypt bucket gcf-sources-* with the provided kms key. The repository has to be encrypted with the same kms key.

module "project" {
  source          = "./fabric/modules/project"
  name            = "cf-v1"
  billing_account = var.billing_account_id
  prefix          = var.prefix
  parent          = var.folder_id
  services = [
    "artifactregistry.googleapis.com",
    "cloudbuild.googleapis.com",
    "cloudfunctions.googleapis.com",
    "cloudkms.googleapis.com",
    "compute.googleapis.com",
    "storage.googleapis.com",
  ]
  iam = {
    # grant compute default service account that is used by Cloud Founction
    # permission to read from the buckets so it can function sources
    "roles/storage.objectViewer" = [
      "serviceAccount:${module.project.default_service_accounts.compute}"
    ]
  }
}

module "kms" {
  source     = "./fabric/modules/kms"
  project_id = module.project.project_id
  keyring = {
    location = var.regions.secondary
    name     = "keyring"
  }
  keys = {
    "key-regional" = {
    }
  }
  iam = {
    "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [
      module.project.service_agents["artifactregistry"].iam_email,
      module.project.service_agents["cloudfunctions"].iam_email,
      module.project.service_agents["storage"].iam_email,
    ]
  }
}

module "artifact-registry" {
  source         = "./fabric/modules/artifact-registry"
  project_id     = module.project.project_id
  location       = var.regions.secondary
  name           = "registry"
  format         = { docker = { standard = {} } }
  encryption_key = module.kms.key_ids["key-regional"]
  iam = {
    "roles/artifactregistry.createOnPushWriter" = [
      # grant compute default service account that is used by Cloud Build
      # permission to push compiled container into Artifact Registry
      "serviceAccount:${module.project.default_service_accounts.compute}",
    ]
  }
}

module "cf-http" {
  source      = "./fabric/modules/cloud-function-v1"
  project_id  = module.project.project_id
  region      = var.regions.secondary
  name        = "test-cf-http"
  bucket_name = var.bucket
  bundle_config = {
    path = "assets/sample-function/"
  }
  kms_key = module.kms.key_ids["key-regional"]
  repository_settings = {
    repository = module.artifact-registry.id
  }
}
# tftest modules=4 resources=25

Variables

name description type required default
bucket_name 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. string
bundle_config Cloud function source. Path can point to a GCS object URI, or a local path. A local path to a zip archive will generate a GCS object using its basename, a folder will be zipped and the GCS object name inferred when not specified. object({…})
name Name used for cloud function and associated resources. string
project_id Project id used for all resources. string
region Region used for all resources. string
bucket_config Enable and configure auto-created bucket. Set fields to null to use defaults. object({…}) null
build_environment_variables A set of key/value environment variable pairs available during build time. map(string) {}
build_worker_pool Build worker pool, in projects//locations//workerPools/<POOL_NAME> format. string null
description Optional description. string "Terraform managed."
environment_variables Cloud function environment variables. map(string) {}
function_config Cloud function configuration. Defaults to using main as entrypoint, 1 instance with 256MiB of memory, and 180 second timeout. object({…}) {…}
https_security_level The security level for the function: Allowed values are SECURE_ALWAYS, SECURE_OPTIONAL. string null
iam IAM bindings for topic in {ROLE => [MEMBERS]} format. map(list(string)) {}
ingress_settings Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL, ALLOW_INTERNAL_AND_GCLB and ALLOW_INTERNAL_ONLY . string null
kms_key Resource name of a KMS crypto key (managed by the user) used to encrypt/decrypt function resources in key id format. If specified, you must also provide an artifact registry repository using the docker_repository field that was created with the same KMS crypto key. string null
labels Resource labels. map(string) {}
prefix Optional prefix used for resource names. string null
repository_settings Docker Registry to use for storing the function's Docker images and specific repository. If kms_key is provided, the repository must have already been encrypted with the key. object({…}) {…}
secrets Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format. map(object({…})) {}
service_account Service account email. Unused if service account is auto-created. string null
service_account_create Auto-create service account. bool false
trigger_config Function trigger configuration. Leave null for HTTP trigger. object({…}) null
vpc_connector VPC connector configuration. Set create to 'true' if a new connector needs to be created. object({…}) null
vpc_connector_config VPC connector network configuration. Must be provided if new VPC connector is being created. object({…}) null

Outputs

name description sensitive
bucket Bucket resource (only if auto-created).
bucket_name Bucket name.
function Cloud function resources.
function_name Cloud function name.
id Fully qualified function id.
service_account Service account resource.
service_account_email Service account email.
service_account_iam_email Service account email.
vpc_connector VPC connector resource if created.

Fixtures