Skip to content

microsoftexpert/tf-mod-gcp-cloud-function

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

☁️ Google Cloud Cloud Function (2nd gen) Terraform Module

Deploys a single 2nd-generation, Cloud-Run-backed Cloud Function (google_cloudfunctions2_function) β€” build configuration, service (runtime) configuration, and an optional Eventarc-backed event trigger. Targets hashicorp/google ~> 7.0, Terraform >= 1.12.0.

Terraform Google Provider Module Version Module Type Resources Posture


🧩 Overview

  • πŸš€ Creates one google_cloudfunctions2_function β€” a Cloud-Run-backed, event- or HTTP-invoked serverless function (GCP console: "Cloud Function," 2nd gen).
  • πŸ—οΈ Renders all three of the resource's nested configuration groups: build_config (how the container is built from caller/CI-staged source), service_config (the deployed Cloud Run runtime β€” memory, CPU, concurrency, VPC egress, secrets), and an optional event_trigger (Eventarc β€” Pub/Sub, GCS, Audit Log, or custom event sources).
  • πŸ”’ Locks down network exposure by default β€” service_config.ingress_settings defaults to ALLOW_INTERNAL_ONLY (a secure-by-default extension to this module suite's house table of secure defaults; this resource's own provider default, if left unmanaged, is ALLOW_ALL).
  • πŸ”Œ Wires cleanly to sibling modules as plain string inputs: a service account across three distinct arguments with two distinct string shapes, an Artifact Registry repository id, a Pub/Sub topic id, a Secret Manager secret_id, and a VPC subnetwork name (not self_link β€” a confirmed deviation from tf-mod-gcp-cloud-run-service's precedent).
  • 🧱 Standalone by design β€” build_config/service_config/event_trigger are nested configuration blocks on one resource, not independent Terraform resources, so this stays a single-keystone module with no composite shape.
  • βœ‚οΈ Does not manage the source archive itself β€” build_config.source accepts plain bucket/object (or repo) coordinates pointing at source the caller/CI pipeline already staged.

πŸ’‘ Why it matters: Cloud Functions (2nd gen) is our default serverless compute target for lightweight event-driven and HTTP workloads that don't warrant a full Cloud Run deployment pipeline. Getting the ingress default locked down, the three separate identity arguments wired to their correct string shapes, and secrets sourced from Secret Manager rather than literal values are the most common Cloud Functions misconfiguration findings this module forecloses by default.


❀️ Support this project

If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:

Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!


πŸ—ΊοΈ Where this fits

graph LR
 PS["tf-mod-gcp-project-services"]:::external
 SA["tf-mod-gcp-service-account"]:::keystoneSibling
 AR["tf-mod-gcp-artifact-registry-repository"]:::sibling
 PST["tf-mod-gcp-pubsub-topic"]:::sibling
 SM["tf-mod-gcp-secret-manager-secret"]:::sibling
 VPCN["tf-mod-gcp-vpc-network"]:::sibling
 KMS["tf-mod-gcp-kms-keyring"]:::sibling
 CF["tf-mod-gcp-cloud-function"]:::thisModule
 SCHED["tf-mod-gcp-cloud-scheduler-job"]:::sibling

 PS -- "enables cloudfunctions/run/cloudbuild/artifactregistry.googleapis.com" --> CF
 SA -- "id consumed as build_config.service_account (fully-qualified)" --> CF
 SA -- "email consumed as service_config.service_account_email (bare)" --> CF
 SA -- "email consumed as event_trigger.service_account_email (bare)" --> CF
 AR -- "id consumed as build_config.docker_repository" --> CF
 PST -- "id consumed as event_trigger.pubsub_topic" --> CF
 SM -- "secret_id consumed as secret_environment_variables / secret_volumes" --> CF
 VPCN -- "subnetwork name (not self_link) consumed as direct_vpc_network_interface" --> CF
 KMS -- "crypto key name consumed as kms_key_name (CMEK)" --> CF
 CF -. "informational β€” plain url string, not a Terraform reference".-> SCHED

 classDef thisModule fill:#4285F4,color:#ffffff,stroke:#174EA6,stroke-width:1px;
 classDef keystoneSibling fill:#174EA6,color:#ffffff,stroke:#174EA6,stroke-width:1px;
 classDef sibling fill:#E8EAED,color:#202124,stroke:#9AA0A6,stroke-width:1px;
 classDef external fill:#E8EAED,color:#202124,stroke:#9AA0A6,stroke-width:1px,stroke-dasharray: 3 3;
Loading

This module has a real sibling family, so the family DAG is not skipped. tf-mod-gcp-service-account is marked as the keystone sibling β€” every real deployment needs at least one identity, and this resource is unusual in consuming three distinct arguments from the same sibling module, with two different string shapes (see Architecture Notes). Validated via the Mermaid Chart MCP before embedding. tf-mod-gcp-project-services (external, dashed) must have already enabled the unconditional APIs before this module applies. tf-mod-gcp-artifact-registry-repository's and tf-mod-gcp-kms-keyring's relationships are both genuinely optional β€” GCF creates its own default Artifact Registry repository and Google-managed encryption if neither is supplied. The edge toward tf-mod-gcp-cloud-scheduler-job is informational only (dashed) β€” the deployed url crosses as a plain string, not a Terraform id/self_link reference.


🧬 What this builds

graph LR
 subgraph Inputs
 A["var.name / var.location / var.description"]
 B["var.kms_key_name"]
 C["var.deletion_policy"]
 D["var.labels / var.timeouts"]
 E["var.build_config
 (runtime, entry_point, source,
 docker_repository, service_account,...)"]
 F["var.service_config
 (ingress_settings, secrets, VPC egress,
 service_account_email,...)"]
 G["var.event_trigger
 (event_type, pubsub_topic,
 event_filters,...)"]
 end

 R["google_cloudfunctions2_function.this"]:::thisModule

 A --> R
 B --> R
 C --> R
 D --> R
 E -- "nested block: build_config" --> R
 F -- "nested block: service_config" --> R
 G -- "nested block: event_trigger (optional)" --> R

 R --> O1["output: id"]
 R --> O2["output: url"]
 R --> O3["output: name"]
 R --> O4["output: state"]
 R --> O5["output: environment"]
 R --> O6["output: service_uri / service_gcf_uri"]

 classDef thisModule fill:#4285F4,color:#ffffff,stroke:#174EA6,stroke-width:1px;
Loading

Resource inventory: exactly one resource, google_cloudfunctions2_function.this. build_config, service_config, and event_trigger are internal nested configuration groups on that one resource, not separate managed resources β€” validated via the Mermaid Chart MCP before embedding.


βœ… Provider / Versions

Requirement Value
Terraform >= 1.12.0
hashicorp/google provider ~> 7.0
Provider block None β€” the caller configures google (project, region/zone, auth)

Schema notes that bite (verified against hashicorp/google v7.39.0 via the live provider schema, provider_doc_id 12683364):

  • No deletion_protection. Confirmed absent from the live schema β€” a gap versus tf-mod-gcp-cloud-run-service. deletion_policy (Terraform-only, default DELETE) is the only deletion-related guard this resource exposes.
  • Three distinct service-account-consuming arguments, two distinct string shapes. build_config.service_account wants the FULLY-QUALIFIED projects/{project}/serviceAccounts/{email} form; service_config.service_account_email and event_trigger.service_account_email both want the BARE email string. Confirmed via the provider's own "Basic Builder" (fully-qualified) and "Full"/"Basic Auditlogs" (bare email) examples.
  • direct_vpc_network_interface.network/.subnetwork take bare NAME strings, not self_link/id β€” a deviation from tf-mod-gcp-cloud-run-service's vpc_access precedent. Confirmed directly in the argument reference text: "The name of the VPC network..."/"The name of the VPC subnetwork...".
  • No self_link. Confirmed absent from the live Attributes Reference β€” id and top-level url are this module's primary outputs instead.
  • url, service_config[0].uri, and service_config[0].gcf_uri are three distinct attribute paths all expected to carry substantially the same deployed URL β€” a confirmed, documented duplication (see the provider's own "Cloudfunctions2 Scheduler Auth" example, which reads service_config[0].uri specifically), not a bug.
  • ingress_settings possible values are ALLOW_ALL / ALLOW_INTERNAL_ONLY / ALLOW_INTERNAL_AND_GCLB β€” NOT the same enum strings as Cloud Run v2's INGRESS_TRAFFIC_* values. Provider default if unmanaged is ALLOW_ALL; this module overrides that to ALLOW_INTERNAL_ONLY (secure-by-default extension β€” see Design Principles).
  • kms_key_name (CMEK) is a plain GA argument, resolved during this authoring session β€” the only official worked example demonstrating it end-to-end sets provider = google-beta on every resource, but that example also provisions a genuinely beta-only google_project_service_identity lookup; kms_key_name itself carries no beta annotation in the Argument Reference. See variables.tf's header comment for the full cross-check. Still recommend a live plan/apply check before relying on CMEK in production (this library's plan-only posture cannot catch apply-time KMS IAM-permission rejections either way).
  • timeouts supports the full create/update/delete triad, each defaulting to 60 minutes.
  • This module does not manage the source archive. build_config.source.storage_source/ .repo_source reference already-staged source (a caller/CI responsibility) β€” see Architecture Notes.

πŸ”‘ Required IAM Roles

  • roles/cloudfunctions.admin on the target project β€” least-privilege role for the applying principal to create, update, and delete Cloud Functions (2nd gen).
  • Separately (required for the function to build and run, not for this module's own apply): the build service account needs roles/logging.logWriter, roles/artifactregistry.writer, and roles/storage.objectAdmin (or narrower equivalents); the runtime service account needs roles/secretmanager.secretAccessor on any secret it reads; an event-triggered function's trigger service account needs roles/run.invoker and roles/eventarc.eventReceiver. Grant these via tf-mod-gcp-project-iam-bindings or a resource-scoped IAM binding, not inside this module.

☁️ GCP Prerequisites

  • cloudfunctions.googleapis.com, run.googleapis.com, cloudbuild.googleapis.com, and artifactregistry.googleapis.com enabled on the target project (via tf-mod-gcp-project-services, applied before this module) β€” all four UNCONDITIONALLY required.
  • eventarc.googleapis.com β€” CONDITIONALLY required, only when event_trigger is populated.
  • secretmanager.googleapis.com enabled, the referenced secret(s) already exist, and the runtime service account already holds roles/secretmanager.secretAccessor on them β€” if any secret_environment_variables/secret_volumes entry is set (allow for IAM propagation lag).
  • vpcaccess.googleapis.com enabled, or an existing Serverless VPC Access connector β€” if service_config.direct_vpc_network_interface or .vpc_connector is set.
  • cloudkms.googleapis.com enabled, the key ring/crypto key already exists, and the relevant service agents already hold roles/cloudkms.cryptoKeyEncrypterDecrypter on it β€” if kms_key_name is set.

πŸ“ Module Structure

tf-mod-gcp-cloud-function/
β”œβ”€β”€ providers.tf # required_providers (hashicorp/google ~> 7.0) + required_version β€” no provider {} block
β”œβ”€β”€ variables.tf # name, location, description, kms_key_name, deletion_policy, labels, timeouts, build_config, service_config, event_trigger
β”œβ”€β”€ main.tf # google_cloudfunctions2_function.this β€” the sole resource
β”œβ”€β”€ outputs.tf # id, url, name, state, environment, update_time, terraform_labels, effective_labels, service_uri, service_gcf_uri
β”œβ”€β”€ README.md # this file
β”œβ”€β”€ SCOPE.md # lightweight cross-module contract
└── examples/ # runnable example matching the Quick Start below

βš™οΈ Quick Start

module "hello_http" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "hello-http"
  location = "us-central1"

  build_config = {
    runtime     = "nodejs20"
    entry_point = "helloHttp"

    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "hello-http-source.zip"
      }
    }
  }
}

The caller's root module configures the google provider (project, region/zone, and authentication via ADC, Workload Identity Federation, or a service account key supplied out-of-band) β€” this module accepts none of those as variables. The staged source archive (my-project-gcf-source/hello-http-source.zip) is a caller/CI responsibility this module does not manage. The empty-beyond-required call above produces service_config.ingress_settings = ALLOW_INTERNAL_ONLY β€” the function is not reachable from the public internet by default.


πŸ”Œ Cross-Module Contract

Consumes

Input Type Source module
build_config.service_account string (plain, FULLY-QUALIFIED projects/{project}/serviceAccounts/{email}) tf-mod-gcp-service-account .id output
service_config.service_account_email string (plain, BARE email) tf-mod-gcp-service-account .email output
event_trigger.service_account_email string (plain, BARE email) tf-mod-gcp-service-account .email output
build_config.docker_repository string (plain) tf-mod-gcp-artifact-registry-repository .id output (NOT .registry_uri)
event_trigger.pubsub_topic string (plain) tf-mod-gcp-pubsub-topic .id output
service_config.secret_environment_variables[*].secret / .secret_volumes[*].secret string (plain, bare secret_id) tf-mod-gcp-secret-manager-secret (secret's own secret_id, not a module output field name β€” see example 4)
service_config.direct_vpc_network_interface.network / .subnetwork string (plain, bare NAME β€” not self_link) tf-mod-gcp-vpc-network network name output / subnetwork map key
kms_key_name string (plain) tf-mod-gcp-kms-keyring crypto key resource name

Emits

Output Description Consumed by
id projects/{{project}}/locations/{{location}}/functions/{{name}} Any module/resource needing the Terraform-internal reference (e.g. a Cloud Functions IAM binding)
url The deployed url for the function β€” this module's second primary output, in place of self_link (this resource has none) Callers of an HTTP-invoked function; informationally, tf-mod-gcp-cloud-scheduler-job's http_target.uri
name The function's name Cloud Functions IAM binding resources' cloud_function argument
state Current state of the function Diagnostic tooling
environment Always GEN_2 for this resource type Diagnostic/informational
update_time Last update timestamp Diagnostic/audit tooling
terraform_labels / effective_labels Resolved label sets Diagnostic/audit tooling
service_uri / service_gcf_uri service_config[0].uri / .gcf_uri β€” confirmed duplicates of url Consumers reading the nested path directly (e.g. Cloud Scheduler compositions)

This resource has no self_link β€” none is emitted.


πŸ“š Example Library

1 Β· Minimal HTTP-invoked function
module "hello_http" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "hello-http"
  location = "us-central1"

  build_config = {
    runtime     = "nodejs20"
    entry_point = "helloHttp"

    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "hello-http-source.zip"
      }
    }
  }
}

πŸ’‘ No event_trigger block means this function is invoked purely over HTTP via its url output. service_config.ingress_settings defaults to ALLOW_INTERNAL_ONLY.

2 Β· Publicly invocable function
module "public_webhook" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "public-webhook"
  location = "us-central1"

  build_config = {
    runtime     = "python312"
    entry_point = "handle_webhook"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "webhook-source.zip"
      }
    }
  }

  service_config = {
    ingress_settings = "ALLOW_ALL"
  }
}

⚠️ ingress_settings = "ALLOW_ALL" is the explicit opt-out this module requires for public internet exposure β€” never the default.

3 Β· Runtime identity from tf-mod-gcp-service-account
module "webhook_sa" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-service-account.git?ref=v1.0.0"

  account_id   = "webhook-runtime"
  display_name = "Webhook function runtime identity"
}

module "public_webhook" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "public-webhook"
  location = "us-central1"

  build_config = {
    runtime     = "python312"
    entry_point = "handle_webhook"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "webhook-source.zip"
      }
    }
  }

  service_config = {
    service_account_email = module.webhook_sa.email # BARE email β€” service_config wants this shape
  }
}

⚠️ service_config.service_account_email wants the BARE .email output. build_config.service_account (example 7) wants the FULLY-QUALIFIED .id output instead β€” these are two different arguments consuming two different string shapes from the same sibling module. Do not swap them.

4 Β· Pub/Sub-triggered function
module "orders_topic" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-pubsub-topic.git?ref=v1.0.0"

  name = "orders-events"
}

module "order_processor" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "order-processor"
  location = "us-central1"

  build_config = {
    runtime     = "nodejs20"
    entry_point = "processOrder"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "order-processor-source.zip"
      }
    }
  }

  service_config = {
    max_instance_count = 5
    min_instance_count = 0
  }

  event_trigger = {
    event_type   = "google.cloud.pubsub.topic.v1.messagePublished"
    pubsub_topic = module.orders_topic.id
    retry_policy = "RETRY_POLICY_RETRY"
  }
}

ℹ️ event_trigger.pubsub_topic consumes tf-mod-gcp-pubsub-topic's id output directly β€” the provider's own docs confirm this must be in PubSub's PublishRequest.name format, which is exactly this module's id output shape.

5 Β· GCS/Eventarc-triggered function with event_filters
module "uploads_processor" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "uploads-processor"
  location = "us-central1"

  build_config = {
    runtime     = "python312"
    entry_point = "process_upload"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "uploads-processor-source.zip"
      }
    }
  }

  service_config = {
    service_account_email = "gcf-events-sa@my-project.iam.gserviceaccount.com"
  }

  event_trigger = {
    event_type            = "google.cloud.storage.object.v1.finalized"
    retry_policy          = "RETRY_POLICY_RETRY"
    service_account_email = "gcf-events-sa@my-project.iam.gserviceaccount.com"
    event_filters = {
      "bucket" = { value = "my-uploads-trigger-bucket" }
    }
  }
}

πŸ”’ The GCS service account requires roles/pubsub.publisher and the trigger service account requires roles/eventarc.eventReceiver + roles/run.invoker β€” grant these via tf-mod-gcp-project-iam-bindings before this function's first successful deploy (see Troubleshooting for the doc-confirmed IAM propagation pattern).

6 Β· Audit-log-triggered function with a path-pattern filter
module "audit_watcher" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "audit-watcher"
  location = "us-central1"

  build_config = {
    runtime     = "python312"
    entry_point = "watch_audit_log"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "audit-watcher-source.zip"
      }
    }
  }

  event_trigger = {
    trigger_region = "us-central1" # must match the audited bucket's location
    event_type     = "google.cloud.audit.log.v1.written"
    retry_policy   = "RETRY_POLICY_RETRY"

    event_filters = {
      "serviceName" = { value = "storage.googleapis.com" }
      "methodName"  = { value = "storage.objects.create" }
      "resourceName" = {
        value    = "/projects/_/buckets/my-audit-log-bucket/objects/*.txt"
        operator = "match-path-pattern"
      }
    }
  }
}

ℹ️ event_filters is keyed by CloudEvents attribute name β€” matching the provider's own "Basic Auditlogs" example, which keys three filters by serviceName/methodName/resourceName. operator = "match-path-pattern" is the only accepted value when set (enforced via this module's validation {} block).

7 Β· Custom build service account
module "builder_sa" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-service-account.git?ref=v1.0.0"

  account_id   = "gcf-builder"
  display_name = "Cloud Function build identity"
}

module "hello_http" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "hello-http"
  location = "us-central1"

  build_config = {
    runtime     = "nodejs20"
    entry_point = "helloHttp"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "hello-http-source.zip"
      }
    }
    service_account = module.builder_sa.id # FULLY-QUALIFIED β€” build_config wants this shape
  }
}

⚠️ build_config.service_account wants the FULLY-QUALIFIED projects/{project}/serviceAccounts/{email} form β€” confirmed via the provider's own "Basic Builder" example (service_account = google_service_account.account.id). This is the account's .id output, not .email β€” the opposite shape from example 3's service_config.service_account_email.

8 Β· Custom docker_repository (Artifact Registry)
module "functions_repo" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-artifact-registry-repository.git?ref=v1.0.0"

  repository_id = "gcf-functions"
  location      = "us-central1"
  format        = "DOCKER"
}

module "hello_http" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "hello-http"
  location = "us-central1"

  build_config = {
    runtime           = "nodejs20"
    entry_point       = "helloHttp"
    docker_repository = module.functions_repo.id # id, NOT registry_uri
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "hello-http-source.zip"
      }
    }
  }
}

ℹ️ Omitting docker_repository entirely is normal β€” GCF creates and manages its own default repository (gcf-artifacts) in the function's region. docker_repository consumes .id, not .registry_uri (the latter is tf-mod-gcp-artifact-registry-repository's own self_link substitute for CI pipelines building/pushing images directly β€” this argument wants the Terraform resource reference form instead).

9 Β· Secret-sourced environment variable
module "db_password" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-secret-manager-secret.git?ref=v1.0.0"

  secret_id   = "order-processor-db-password"
  replication = { auto = {} }
}

module "order_processor" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "order-processor"
  location = "us-central1"

  build_config = {
    runtime     = "nodejs20"
    entry_point = "processOrder"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "order-processor-source.zip"
      }
    }
  }

  service_config = {
    secret_environment_variables = {
      "DB_PASSWORD" = {
        project_id = "my-project"
        secret     = "order-processor-db-password" # bare secret_id, as supplied above β€” not a module output
        version    = "latest"
      }
    }
  }
}

πŸ”’ The runtime service account must hold roles/secretmanager.secretAccessor on this secret β€” grant it via tf-mod-gcp-project-iam-bindings (see the end-to-end composition, example 15). This module only wires the reference; it does not grant access.

10 Β· Secret mounted as a volume
module "tls_cert" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-secret-manager-secret.git?ref=v1.0.0"

  secret_id   = "order-processor-tls-cert"
  replication = { auto = {} }
}

module "order_processor" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "order-processor"
  location = "us-central1"

  build_config = {
    runtime     = "nodejs20"
    entry_point = "processOrder"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "order-processor-source.zip"
      }
    }
  }

  service_config = {
    secret_volumes = {
      "/etc/secrets/tls" = {
        project_id = "my-project"
        secret     = "order-processor-tls-cert"
        versions   = []
      }
    }
  }
}

ℹ️ secret_volumes is keyed by mount_path β€” the field that must be unique across volumes. Omitting versions (the default, []) mounts the latest version under a file named after the secret.

11 Β· Direct VPC egress via a subnetwork name
module "network" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-vpc-network.git?ref=v1.0.0"

  network_name = "workloads-network"
  subnetworks = {
    "functions-subnet-usc1" = {
      ip_cidr_range = "10.6.0.0/28"
      region        = "us-central1"
    }
  }
}

module "order_processor" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "order-processor"
  location = "us-central1"

  build_config = {
    runtime     = "nodejs20"
    entry_point = "processOrder"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "order-processor-source.zip"
      }
    }
  }

  service_config = {
    direct_vpc_network_interface = {
      network    = module.network.name     # bare NAME, not self_link
      subnetwork = "functions-subnet-usc1" # the map key used above β€” also a bare NAME
    }
    direct_vpc_egress = "VPC_EGRESS_PRIVATE_RANGES_ONLY"
  }
}

⚠️ CONFIRMED DEVIATION from tf-mod-gcp-cloud-run-service: direct_vpc_network_interface.network/ .subnetwork take bare NAME strings, not self_link. Do not wire module.network.subnetwork_self_links[...] here β€” use the literal subnetwork name (the same string used as the subnetworks map key when calling tf-mod-gcp-vpc-network).

12 Β· Legacy Serverless VPC Access connector egress
module "legacy_integration" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "legacy-integration"
  location = "us-central1"

  build_config = {
    runtime     = "python312"
    entry_point = "handle_legacy_call"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "legacy-integration-source.zip"
      }
    }
  }

  service_config = {
    vpc_connector                 = "projects/my-project/locations/us-central1/connectors/run-vpc"
    vpc_connector_egress_settings = "PRIVATE_RANGES_ONLY"
  }
}

⚠️ vpc_connector (legacy) and direct_vpc_network_interface (modern, example 11) are alternative paths on the same service_config block β€” this module does not validate mutual exclusivity; supplying both is a caller error the GCP API itself will reject. No tf-mod-gcp-vpc-access-connector sibling module exists in the current catalog.

13 Β· CMEK (customer-managed encryption key)
module "cmek_function" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name         = "cmek-function"
  location     = "us-central1"
  kms_key_name = "projects/my-project/locations/us-central1/keyRings/gcf-keyring/cryptoKeys/gcf-key"

  build_config = {
    runtime     = "nodejs20"
    entry_point = "helloHttp"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "hello-http-source.zip"
      }
    }
  }
}

⚠️ Confirmed GA on hashicorp/google ~> 7.0 during this module's authoring session β€” see Architecture Notes for the full google-beta ambiguity resolution. The GCF/Artifact Registry/Cloud Storage/Eventarc service agents must already hold roles/cloudkms.cryptoKeyEncrypterDecrypter on this key before the first apply (IAM propagation lag applies here too) β€” a live plan/apply check against a real project is still recommended before relying on this in production.

14 Β· Custom scaling, memory, and concurrency
module "high_throughput_processor" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "high-throughput-processor"
  location = "us-central1"

  build_config = {
    runtime     = "python312"
    entry_point = "process_batch"
    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "high-throughput-processor-source.zip"
      }
    }
  }

  service_config = {
    available_memory                 = "4Gi"
    available_cpu                    = "4"
    max_instance_request_concurrency = 80
    max_instance_count               = 20
    min_instance_count               = 1
    timeout_seconds                  = 300
  }
}

ℹ️ Per the live docs, available_cpu is computed from available_memory when left unset β€” set it explicitly (as here) when concurrency needs more CPU per instance than the memory-derived default would provide.

15 Β· πŸ—οΈ End-to-end composition
module "project_services" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-project-services.git?ref=v1.0.0"

  # Enables cloudfunctions.googleapis.com, run.googleapis.com,
  # cloudbuild.googleapis.com, artifactregistry.googleapis.com,
  # eventarc.googleapis.com, secretmanager.googleapis.com, and any other
  # APIs this composition needs.
}

module "gcf_build_sa" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-service-account.git?ref=v1.0.0"

  account_id   = "gcf-order-builder"
  display_name = "Order processor build identity"

  depends_on = [module.project_services]
}

module "gcf_runtime_sa" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-service-account.git?ref=v1.0.0"

  account_id   = "gcf-order-runtime"
  display_name = "Order processor runtime + event-trigger identity"

  depends_on = [module.project_services]
}

module "functions_repo" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-artifact-registry-repository.git?ref=v1.0.0"

  repository_id = "gcf-functions"
  location      = "us-central1"
  format        = "DOCKER"

  depends_on = [module.project_services]
}

module "orders_topic" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-pubsub-topic.git?ref=v1.0.0"

  name = "orders-events"

  depends_on = [module.project_services]
}

module "network" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-vpc-network.git?ref=v1.0.0"

  network_name = "workloads-network"
  subnetworks = {
    "functions-subnet-usc1" = {
      ip_cidr_range = "10.6.0.0/28"
      region        = "us-central1"
    }
  }

  depends_on = [module.project_services]
}

module "db_password" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-secret-manager-secret.git?ref=v1.0.0"

  secret_id   = "order-processor-db-password"
  replication = { auto = {} }

  depends_on = [module.project_services]
}

module "order_processor_iam" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-project-iam-bindings.git?ref=v1.0.0"

  bindings = {
    "gcf-builder-log-writer" = {
      role   = "roles/logging.logWriter"
      member = module.gcf_build_sa.member
    }
    "gcf-builder-ar-writer" = {
      role   = "roles/artifactregistry.writer"
      member = module.gcf_build_sa.member
    }
    "gcf-runtime-secret-accessor" = {
      role   = "roles/secretmanager.secretAccessor"
      member = module.gcf_runtime_sa.member
    }
    "gcf-runtime-eventarc-receiver" = {
      role   = "roles/eventarc.eventReceiver"
      member = module.gcf_runtime_sa.member
    }
    "gcf-runtime-run-invoker" = {
      role   = "roles/run.invoker"
      member = module.gcf_runtime_sa.member
    }
  }
}

module "order_processor" {
  source = "git::https://github.com/microsoftexpert/tf-mod-gcp-cloud-function.git?ref=v1.0.0"

  name     = "order-processor"
  location = "us-central1"

  build_config = {
    runtime           = "nodejs20"
    entry_point       = "processOrder"
    docker_repository = module.functions_repo.id # id, NOT registry_uri
    service_account   = module.gcf_build_sa.id   # FULLY-QUALIFIED β€” build_config's shape

    source = {
      storage_source = {
        bucket = "my-project-gcf-source"
        object = "order-processor-source.zip"
      }
    }
  }

  service_config = {
    service_account_email = module.gcf_runtime_sa.email # BARE email β€” service_config's shape

    max_instance_count = 10
    min_instance_count = 0

    direct_vpc_network_interface = {
      network    = module.network.name
      subnetwork = "functions-subnet-usc1" # bare NAME β€” the subnetworks map key above, not self_link
    }

    secret_environment_variables = {
      "DB_PASSWORD" = {
        project_id = "my-project"
        secret     = "order-processor-db-password" # module.db_password's secret_id, as supplied
        version    = "latest"
      }
    }
  }

  event_trigger = {
    event_type            = "google.cloud.pubsub.topic.v1.messagePublished"
    pubsub_topic          = module.orders_topic.id
    service_account_email = module.gcf_runtime_sa.email # BARE email β€” event_trigger's shape too
    retry_policy          = "RETRY_POLICY_RETRY"
  }

  depends_on = [
    module.gcf_build_sa,
    module.gcf_runtime_sa,
    module.functions_repo,
    module.orders_topic,
    module.network,
    module.db_password,
    module.order_processor_iam,
  ]
}

πŸ’‘ This wires the full dependency chain in order: APIs enabled, then identities/repository/ topic/network/secret created in parallel, then IAM grants, then the function itself β€” with an explicit depends_on on the IAM bindings so the build/runtime service accounts' roles have a chance to propagate before the function's first apply builds and deploys.

⚠️ IAM propagation can still take up to ~60 seconds even with correct graph ordering β€” the provider's own "Basic Builder" example inserts an explicit 60-second time_sleep for exactly this reason. A first-time apply of this composition may need a second apply if the build fails to pull the source or the runtime fails to read the secret. See Troubleshooting.


πŸ“₯ Inputs

Variable Type Required Default Notes
name string Yes β€” Embedded in the resource id path; treat as effectively force-new
location string Yes β€” Resource-level required argument, not a provider override
description string No null No stated character limit in the live docs
kms_key_name string No null CMEK; confirmed GA β€” see Architecture Notes; format-validated
deletion_policy string No "DELETE" DELETE | ABANDON | PREVENT; only deletion guard this resource has (no deletion_protection)
labels map(string) No {} GCP label-format validated; non-authoritative per the live docs
timeouts object({create,update,delete}) No null All three supported; each defaults to 60m
build_config object({...}) No null Build step; omitting it entirely produces a function with no deployable code
service_config object({...}) No {} Runtime configuration; every field defaulted, so {} is a complete, secure-by-default object
event_trigger object({...}) No null Eventarc trigger; absence = pure HTTP-invoked function
Full variable schemas
variable "name" {
  type = string
}

variable "location" {
  type = string
}

variable "description" {
  type    = string
  default = null
}

variable "kms_key_name" {
  type    = string
  default = null
  # must match projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}
  # β€” enforced via validation {}
}

variable "deletion_policy" {
  type    = string
  default = "DELETE" # DELETE | ABANDON | PREVENT
}

variable "labels" {
  type    = map(string)
  default = {}
  # GCP label key/value format enforced via validation {}
}

variable "timeouts" {
  type = object({
    create = optional(string)
    update = optional(string)
    delete = optional(string)
  })
  default = null
}

variable "build_config" {
  type = object({
    runtime                 = optional(string)
    entry_point             = optional(string)
    worker_pool             = optional(string)
    environment_variables   = optional(map(string), {})
    docker_repository       = optional(string)
    service_account         = optional(string)      # FULLY-QUALIFIED projects/{project}/serviceAccounts/{email}
    automatic_update_policy = optional(bool, false) # mutually exclusive with on_deploy_update_policy
    on_deploy_update_policy = optional(bool, false)

    source = optional(object({
      storage_source = optional(object({
        bucket     = optional(string)
        object     = optional(string)
        generation = optional(number)
      }))
      repo_source = optional(object({
        project_id   = optional(string)
        repo_name    = optional(string)
        branch_name  = optional(string)
        tag_name     = optional(string)
        commit_sha   = optional(string)
        dir          = optional(string)
        invert_regex = optional(bool)
      }))
    }))
  })
  default = null
}

variable "service_config" {
  type = object({
    timeout_seconds                  = optional(number, 60)
    available_memory                 = optional(string, "256M")
    available_cpu                    = optional(string)
    max_instance_request_concurrency = optional(number, 1)
    environment_variables            = optional(map(string), {})
    max_instance_count               = optional(number)
    min_instance_count               = optional(number)

    vpc_connector                 = optional(string)
    vpc_connector_egress_settings = optional(string) # VPC_CONNECTOR_EGRESS_SETTINGS_UNSPECIFIED | PRIVATE_RANGES_ONLY | ALL_TRAFFIC

    direct_vpc_network_interface = optional(object({
      network    = optional(string) # bare NAME, not self_link
      subnetwork = optional(string) # bare NAME, not self_link
      tags       = optional(list(string), [])
    }))
    direct_vpc_egress = optional(string) # VPC_EGRESS_ALL_TRAFFIC | VPC_EGRESS_PRIVATE_RANGES_ONLY

    ingress_settings = optional(string, "ALLOW_INTERNAL_ONLY") # secure-by-default extension

    service_account_email          = optional(string) # BARE email
    all_traffic_on_latest_revision = optional(bool, true)

    secret_environment_variables = optional(map(object({ # keyed by env var name
      project_id = string
      secret     = string
      version    = string
    })), {})

    secret_volumes = optional(map(object({ # keyed by mount_path
      project_id = string
      secret     = string
      versions = optional(list(object({
        version = string
        path    = string
      })), [])
    })), {})

    binary_authorization_policy = optional(string)
  })
  default = {}
}

variable "event_trigger" {
  type = object({
    trigger_region        = optional(string)
    event_type            = string # Required if event_trigger is present at all
    pubsub_topic          = optional(string)
    service_account_email = optional(string) # BARE email
    retry_policy          = optional(string) # RETRY_POLICY_UNSPECIFIED | RETRY_POLICY_DO_NOT_RETRY | RETRY_POLICY_RETRY

    event_filters = optional(map(object({ # keyed by CloudEvents attribute name
      value    = string
      operator = optional(string) # only "match-path-pattern" accepted when set
    })), {})
  })
  default = null
}

🧾 Outputs

Output Description
id projects/{{project}}/locations/{{location}}/functions/{{name}}
url The deployed url for the function β€” second primary output, in place of self_link
name The function's name
state Current state of the function
environment Always GEN_2 for this resource type
update_time Last update timestamp
terraform_labels / effective_labels Resolved label sets
service_uri / service_gcf_uri service_config[0].uri / .gcf_uri β€” confirmed duplicates of url

ℹ️ Deviation from the house id/self_link convention, confirmed during authoring: the live Attributes Reference for google_cloudfunctions2_function has no self_link attribute. This module's primary_output is id first, then url in its place. Separately, service_config[0].uri and service_config[0].gcf_uri are two additional, distinct attribute paths expected to carry the same underlying value as url β€” a confirmed, documented duplication, exposed here as service_uri/service_gcf_uri so a future maintainer does not "fix" it as a bug.

None of these outputs are secret-bearing; no sensitive = true is applied to any of them. Secret Manager references (secret_environment_variables/secret_volumes) are write-only inputs β€” never echoed back as outputs.


🧠 Architecture Notes

  • id then url, not id then self_link. Confirmed via the live schema: this resource has no self_link attribute. url ("The deployed url for the function") is the closest analog and is this module's second primary output β€” a deliberate, documented deviation from the house convention, not an oversight.
  • url, service_config[0].uri, and service_config[0].gcf_uri are three distinct attribute paths confirmed to carry substantially the same deployed URL. The provider's own "Cloudfunctions2 Scheduler Auth" example specifically reads service_config[0].uri rather than the top-level url β€” both are populated with the same URL, but a future maintainer should not "simplify" this module by removing the apparent redundancy; all three are exposed as distinct outputs precisely so consumers can pick whichever path a given sibling composition's own examples reference.
  • Three distinct service-account-consuming arguments, two distinct string shapes. build_config.service_account wants the FULLY-QUALIFIED projects/{project}/serviceAccounts/{email} form (tf-mod-gcp-service-account's .id output); service_config.service_account_email and event_trigger.service_account_email both want the BARE email string (the same module's .email output). This is the single most common cross-module wiring mistake this README's examples exist to forestall.
  • direct_vpc_network_interface.network/.subnetwork take bare NAME strings, not self_link/id. A confirmed deviation from tf-mod-gcp-cloud-run-service's vpc_access.network_interfaces precedent, which takes a subnetwork self_link. Wire the literal name β€” the same string used as the subnetworks map key when calling tf-mod-gcp-vpc-network β€” not a self_link/id output.
  • This module does not manage the source archive. build_config.source.storage_source/ .repo_source reference already-staged source coordinates only β€” the caller/CI pipeline owns the archive's contents and its upload to GCS or a Cloud Source Repository. This module never creates a google_storage_bucket_object.
  • No deletion_protection exists on this resource. Confirmed absent from the live schema β€” a gap versus tf-mod-gcp-cloud-run-service. deletion_policy (Terraform-only, default DELETE) is the only guard available; set it to "PREVENT" explicitly for a stronger destroy guard, understanding that it is not an API-enforced guard the way deletion_protection is on sibling modules.
  • IAM propagation delay is doc-confirmed for this specific resource. The provider's own "Basic Builder" example inserts a 60-second time_sleep before the function can build ("builder permissions need to stabilize before it can pull the source zip"); the "Basic Gcs"/"Basic Auditlogs" examples chain IAM grants via depends_on before the function/trigger resource. Cite this as resource-specific, doc-confirmed evidence for this module suite's general ~60-second IAM propagation note β€” a first apply failing on a fresh IAM grant is expected behavior, not a module bug.
  • kms_key_name (CMEK) google-beta ambiguity β€” resolved. The only official worked example end-to-end sets provider = google-beta on every resource, including google_cloudfunctions2_function itself β€” but that example also provisions a google_project_service_identity resource, and the live provider schema for that resource (provider_doc_id 12684073) confirms an explicit warning: "These resources are in beta, and should be used with the terraform-provider-google-beta provider." google_cloudfunctions2_function's own doc page carries no such warning, and kms_key_name is listed as a plain Optional argument with no beta annotation. Conclusion: the google-beta provider tag in that example is attributable to the co-located service-identity lookup, not to any beta requirement on kms_key_name itself. Treated as GA here β€” a live plan/apply check is still recommended before production use, per this library's general plan-only posture (which cannot catch apply-time KMS/IAM rejections regardless of GA-vs-beta status).
  • secret_environment_variables/secret_volumes modeled as map(object(...)), not the provider's own repeatable-block-with-a-key/mount_path shape. secret_environment_variables is keyed by environment variable name; secret_volumes is keyed by mount_path (the field that must be unique across volumes) β€” the house for_each-over-a-keyed-map pattern applied to these two nested collections.
  • automatic_update_policy/on_deploy_update_policy are two mutually-exclusive, zero-argument nested blocks in the live schema, represented here as two boolean flags rather than two empty object types β€” this module's own validation {} block rejects setting both true.

🧱 Design Principles

Concern Secure default Opt-out (explicit)
Ingress / public exposure service_config.ingress_settings = "ALLOW_INTERNAL_ONLY" (extension to this module suite's house table of secure defaults β€” this resource has no pre-existing row there; provider's own default if unmanaged is ALLOW_ALL) Caller sets ingress_settings = "ALLOW_ALL" explicitly
Deletion guard N/A β€” this resource exposes no deletion_protection boolean (confirmed absent from the live schema); deletion_policy (Terraform-only, default DELETE) is the only guard available Caller sets deletion_policy = "PREVENT" explicitly for a stronger (Terraform-only) destroy guard
CMEK for function resources kms_key_name accepted as an optional variable, never defaulted to a specific key Caller supplies a tf-mod-gcp-kms-keyring crypto key resource name
Service account key material This module never creates a service account or key β€” all three identity arguments are plain strings consumed from tf-mod-gcp-service-account N/A β€” use Workload Identity Federation or a dedicated service account module
Secrets in configuration Env/volume secret references are Secret Manager secret/project_id/version string pointers only β€” this module never accepts or stores a literal secret value N/A β€” literal secret values are out of scope by design
VPC egress identity direct_vpc_network_interface/vpc_connector both accepted as plain strings; neither defaults to a specific network Caller supplies the subnetwork/connector explicitly to opt into VPC egress at all
Source deployment This module never manages the source archive's contents or upload β€” a caller/CI pipeline responsibility by design N/A β€” out of scope; see Architecture Notes

πŸš€ Runbook

cd tf-mod-gcp-cloud-function
terraform init -backend=false
terraform validate
terraform fmt -check

Pin the module source to ?ref=v1.0.0 β€” never a branch. This library is plan-only from an authoring session; a human applies from CI with valid Workload Identity Federation or ADC credentials.


πŸ§ͺ Testing

terraform validate confirms internal type and reference consistency β€” every validation {} block (deletion_policy/ingress_settings/vpc_connector_egress_settings/direct_vpc_egress/ retry_policy/event_filters[*].operator enums, kms_key_name format, label format, the automatic_update_policy/on_deploy_update_policy mutual-exclusivity check) runs at plan time, before any API call. terraform fmt -check confirms canonical formatting. Neither can catch GCP API-level rejections this module cannot see in advance: a malformed event_trigger/event_filters combination the Eventarc API itself rejects, an invalid or inaccessible docker_repository reference, quota limits, IAM propagation lag on the build/runtime/trigger service accounts, or the kms_key_name google-beta ambiguity this session resolved via documentation cross-checking rather than a live apply β€” only a real terraform plan/apply against a live project, with valid credentials, exercises those paths. That step belongs to the consuming CI pipeline, not this authoring session.


πŸ’¬ Example Output

$ terraform output

effective_labels = {
 "goog-terraform-provisioned" = "true"
}
environment = "GEN_2"
id = "projects/casey-prod-workloads/locations/us-central1/functions/order-processor"
name = "order-processor"
service_gcf_uri = "https://order-processor-abcdefghij-uc.a.run.app"
service_uri = "https://order-processor-abcdefghij-uc.a.run.app"
state = "ACTIVE"
terraform_labels = {
 "goog-terraform-provisioned" = "true"
}
update_time = "2026-07-11T18:42:03Z"
url = "https://order-processor-abcdefghij-uc.a.run.app"

πŸ” Troubleshooting

Symptom Cause Fix
apply fails immediately after granting a build/runtime IAM role, with a permission-denied error building or invoking the function IAM propagation lag (up to ~60 seconds) β€” doc-confirmed for this resource via the provider's own "Basic Builder" time_sleep pattern Re-run apply; consider an explicit depends_on plus a short delay (or a time_sleep resource) for first-time bring-up
plan/apply rejects a service-account-shaped string with an invalid-format error Wrong string shape supplied β€” build_config.service_account wants the FULLY-QUALIFIED projects/{project}/serviceAccounts/{email} form, while service_config.service_account_email/event_trigger.service_account_email want the BARE email Swap to the correct tf-mod-gcp-service-account output (.id for build_config.service_account; .email for the other two)
Function builds but the container image pull or push to Artifact Registry fails with a permission error The build service account (or GCF's own default builder identity) lacks roles/artifactregistry.writer on the target docker_repository, or roles/artifactregistry.reader at runtime Grant the missing role via tf-mod-gcp-project-iam-bindings or a resource-scoped Artifact Registry IAM binding
Function is reachable from the public internet unexpectedly ingress_settings left at its secure default is fine β€” this symptom means a caller explicitly set ingress_settings = "ALLOW_ALL" without intending public exposure Review the composition for an explicit override; revert to "ALLOW_INTERNAL_ONLY" (or "ALLOW_INTERNAL_AND_GCLB") if public exposure was not intended
Event-triggered function never fires Missing roles/eventarc.eventReceiver/roles/run.invoker on the trigger service account, or (for GCS triggers) missing roles/pubsub.publisher on the GCS service agent Grant the missing roles; confirm via gcloud eventarc triggers describe that the underlying Eventarc trigger (this resource's trigger output-only attribute) exists and is healthy
apply with kms_key_name set fails with a KMS permission error The GCF/Artifact Registry/Cloud Storage/Eventarc service agents have not been granted roles/cloudkms.cryptoKeyEncrypterDecrypter on the referenced key, or IAM propagation has not yet completed Grant the role to all relevant service agents before the first apply; allow for propagation lag; if the error persists, treat it as evidence for re-checking the google-beta resolution documented in Architecture Notes against a live plan
terraform destroy fails even after setting deletion_policy = "ABANDON"/"PREVENT" reviewed This resource has no deletion_protection β€” a "PREVENT" deletion_policy blocks Terraform itself, but check for an out-of-band GCP-side lock (e.g. an org policy) if the failure is unexpected Set deletion_policy = "DELETE" explicitly if destruction is intended; investigate org-policy constraints if not

πŸ”— Related Docs

  • google_cloudfunctions2_function provider resource reference
  • tf-mod-gcp-service-account (build/runtime/event-trigger identity source β€” three arguments, two string shapes)
  • tf-mod-gcp-artifact-registry-repository (build output destination for build_config.docker_repository)
  • tf-mod-gcp-pubsub-topic (event trigger source for event_trigger.pubsub_topic)
  • tf-mod-gcp-secret-manager-secret (secret source for env/volume secret references)
  • tf-mod-gcp-vpc-network (subnetwork NAME source for direct VPC egress)
  • tf-mod-gcp-kms-keyring (CMEK crypto key source for kms_key_name)
  • tf-mod-gcp-project-iam-bindings (grants the build/runtime/trigger service accounts' roles)
  • tf-mod-gcp-project-services (must enable the unconditional + conditional APIs before this module applies)
  • tf-mod-gcp-cloud-scheduler-job (informational consumer of this module's url output)
  • tf-mod-gcp-cloud-run-service (sibling Cloud-Run-backed compute module; compare its self_link-based VPC egress precedent against this module's name-based one)
  • This module's SCOPE.md

Packages

 
 
 

Contributors

Languages