From d9029e47a0c8bd3db1affcfc79fbfe65e3c9c3dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Niesiob=C4=99dzki?= Date: Mon, 20 Oct 2025 21:46:11 +0000 Subject: [PATCH] VPC Connector alignment to Cloud Run v2 + contexts --- modules/cloud-function-v1/README.md | 86 ++++++++++++++++++- modules/cloud-function-v1/main.tf | 62 ++++--------- .../variables-vpcconnector.tf | 59 +++++++++++++ modules/cloud-function-v1/variables.tf | 36 -------- modules/cloud-function-v1/vpcconnector.tf | 74 ++++++++++++++++ modules/cloud-function-v2/README.md | 86 ++++++++++++++++++- modules/cloud-function-v2/main.tf | 62 ++++--------- .../variables-vpcconnector.tf | 59 +++++++++++++ modules/cloud-function-v2/variables.tf | 36 -------- modules/cloud-function-v2/vpcconnector.tf | 74 ++++++++++++++++ modules/cloud-run-v2/README.md | 2 +- tests/fixtures/vpc-connector.tf | 2 +- .../context-subnet-project.tfvars | 58 +++++++++++++ .../context-subnet-project.yaml | 61 +++++++++++++ .../cloud_function_v1/context-subnet.tfvars | 57 ++++++++++++ .../cloud_function_v1/context-subnet.yaml | 60 +++++++++++++ .../modules/cloud_function_v1/context.tfvars | 2 +- tests/modules/cloud_function_v1/context.yaml | 2 +- ...vpc-access-connector-create-sharedvpc.yaml | 68 +++++++++++++++ .../service-vpc-access-connector-create.yaml | 56 ++++++++++++ .../service-vpc-access-connector.yaml | 56 ++++++++++++ tests/modules/cloud_function_v1/tftest.yaml | 2 + .../context-subnet-project.tfvars | 58 +++++++++++++ .../context-subnet-project.yaml | 64 ++++++++++++++ .../cloud_function_v2/context-subnet.tfvars | 57 ++++++++++++ .../cloud_function_v2/context-subnet.yaml | 62 +++++++++++++ .../modules/cloud_function_v2/context.tfvars | 56 ++++++++++++ tests/modules/cloud_function_v2/context.yaml | 61 +++++++++++++ ...vpc-access-connector-create-sharedvpc.yaml | 73 ++++++++++++++++ .../service-vpc-access-connector-create.yaml | 62 +++++++++++++ .../service-vpc-access-connector.yaml | 62 +++++++++++++ tests/modules/cloud_function_v2/kms.tfvars | 9 ++ tests/modules/cloud_function_v2/kms.yaml | 44 ++++++++++ tests/modules/cloud_function_v2/tftest.yaml | 21 +++++ .../cloud_function_v2/vpcconnector.tfvars | 11 +++ .../cloud_function_v2/vpcconnector.yaml | 44 ++++++++++ .../service-vpc-access-connector.yaml | 3 +- tools/duplicate-diff.py | 14 ++- 38 files changed, 1588 insertions(+), 173 deletions(-) create mode 100644 modules/cloud-function-v1/variables-vpcconnector.tf create mode 100644 modules/cloud-function-v1/vpcconnector.tf create mode 100644 modules/cloud-function-v2/variables-vpcconnector.tf create mode 100644 modules/cloud-function-v2/vpcconnector.tf create mode 100644 tests/modules/cloud_function_v1/context-subnet-project.tfvars create mode 100644 tests/modules/cloud_function_v1/context-subnet-project.yaml create mode 100644 tests/modules/cloud_function_v1/context-subnet.tfvars create mode 100644 tests/modules/cloud_function_v1/context-subnet.yaml create mode 100644 tests/modules/cloud_function_v1/examples/service-vpc-access-connector-create-sharedvpc.yaml create mode 100644 tests/modules/cloud_function_v1/examples/service-vpc-access-connector-create.yaml create mode 100644 tests/modules/cloud_function_v1/examples/service-vpc-access-connector.yaml create mode 100644 tests/modules/cloud_function_v2/context-subnet-project.tfvars create mode 100644 tests/modules/cloud_function_v2/context-subnet-project.yaml create mode 100644 tests/modules/cloud_function_v2/context-subnet.tfvars create mode 100644 tests/modules/cloud_function_v2/context-subnet.yaml create mode 100644 tests/modules/cloud_function_v2/context.tfvars create mode 100644 tests/modules/cloud_function_v2/context.yaml create mode 100644 tests/modules/cloud_function_v2/examples/service-vpc-access-connector-create-sharedvpc.yaml create mode 100644 tests/modules/cloud_function_v2/examples/service-vpc-access-connector-create.yaml create mode 100644 tests/modules/cloud_function_v2/examples/service-vpc-access-connector.yaml create mode 100644 tests/modules/cloud_function_v2/kms.tfvars create mode 100644 tests/modules/cloud_function_v2/kms.yaml create mode 100644 tests/modules/cloud_function_v2/tftest.yaml create mode 100644 tests/modules/cloud_function_v2/vpcconnector.tfvars create mode 100644 tests/modules/cloud_function_v2/vpcconnector.yaml diff --git a/modules/cloud-function-v1/README.md b/modules/cloud-function-v1/README.md index 47baab320..158522750 100644 --- a/modules/cloud-function-v1/README.md +++ b/modules/cloud-function-v1/README.md @@ -15,6 +15,7 @@ Cloud Function management, with support for IAM roles, optional bucket creation - [Multiple Cloud Functions within project](#multiple-cloud-functions-within-project) - [Mounting secrets from Secret Manager](#mounting-secrets-from-secret-manager) - [Using CMEK to encrypt function resources](#using-cmek-to-encrypt-function-resources) +- [VPC Access Connector](#vpc-access-connector) - [Variables](#variables) - [Outputs](#outputs) - [Fixtures](#fixtures) @@ -393,6 +394,85 @@ module "cf-http" { } # tftest inventory=cmek.yaml ``` + +## VPC Access Connector + +You can use an existing [VPC Access Connector](https://cloud.google.com/vpc/docs/serverless-vpc-access) to connect to a VPC from Cloud Run. + +```hcl +module "cf_http" { + source = "./fabric/modules/cloud-function-v1" + project_id = var.project_id + region = var.region + name = "test-cf-http" + bucket_name = var.bucket + bundle_config = { + path = "assets/sample-function/" + } + vpc_connector = { + name = google_vpc_access_connector.connector.id + egress_setting = "ALL_TRAFFIC" + } +} +# tftest fixtures=fixtures/vpc-connector.tf inventory=service-vpc-access-connector.yaml e2e +``` + +If creation of the VPC Access Connector is required, use the `vpc_connector.create` and `vpc_connector_create` variable which also supports optional attributes like number of instances, machine type, or throughput. + +```hcl +module "cf_http" { + source = "./fabric/modules/cloud-function-v1" + project_id = var.project_id + region = var.region + name = "test-cf-http" + bucket_name = var.bucket + bundle_config = { + path = "assets/sample-function/" + } + vpc_connector = { + create = true + } + vpc_connector_create = { + ip_cidr_range = "10.10.10.0/28" + network = var.vpc.self_link + instances = { + max = 10 + min = 3 + } + } +} +# tftest inventory=service-vpc-access-connector-create.yaml e2e +``` + +Note that if you are using a Shared VPC for the connector, you need to specify a subnet and the host project if this is not where the Cloud Run service is deployed. + +```hcl +module "cf_http" { + source = "./fabric/modules/cloud-function-v1" + project_id = var.project_id + region = var.region + name = "test-cf-http" + bucket_name = var.bucket + bundle_config = { + path = "assets/sample-function/" + } + vpc_connector = { + create = true + } + vpc_connector_create = { + machine_type = "e2-standard-4" + subnet = { + name = module.net-vpc-host.subnets["${var.region}/fixture-subnet-28"].name + project_id = module.project-host.project_id + } + throughput = { + max = 300 + min = 200 + } + } +} +# tftest fixtures=fixtures/shared-vpc.tf inventory=service-vpc-access-connector-create-sharedvpc.yaml e2e +``` ## Variables @@ -420,8 +500,8 @@ module "cf-http" { | [secrets](variables.tf#L194) | Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format. | map(object({…})) | | {} | | [service_account_config](variables-serviceaccount.tf#L17) | Service account configurations. | object({…}) | | {} | | [trigger_config](variables.tf#L206) | Function trigger configuration. Leave null for HTTP trigger. | object({…}) | | null | -| [vpc_connector](variables.tf#L216) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | {} | -| [vpc_connector_config](variables.tf#L227) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null | +| [vpc_connector](variables-vpcconnector.tf#L17) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | {} | +| [vpc_connector_create](variables-vpcconnector.tf#L28) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null | ## Outputs @@ -443,4 +523,6 @@ module "cf-http" { - [cloudbuild-custom-pool.tf](../../tests/fixtures/cloudbuild-custom-pool.tf) - [functions-default-sa-iam-grants.tf](../../tests/fixtures/functions-default-sa-iam-grants.tf) - [pubsub.tf](../../tests/fixtures/pubsub.tf) +- [shared-vpc.tf](../../tests/fixtures/shared-vpc.tf) +- [vpc-connector.tf](../../tests/fixtures/vpc-connector.tf) diff --git a/modules/cloud-function-v1/main.tf b/modules/cloud-function-v1/main.tf index 5d215226c..4c6cc0f07 100644 --- a/modules/cloud-function-v1/main.tf +++ b/modules/cloud-function-v1/main.tf @@ -30,36 +30,10 @@ locals { : null ) ) - location = lookup(local.ctx.locations, var.region, var.region) - prefix = var.prefix == null ? "" : "${var.prefix}-" - project_id = lookup(local.ctx.project_ids, var.project_id, var.project_id) - vpc_connector = ( - var.vpc_connector.name == null - ? null - : ( - var.vpc_connector.create == false - ? var.vpc_connector.name - : google_vpc_access_connector.connector[0].id - ) - ) -} - -resource "google_vpc_access_connector" "connector" { - count = var.vpc_connector.create == true ? 1 : 0 - project = local.project_id - name = var.vpc_connector.name - region = local.location - ip_cidr_range = lookup(local.ctx.cidr_ranges, - var.vpc_connector_config.ip_cidr_range, - var.vpc_connector_config.ip_cidr_range - ) - network = lookup(local.ctx.networks, - var.vpc_connector_config.network, var.vpc_connector_config.network - ) - max_instances = try(var.vpc_connector_config.instances.max, null) - min_instances = try(var.vpc_connector_config.instances.min, null) - max_throughput = try(var.vpc_connector_config.throughput.max, null) - min_throughput = try(var.vpc_connector_config.throughput.min, null) + location = lookup(local.ctx.locations, var.region, var.region) + prefix = var.prefix == null ? "" : "${var.prefix}-" + project_id = lookup(local.ctx.project_ids, var.project_id, var.project_id) + vpc_connector = var.vpc_connector.create ? google_vpc_access_connector.connector[0].id : var.vpc_connector.name } resource "google_cloudfunctions_function" "function" { @@ -80,19 +54,17 @@ resource "google_cloudfunctions_function" "function" { ? replace(var.bundle_config.path, "/^gs:\\/\\/[^\\/]+\\//", "") : google_storage_bucket_object.bundle[0].name ) - labels = var.labels - trigger_http = var.trigger_config == null ? true : null - https_trigger_security_level = var.https_security_level == null ? "SECURE_ALWAYS" : var.https_security_level - ingress_settings = var.ingress_settings - build_worker_pool = var.build_worker_pool - build_environment_variables = var.build_environment_variables - kms_key_name = var.kms_key == null ? null : lookup(local.ctx.kms_keys, var.kms_key, var.kms_key) - docker_registry = try(var.repository_settings.registry, "ARTIFACT_REGISTRY") - docker_repository = try(var.repository_settings.repository, null) - vpc_connector = local.vpc_connector - vpc_connector_egress_settings = try( - var.vpc_connector.egress_settings, null - ) + labels = var.labels + trigger_http = var.trigger_config == null ? true : null + https_trigger_security_level = var.https_security_level == null ? "SECURE_ALWAYS" : var.https_security_level + ingress_settings = var.ingress_settings + build_worker_pool = var.build_worker_pool + build_environment_variables = var.build_environment_variables + kms_key_name = var.kms_key == null ? null : lookup(local.ctx.kms_keys, var.kms_key, var.kms_key) + docker_registry = try(var.repository_settings.registry, "ARTIFACT_REGISTRY") + docker_repository = try(var.repository_settings.repository, null) + vpc_connector = local.vpc_connector + vpc_connector_egress_settings = var.vpc_connector.egress_settings dynamic "event_trigger" { for_each = var.trigger_config == null ? [] : [""] @@ -143,8 +115,8 @@ resource "google_cloudfunctions_function_iam_binding" "default" { project = local.project_id region = local.location cloud_function = google_cloudfunctions_function.function.id - role = each.key - members = each.value + role = lookup(local.ctx.custom_roles, each.key, each.key) + members = [for member in each.value : lookup(local.ctx.iam_principals, member, member)] lifecycle { replace_triggered_by = [google_cloudfunctions_function.function] } diff --git a/modules/cloud-function-v1/variables-vpcconnector.tf b/modules/cloud-function-v1/variables-vpcconnector.tf new file mode 100644 index 000000000..967ce6983 --- /dev/null +++ b/modules/cloud-function-v1/variables-vpcconnector.tf @@ -0,0 +1,59 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "vpc_connector" { + description = "VPC connector configuration. Set create to 'true' if a new connector needs to be created." + type = object({ + create = optional(bool, false) + name = optional(string) + egress_settings = optional(string) + }) + nullable = false + default = {} +} + +variable "vpc_connector_create" { + description = "VPC connector network configuration. Must be provided if new VPC connector is being created." + type = object({ + ip_cidr_range = optional(string) + machine_type = optional(string) + name = optional(string) + network = optional(string) + instances = optional(object({ + max = optional(number) + min = optional(number) + }), {} + ) + throughput = optional(object({ + max = optional(number) + min = optional(number) + }), {} + ) + subnet = optional(object({ + name = optional(string) + project_id = optional(string) + }), {}) + }) + default = null + validation { + condition = ( + var.vpc_connector.create == false || + try(var.vpc_connector_create.instances, null) != null || + try(var.vpc_connector_create.throughput, null) != null + ) + error_message = "VPC connector must specify either instances or throughput." + } +} diff --git a/modules/cloud-function-v1/variables.tf b/modules/cloud-function-v1/variables.tf index 12843bc59..c089bbb07 100644 --- a/modules/cloud-function-v1/variables.tf +++ b/modules/cloud-function-v1/variables.tf @@ -212,39 +212,3 @@ variable "trigger_config" { }) default = null } - -variable "vpc_connector" { - description = "VPC connector configuration. Set create to 'true' if a new connector needs to be created." - type = object({ - create = optional(bool, false) - name = optional(string) - egress_settings = optional(string) - }) - nullable = false - default = {} -} - -variable "vpc_connector_config" { - description = "VPC connector network configuration. Must be provided if new VPC connector is being created." - type = object({ - ip_cidr_range = string - network = string - instances = optional(object({ - max = optional(number) - min = optional(number, 2) - })) - throughput = optional(object({ - max = optional(number, 300) - min = optional(number, 200) - })) - }) - default = null - validation { - condition = ( - var.vpc_connector_config == null || - try(var.vpc_connector_config.instances, null) != null || - try(var.vpc_connector_config.throughput, null) != null - ) - error_message = "VPC connector must specify either instances or throughput." - } -} diff --git a/modules/cloud-function-v1/vpcconnector.tf b/modules/cloud-function-v1/vpcconnector.tf new file mode 100644 index 000000000..4d01eada0 --- /dev/null +++ b/modules/cloud-function-v1/vpcconnector.tf @@ -0,0 +1,74 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + _connector_subnet_name_ctx = ( + try(var.vpc_connector_create.subnet.name, null) == null ? false : + contains(keys(local.ctx.subnets), var.vpc_connector_create.subnet.name) + ) + # if you pass the subnet, you must pass only the name, not the whole id + _connector_subnet_name = ( + local._connector_subnet_name_ctx + ? provider::google::name_from_id(local.ctx.subnets[var.vpc_connector_create.subnet.name]) + : try(var.vpc_connector_create.subnet.name, null) + ) + # if project is not provided, but subnet is coming from context, use project from subnet id in context + # and avoid lookups using null project + _connector_subnet_project_input = try(var.vpc_connector_create.subnet.project_id, null) + _connector_subnet_project = ( + local._connector_subnet_project_input == null + ? ( + local._connector_subnet_name_ctx + ? provider::google::project_from_id(local.ctx.subnets[var.vpc_connector_create.subnet.name]) + : null + ) + : lookup( + local.ctx.project_ids, local._connector_subnet_project_input, + local._connector_subnet_project_input + ) + ) +} + +resource "google_vpc_access_connector" "connector" { + count = var.vpc_connector_create != null ? 1 : 0 + project = local.project_id + name = ( + var.vpc_connector_create.name != null + ? var.vpc_connector_create.name + : var.name + ) + region = local.location + ip_cidr_range = var.vpc_connector_create.ip_cidr_range == null ? null : lookup( + local.ctx.cidr_ranges, var.vpc_connector_create.ip_cidr_range, + var.vpc_connector_create.ip_cidr_range + ) + network = var.vpc_connector_create.network == null ? null : lookup( + local.ctx.networks, var.vpc_connector_create.network, + var.vpc_connector_create.network + ) + machine_type = var.vpc_connector_create.machine_type + max_instances = var.vpc_connector_create.instances.max + max_throughput = var.vpc_connector_create.throughput.max + min_instances = var.vpc_connector_create.instances.min + min_throughput = var.vpc_connector_create.throughput.min + dynamic "subnet" { + for_each = var.vpc_connector_create.subnet.name == null ? [] : [""] + content { + name = local._connector_subnet_name + project_id = local._connector_subnet_project + } + } +} diff --git a/modules/cloud-function-v2/README.md b/modules/cloud-function-v2/README.md index 5617eaad0..9f60b645f 100644 --- a/modules/cloud-function-v2/README.md +++ b/modules/cloud-function-v2/README.md @@ -14,6 +14,7 @@ Cloud Function management, with support for IAM roles, optional bucket creation - [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) +- [VPC Access Connector](#vpc-access-connector) - [Variables](#variables) - [Outputs](#outputs) - [Fixtures](#fixtures) @@ -325,6 +326,85 @@ module "secret-manager" { } # tftest fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=secrets.yaml e2e skip-tofu ``` + +## VPC Access Connector + +You can use an existing [VPC Access Connector](https://cloud.google.com/vpc/docs/serverless-vpc-access) to connect to a VPC from Cloud Run. + +```hcl +module "cf_http" { + source = "./fabric/modules/cloud-function-v2" + project_id = var.project_id + region = var.region + name = "test-cf-http" + bucket_name = var.bucket + bundle_config = { + path = "assets/sample-function/" + } + vpc_connector = { + name = google_vpc_access_connector.connector.id + egress_setting = "ALL_TRAFFIC" + } +} +# tftest fixtures=fixtures/vpc-connector.tf inventory=service-vpc-access-connector.yaml e2e +``` + +If creation of the VPC Access Connector is required, use the `vpc_connector.create` and `vpc_connector_create` variable which also supports optional attributes like number of instances, machine type, or throughput. + +```hcl +module "cf_http" { + source = "./fabric/modules/cloud-function-v2" + project_id = var.project_id + region = var.region + name = "test-cf-http" + bucket_name = var.bucket + bundle_config = { + path = "assets/sample-function/" + } + vpc_connector = { + create = true + } + vpc_connector_create = { + ip_cidr_range = "10.10.10.0/28" + network = var.vpc.self_link + instances = { + max = 10 + min = 3 + } + } +} +# tftest inventory=service-vpc-access-connector-create.yaml e2e +``` + +Note that if you are using a Shared VPC for the connector, you need to specify a subnet and the host project if this is not where the Cloud Run service is deployed. + +```hcl +module "cf_http" { + source = "./fabric/modules/cloud-function-v2" + project_id = var.project_id + region = var.region + name = "test-cf-http" + bucket_name = var.bucket + bundle_config = { + path = "assets/sample-function/" + } + vpc_connector = { + create = true + } + vpc_connector_create = { + machine_type = "e2-standard-4" + subnet = { + name = module.net-vpc-host.subnets["${var.region}/fixture-subnet-28"].name + project_id = module.project-host.project_id + } + throughput = { + max = 300 + min = 200 + } + } +} +# tftest fixtures=fixtures/shared-vpc.tf inventory=service-vpc-access-connector-create-sharedvpc.yaml e2e +``` ## Variables @@ -352,8 +432,8 @@ module "secret-manager" { | [secrets](variables.tf#L192) | Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format. | map(object({…})) | | {} | | [service_account_config](variables-serviceaccount.tf#L17) | Service account configurations. | object({…}) | | {} | | [trigger_config](variables.tf#L204) | Function trigger configuration. Leave null for HTTP trigger. | object({…}) | | null | -| [vpc_connector](variables.tf#L222) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | {} | -| [vpc_connector_config](variables.tf#L233) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null | +| [vpc_connector](variables-vpcconnector.tf#L17) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | {} | +| [vpc_connector_create](variables-vpcconnector.tf#L28) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null | ## Outputs @@ -379,4 +459,6 @@ module "secret-manager" { - [cloudbuild-custom-pool.tf](../../tests/fixtures/cloudbuild-custom-pool.tf) - [functions-default-sa-iam-grants.tf](../../tests/fixtures/functions-default-sa-iam-grants.tf) - [pubsub.tf](../../tests/fixtures/pubsub.tf) +- [shared-vpc.tf](../../tests/fixtures/shared-vpc.tf) +- [vpc-connector.tf](../../tests/fixtures/vpc-connector.tf) diff --git a/modules/cloud-function-v2/main.tf b/modules/cloud-function-v2/main.tf index db964075f..7905158ca 100644 --- a/modules/cloud-function-v2/main.tf +++ b/modules/cloud-function-v2/main.tf @@ -41,33 +41,7 @@ locals { var.trigger_config.service_account_email, null ) - vpc_connector = ( - var.vpc_connector.name == null - ? null - : ( - var.vpc_connector.create == false - ? var.vpc_connector.name - : google_vpc_access_connector.connector[0].id - ) - ) -} - -resource "google_vpc_access_connector" "connector" { - count = var.vpc_connector.create == true ? 1 : 0 - project = local.project_id - name = var.vpc_connector.name - region = local.location - ip_cidr_range = lookup(local.ctx.cidr_ranges, - var.vpc_connector_config.ip_cidr_range, - var.vpc_connector_config.ip_cidr_range - ) - network = lookup(local.ctx.networks, - var.vpc_connector_config.network, var.vpc_connector_config.network - ) - max_instances = try(var.vpc_connector_config.instances.max, null) - min_instances = try(var.vpc_connector_config.instances.min, null) - max_throughput = try(var.vpc_connector_config.throughput.max, null) - min_throughput = try(var.vpc_connector_config.throughput.min, null) + vpc_connector = var.vpc_connector.create ? google_vpc_access_connector.connector[0].id : var.vpc_connector.name } resource "google_cloudfunctions2_function" "function" { @@ -168,33 +142,35 @@ resource "google_cloudfunctions2_function_iam_binding" "binding" { for_each = { for k, v in var.iam : k => v if k != "roles/run.invoker" } - project = var.project_id - location = google_cloudfunctions2_function.function.location + project = local.project_id + location = local.location cloud_function = google_cloudfunctions2_function.function.name - role = each.key - members = each.value + role = lookup(local.ctx.custom_roles, each.key, each.key) + members = [for member in each.value : lookup(local.ctx.iam_principals, member, member)] lifecycle { replace_triggered_by = [google_cloudfunctions2_function.function] } } +locals { + run_invoker_members = distinct(compact(concat( + !local.trigger_sa_create + ? [] + : ["serviceAccount:${local.trigger_sa_email}"], + lookup(var.iam, "roles/run.invoker", []), + ))) +} + resource "google_cloud_run_service_iam_binding" "invoker" { # cloud run resources are needed for invoker role to the underlying service count = ( lookup(var.iam, "roles/run.invoker", null) != null ) ? 1 : 0 - project = var.project_id - location = google_cloudfunctions2_function.function.location + project = local.project_id + location = local.location service = google_cloudfunctions2_function.function.name role = "roles/run.invoker" - members = distinct(compact(concat( - lookup(var.iam, "roles/run.invoker", []), - ( - !local.trigger_sa_create - ? [] - : ["serviceAccount:${local.trigger_sa_email}"] - ) - ))) + members = [for member in local.run_invoker_members : lookup(local.ctx.iam_principals, member, member)] lifecycle { replace_triggered_by = [google_cloudfunctions2_function.function] } @@ -207,8 +183,8 @@ resource "google_cloud_run_service_iam_member" "invoker" { lookup(var.iam, "roles/run.invoker", null) == null && local.trigger_sa_create ) ? 1 : 0 - project = var.project_id - location = google_cloudfunctions2_function.function.location + project = local.project_id + location = local.location service = google_cloudfunctions2_function.function.name role = "roles/run.invoker" member = "serviceAccount:${local.trigger_sa_email}" diff --git a/modules/cloud-function-v2/variables-vpcconnector.tf b/modules/cloud-function-v2/variables-vpcconnector.tf new file mode 100644 index 000000000..967ce6983 --- /dev/null +++ b/modules/cloud-function-v2/variables-vpcconnector.tf @@ -0,0 +1,59 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "vpc_connector" { + description = "VPC connector configuration. Set create to 'true' if a new connector needs to be created." + type = object({ + create = optional(bool, false) + name = optional(string) + egress_settings = optional(string) + }) + nullable = false + default = {} +} + +variable "vpc_connector_create" { + description = "VPC connector network configuration. Must be provided if new VPC connector is being created." + type = object({ + ip_cidr_range = optional(string) + machine_type = optional(string) + name = optional(string) + network = optional(string) + instances = optional(object({ + max = optional(number) + min = optional(number) + }), {} + ) + throughput = optional(object({ + max = optional(number) + min = optional(number) + }), {} + ) + subnet = optional(object({ + name = optional(string) + project_id = optional(string) + }), {}) + }) + default = null + validation { + condition = ( + var.vpc_connector.create == false || + try(var.vpc_connector_create.instances, null) != null || + try(var.vpc_connector_create.throughput, null) != null + ) + error_message = "VPC connector must specify either instances or throughput." + } +} diff --git a/modules/cloud-function-v2/variables.tf b/modules/cloud-function-v2/variables.tf index 3b992812c..0926f8fd5 100644 --- a/modules/cloud-function-v2/variables.tf +++ b/modules/cloud-function-v2/variables.tf @@ -218,39 +218,3 @@ variable "trigger_config" { }) default = null } - -variable "vpc_connector" { - description = "VPC connector configuration. Set create to 'true' if a new connector needs to be created." - type = object({ - create = optional(bool, false) - name = optional(string) - egress_settings = optional(string) - }) - nullable = false - default = {} -} - -variable "vpc_connector_config" { - description = "VPC connector network configuration. Must be provided if new VPC connector is being created." - type = object({ - ip_cidr_range = string - network = string - instances = optional(object({ - max = optional(number) - min = optional(number, 2) - })) - throughput = optional(object({ - max = optional(number, 300) - min = optional(number, 200) - })) - }) - default = null - validation { - condition = ( - var.vpc_connector_config == null || - try(var.vpc_connector_config.instances, null) != null || - try(var.vpc_connector_config.throughput, null) != null - ) - error_message = "VPC connector must specify either instances or throughput." - } -} diff --git a/modules/cloud-function-v2/vpcconnector.tf b/modules/cloud-function-v2/vpcconnector.tf new file mode 100644 index 000000000..4d01eada0 --- /dev/null +++ b/modules/cloud-function-v2/vpcconnector.tf @@ -0,0 +1,74 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + _connector_subnet_name_ctx = ( + try(var.vpc_connector_create.subnet.name, null) == null ? false : + contains(keys(local.ctx.subnets), var.vpc_connector_create.subnet.name) + ) + # if you pass the subnet, you must pass only the name, not the whole id + _connector_subnet_name = ( + local._connector_subnet_name_ctx + ? provider::google::name_from_id(local.ctx.subnets[var.vpc_connector_create.subnet.name]) + : try(var.vpc_connector_create.subnet.name, null) + ) + # if project is not provided, but subnet is coming from context, use project from subnet id in context + # and avoid lookups using null project + _connector_subnet_project_input = try(var.vpc_connector_create.subnet.project_id, null) + _connector_subnet_project = ( + local._connector_subnet_project_input == null + ? ( + local._connector_subnet_name_ctx + ? provider::google::project_from_id(local.ctx.subnets[var.vpc_connector_create.subnet.name]) + : null + ) + : lookup( + local.ctx.project_ids, local._connector_subnet_project_input, + local._connector_subnet_project_input + ) + ) +} + +resource "google_vpc_access_connector" "connector" { + count = var.vpc_connector_create != null ? 1 : 0 + project = local.project_id + name = ( + var.vpc_connector_create.name != null + ? var.vpc_connector_create.name + : var.name + ) + region = local.location + ip_cidr_range = var.vpc_connector_create.ip_cidr_range == null ? null : lookup( + local.ctx.cidr_ranges, var.vpc_connector_create.ip_cidr_range, + var.vpc_connector_create.ip_cidr_range + ) + network = var.vpc_connector_create.network == null ? null : lookup( + local.ctx.networks, var.vpc_connector_create.network, + var.vpc_connector_create.network + ) + machine_type = var.vpc_connector_create.machine_type + max_instances = var.vpc_connector_create.instances.max + max_throughput = var.vpc_connector_create.throughput.max + min_instances = var.vpc_connector_create.instances.min + min_throughput = var.vpc_connector_create.throughput.min + dynamic "subnet" { + for_each = var.vpc_connector_create.subnet.name == null ? [] : [""] + content { + name = local._connector_subnet_name + project_id = local._connector_subnet_project + } + } +} diff --git a/modules/cloud-run-v2/README.md b/modules/cloud-run-v2/README.md index 96141de7b..f33a3a13f 100644 --- a/modules/cloud-run-v2/README.md +++ b/modules/cloud-run-v2/README.md @@ -189,7 +189,7 @@ You can use an existing [VPC Access Connector](https://cloud.google.com/vpc/docs module "cloud_run" { source = "./fabric/modules/cloud-run-v2" project_id = var.project_id - region = var.region + region = var.regions.secondary name = "hello" containers = { hello = { diff --git a/tests/fixtures/vpc-connector.tf b/tests/fixtures/vpc-connector.tf index 483cf64d0..fda673012 100644 --- a/tests/fixtures/vpc-connector.tf +++ b/tests/fixtures/vpc-connector.tf @@ -17,7 +17,7 @@ resource "google_vpc_access_connector" "connector" { project = var.project_id name = "vpc-connector" - region = var.region + region = var.regions.secondary min_instances = 2 max_instances = 3 ip_cidr_range = "192.168.0.0/28" diff --git a/tests/modules/cloud_function_v1/context-subnet-project.tfvars b/tests/modules/cloud_function_v1/context-subnet-project.tfvars new file mode 100644 index 000000000..6428c97e1 --- /dev/null +++ b/tests/modules/cloud_function_v1/context-subnet-project.tfvars @@ -0,0 +1,58 @@ +name = "test-cf-kms" +bucket_name = "bucket" +bundle_config = { + path = "gs://assets/sample-function.zip" +} +context = { + cidr_ranges = { + test = "10.10.20.0/28" + } + custom_roles = { + myrole_one = "organizations/366118655033/roles/myRoleOne" + } + iam_principals = { + mygroup = "group:test-group@example.com" + } + kms_keys = { + test = "projects/foo-prod-sec-core/locations/global/keyRings/prod-global-default/cryptoKeys/compute" + } + locations = { + ew8 = "europe-west8" + } + networks = { + test = "projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0" + } + project_ids = { + test = "foo-test-0" + } + subnets = { + test = "projects/foo-dev-net-spoke-0/regions/europe-west1/subnetworks/gce" + } +} +kms_key = "$kms_keys:test" +iam = { + "$custom_roles:myrole_one" = [ + "$iam_principals:mygroup" + ] +} +project_id = "$project_ids:test" +region = "$locations:ew8" +service_account_config = { + roles = [ + "$custom_roles:myrole_one" + ] +} +vpc_connector = { + create = true + name = "connector_name" +} +vpc_connector_create = { + instances = { + max = 10 + min = 3 + } + subnet = { + name = "$subnets:test" + project_id = "$project_ids:test" + } +} diff --git a/tests/modules/cloud_function_v1/context-subnet-project.yaml b/tests/modules/cloud_function_v1/context-subnet-project.yaml new file mode 100644 index 000000000..6ada43545 --- /dev/null +++ b/tests/modules/cloud_function_v1/context-subnet-project.yaml @@ -0,0 +1,61 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + google_cloudfunctions_function.function: + kms_key_name: projects/foo-prod-sec-core/locations/global/keyRings/prod-global-default/cryptoKeys/compute + project: foo-test-0 + region: europe-west8 + service_account_email: test-cf-kms@foo-test-0.iam.gserviceaccount.com + google_cloudfunctions_function_iam_binding.default["$custom_roles:myrole_one"]: + condition: [] + members: + - group:test-group@example.com + project: foo-test-0 + region: europe-west8 + role: organizations/366118655033/roles/myRoleOne + google_project_iam_member.default["organizations/366118655033/roles/myRoleOne"]: + condition: [] + member: serviceAccount:test-cf-kms@foo-test-0.iam.gserviceaccount.com + project: foo-test-0 + role: organizations/366118655033/roles/myRoleOne + google_service_account.service_account[0]: + account_id: test-cf-kms + create_ignore_already_exists: null + description: null + disabled: false + display_name: test-cf-kms + email: test-cf-kms@foo-test-0.iam.gserviceaccount.com + member: serviceAccount:test-cf-kms@foo-test-0.iam.gserviceaccount.com + project: foo-test-0 + timeouts: null + google_vpc_access_connector.connector[0]: + ip_cidr_range: null + machine_type: e2-micro + max_instances: 10 + min_instances: 3 + name: test-cf-kms + project: foo-test-0 + region: europe-west8 + subnet: + - name: gce + project_id: foo-test-0 + timeouts: null + +counts: + google_cloudfunctions_function: 1 + google_cloudfunctions_function_iam_binding: 1 + google_project_iam_member: 1 + google_service_account: 1 + google_vpc_access_connector: 1 diff --git a/tests/modules/cloud_function_v1/context-subnet.tfvars b/tests/modules/cloud_function_v1/context-subnet.tfvars new file mode 100644 index 000000000..7512e3ab3 --- /dev/null +++ b/tests/modules/cloud_function_v1/context-subnet.tfvars @@ -0,0 +1,57 @@ +name = "test-cf-kms" +bucket_name = "bucket" +bundle_config = { + path = "gs://assets/sample-function.zip" +} +context = { + cidr_ranges = { + test = "10.10.20.0/28" + } + custom_roles = { + myrole_one = "organizations/366118655033/roles/myRoleOne" + } + iam_principals = { + mygroup = "group:test-group@example.com" + } + kms_keys = { + test = "projects/foo-prod-sec-core/locations/global/keyRings/prod-global-default/cryptoKeys/compute" + } + locations = { + ew8 = "europe-west8" + } + networks = { + test = "projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0" + } + project_ids = { + test = "foo-test-0" + } + subnets = { + test = "projects/foo-dev-net-spoke-0/regions/europe-west1/subnetworks/gce" + } +} +kms_key = "$kms_keys:test" +iam = { + "$custom_roles:myrole_one" = [ + "$iam_principals:mygroup" + ] +} +project_id = "$project_ids:test" +region = "$locations:ew8" +service_account_config = { + roles = [ + "$custom_roles:myrole_one" + ] +} +vpc_connector = { + create = true + name = "connector_name" +} +vpc_connector_create = { + instances = { + max = 10 + min = 3 + } + subnet = { + name = "$subnets:test" + } +} diff --git a/tests/modules/cloud_function_v1/context-subnet.yaml b/tests/modules/cloud_function_v1/context-subnet.yaml new file mode 100644 index 000000000..de5cf036a --- /dev/null +++ b/tests/modules/cloud_function_v1/context-subnet.yaml @@ -0,0 +1,60 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + google_cloudfunctions_function.function: + kms_key_name: projects/foo-prod-sec-core/locations/global/keyRings/prod-global-default/cryptoKeys/compute + project: foo-test-0 + region: europe-west8 + service_account_email: test-cf-kms@foo-test-0.iam.gserviceaccount.com + google_cloudfunctions_function_iam_binding.default["$custom_roles:myrole_one"]: + condition: [] + members: + - group:test-group@example.com + project: foo-test-0 + region: europe-west8 + role: organizations/366118655033/roles/myRoleOne + google_project_iam_member.default["organizations/366118655033/roles/myRoleOne"]: + condition: [] + member: serviceAccount:test-cf-kms@foo-test-0.iam.gserviceaccount.com + project: foo-test-0 + role: organizations/366118655033/roles/myRoleOne + google_service_account.service_account[0]: + account_id: test-cf-kms + create_ignore_already_exists: null + description: null + disabled: false + display_name: test-cf-kms + email: test-cf-kms@foo-test-0.iam.gserviceaccount.com + member: serviceAccount:test-cf-kms@foo-test-0.iam.gserviceaccount.com + project: foo-test-0 + timeouts: null + google_vpc_access_connector.connector[0]: + ip_cidr_range: null + machine_type: e2-micro + max_instances: 10 + min_instances: 3 + name: test-cf-kms + project: foo-test-0 + region: europe-west8 + subnet: + - name: gce + project_id: foo-dev-net-spoke-0 + +counts: + google_cloudfunctions_function: 1 + google_cloudfunctions_function_iam_binding: 1 + google_project_iam_member: 1 + google_service_account: 1 + google_vpc_access_connector: 1 diff --git a/tests/modules/cloud_function_v1/context.tfvars b/tests/modules/cloud_function_v1/context.tfvars index 558271b35..f6eb5e3e3 100644 --- a/tests/modules/cloud_function_v1/context.tfvars +++ b/tests/modules/cloud_function_v1/context.tfvars @@ -46,7 +46,7 @@ vpc_connector = { create = true name = "connector_name" } -vpc_connector_config = { +vpc_connector_create = { ip_cidr_range = "$cidr_ranges:test" network = "$networks:test" instances = { diff --git a/tests/modules/cloud_function_v1/context.yaml b/tests/modules/cloud_function_v1/context.yaml index 6417d4548..da60e5571 100644 --- a/tests/modules/cloud_function_v1/context.yaml +++ b/tests/modules/cloud_function_v1/context.yaml @@ -45,7 +45,7 @@ values: machine_type: e2-micro max_instances: 10 min_instances: 3 - name: connector_name + name: test-cf-kms network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0 project: foo-test-0 region: europe-west8 diff --git a/tests/modules/cloud_function_v1/examples/service-vpc-access-connector-create-sharedvpc.yaml b/tests/modules/cloud_function_v1/examples/service-vpc-access-connector-create-sharedvpc.yaml new file mode 100644 index 000000000..1ae759ba3 --- /dev/null +++ b/tests/modules/cloud_function_v1/examples/service-vpc-access-connector-create-sharedvpc.yaml @@ -0,0 +1,68 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + module.cf_http.google_cloudfunctions_function.function: + available_memory_mb: 256 + build_environment_variables: null + build_worker_pool: null + description: Terraform managed. + docker_registry: ARTIFACT_REGISTRY + docker_repository: null + effective_labels: + goog-terraform-provisioned: 'true' + entry_point: main + environment_variables: null + https_trigger_security_level: SECURE_ALWAYS + ingress_settings: ALLOW_ALL + kms_key_name: null + labels: null + max_instances: 1 + min_instances: null + name: test-cf-http + on_deploy_update_policy: [] + project: project-id + region: europe-west8 + runtime: python310 + secret_environment_variables: [] + secret_volumes: [] + service_account_email: test-cf-http@project-id.iam.gserviceaccount.com + source_archive_bucket: bucket + source_archive_object: bundle-95c1b0e5b92dae8333539b1e0ad5173b.zip + source_repository: [] + terraform_labels: + goog-terraform-provisioned: 'true' + timeout: 180 + timeouts: null + trigger_http: true + module.cf_http.google_vpc_access_connector.connector[0]: + ip_cidr_range: null + machine_type: e2-standard-4 + max_throughput: 300 + min_throughput: 200 + name: test-cf-http + project: project-id + region: europe-west8 + subnet: + - name: fixture-subnet-28 + project_id: test-host + timeouts: null + +counts: + google_cloudfunctions_function: 1 + google_service_account: 1 + google_storage_bucket_object: 1 + + +outputs: {} diff --git a/tests/modules/cloud_function_v1/examples/service-vpc-access-connector-create.yaml b/tests/modules/cloud_function_v1/examples/service-vpc-access-connector-create.yaml new file mode 100644 index 000000000..e1c215525 --- /dev/null +++ b/tests/modules/cloud_function_v1/examples/service-vpc-access-connector-create.yaml @@ -0,0 +1,56 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + module.cf_http.google_cloudfunctions_function.function: + available_memory_mb: 256 + build_environment_variables: null + build_worker_pool: null + description: Terraform managed. + docker_registry: ARTIFACT_REGISTRY + docker_repository: null + effective_labels: + goog-terraform-provisioned: 'true' + entry_point: main + environment_variables: null + https_trigger_security_level: SECURE_ALWAYS + ingress_settings: ALLOW_ALL + kms_key_name: null + labels: null + max_instances: 1 + min_instances: null + name: test-cf-http + on_deploy_update_policy: [] + project: project-id + region: europe-west8 + runtime: python310 + secret_environment_variables: [] + secret_volumes: [] + service_account_email: test-cf-http@project-id.iam.gserviceaccount.com + source_archive_bucket: bucket + source_repository: [] + terraform_labels: + goog-terraform-provisioned: 'true' + timeout: 180 + timeouts: null + trigger_http: true + +counts: + google_cloudfunctions_function: 1 + google_project_iam_member: 2 + google_service_account: 1 + google_storage_bucket_object: 1 + + +outputs: {} diff --git a/tests/modules/cloud_function_v1/examples/service-vpc-access-connector.yaml b/tests/modules/cloud_function_v1/examples/service-vpc-access-connector.yaml new file mode 100644 index 000000000..e1c215525 --- /dev/null +++ b/tests/modules/cloud_function_v1/examples/service-vpc-access-connector.yaml @@ -0,0 +1,56 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + module.cf_http.google_cloudfunctions_function.function: + available_memory_mb: 256 + build_environment_variables: null + build_worker_pool: null + description: Terraform managed. + docker_registry: ARTIFACT_REGISTRY + docker_repository: null + effective_labels: + goog-terraform-provisioned: 'true' + entry_point: main + environment_variables: null + https_trigger_security_level: SECURE_ALWAYS + ingress_settings: ALLOW_ALL + kms_key_name: null + labels: null + max_instances: 1 + min_instances: null + name: test-cf-http + on_deploy_update_policy: [] + project: project-id + region: europe-west8 + runtime: python310 + secret_environment_variables: [] + secret_volumes: [] + service_account_email: test-cf-http@project-id.iam.gserviceaccount.com + source_archive_bucket: bucket + source_repository: [] + terraform_labels: + goog-terraform-provisioned: 'true' + timeout: 180 + timeouts: null + trigger_http: true + +counts: + google_cloudfunctions_function: 1 + google_project_iam_member: 2 + google_service_account: 1 + google_storage_bucket_object: 1 + + +outputs: {} diff --git a/tests/modules/cloud_function_v1/tftest.yaml b/tests/modules/cloud_function_v1/tftest.yaml index ea15fe700..f763f77be 100644 --- a/tests/modules/cloud_function_v1/tftest.yaml +++ b/tests/modules/cloud_function_v1/tftest.yaml @@ -15,4 +15,6 @@ module: modules/cloud-function-v1 tests: context: + context-subnet: + context-subnet-project: kms: diff --git a/tests/modules/cloud_function_v2/context-subnet-project.tfvars b/tests/modules/cloud_function_v2/context-subnet-project.tfvars new file mode 100644 index 000000000..6428c97e1 --- /dev/null +++ b/tests/modules/cloud_function_v2/context-subnet-project.tfvars @@ -0,0 +1,58 @@ +name = "test-cf-kms" +bucket_name = "bucket" +bundle_config = { + path = "gs://assets/sample-function.zip" +} +context = { + cidr_ranges = { + test = "10.10.20.0/28" + } + custom_roles = { + myrole_one = "organizations/366118655033/roles/myRoleOne" + } + iam_principals = { + mygroup = "group:test-group@example.com" + } + kms_keys = { + test = "projects/foo-prod-sec-core/locations/global/keyRings/prod-global-default/cryptoKeys/compute" + } + locations = { + ew8 = "europe-west8" + } + networks = { + test = "projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0" + } + project_ids = { + test = "foo-test-0" + } + subnets = { + test = "projects/foo-dev-net-spoke-0/regions/europe-west1/subnetworks/gce" + } +} +kms_key = "$kms_keys:test" +iam = { + "$custom_roles:myrole_one" = [ + "$iam_principals:mygroup" + ] +} +project_id = "$project_ids:test" +region = "$locations:ew8" +service_account_config = { + roles = [ + "$custom_roles:myrole_one" + ] +} +vpc_connector = { + create = true + name = "connector_name" +} +vpc_connector_create = { + instances = { + max = 10 + min = 3 + } + subnet = { + name = "$subnets:test" + project_id = "$project_ids:test" + } +} diff --git a/tests/modules/cloud_function_v2/context-subnet-project.yaml b/tests/modules/cloud_function_v2/context-subnet-project.yaml new file mode 100644 index 000000000..1c0947fb9 --- /dev/null +++ b/tests/modules/cloud_function_v2/context-subnet-project.yaml @@ -0,0 +1,64 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + google_cloudfunctions2_function.function: + kms_key_name: projects/foo-prod-sec-core/locations/global/keyRings/prod-global-default/cryptoKeys/compute + location: europe-west8 + name: test-cf-kms + project: foo-test-0 + service_config: + - service_account_email: test-cf-kms@foo-test-0.iam.gserviceaccount.com + google_cloudfunctions2_function_iam_binding.binding["$custom_roles:myrole_one"]: + cloud_function: test-cf-kms + condition: [] + members: + - group:test-group@example.com + project: foo-test-0 + location: europe-west8 + role: organizations/366118655033/roles/myRoleOne + google_project_iam_member.default["organizations/366118655033/roles/myRoleOne"]: + condition: [] + member: serviceAccount:test-cf-kms@foo-test-0.iam.gserviceaccount.com + project: foo-test-0 + role: organizations/366118655033/roles/myRoleOne + google_service_account.service_account[0]: + account_id: test-cf-kms + create_ignore_already_exists: null + description: null + disabled: false + display_name: test-cf-kms + email: test-cf-kms@foo-test-0.iam.gserviceaccount.com + member: serviceAccount:test-cf-kms@foo-test-0.iam.gserviceaccount.com + project: foo-test-0 + timeouts: null + google_vpc_access_connector.connector[0]: + ip_cidr_range: null + machine_type: e2-micro + max_instances: 10 + min_instances: 3 + name: test-cf-kms + project: foo-test-0 + region: europe-west8 + subnet: + - name: gce + project_id: foo-test-0 + timeouts: null + +counts: + google_cloudfunctions2_function: 1 + google_cloudfunctions2_function_iam_binding: 1 + google_project_iam_member: 1 + google_service_account: 1 + google_vpc_access_connector: 1 diff --git a/tests/modules/cloud_function_v2/context-subnet.tfvars b/tests/modules/cloud_function_v2/context-subnet.tfvars new file mode 100644 index 000000000..7512e3ab3 --- /dev/null +++ b/tests/modules/cloud_function_v2/context-subnet.tfvars @@ -0,0 +1,57 @@ +name = "test-cf-kms" +bucket_name = "bucket" +bundle_config = { + path = "gs://assets/sample-function.zip" +} +context = { + cidr_ranges = { + test = "10.10.20.0/28" + } + custom_roles = { + myrole_one = "organizations/366118655033/roles/myRoleOne" + } + iam_principals = { + mygroup = "group:test-group@example.com" + } + kms_keys = { + test = "projects/foo-prod-sec-core/locations/global/keyRings/prod-global-default/cryptoKeys/compute" + } + locations = { + ew8 = "europe-west8" + } + networks = { + test = "projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0" + } + project_ids = { + test = "foo-test-0" + } + subnets = { + test = "projects/foo-dev-net-spoke-0/regions/europe-west1/subnetworks/gce" + } +} +kms_key = "$kms_keys:test" +iam = { + "$custom_roles:myrole_one" = [ + "$iam_principals:mygroup" + ] +} +project_id = "$project_ids:test" +region = "$locations:ew8" +service_account_config = { + roles = [ + "$custom_roles:myrole_one" + ] +} +vpc_connector = { + create = true + name = "connector_name" +} +vpc_connector_create = { + instances = { + max = 10 + min = 3 + } + subnet = { + name = "$subnets:test" + } +} diff --git a/tests/modules/cloud_function_v2/context-subnet.yaml b/tests/modules/cloud_function_v2/context-subnet.yaml new file mode 100644 index 000000000..de83bf86d --- /dev/null +++ b/tests/modules/cloud_function_v2/context-subnet.yaml @@ -0,0 +1,62 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + google_cloudfunctions2_function.function: + kms_key_name: projects/foo-prod-sec-core/locations/global/keyRings/prod-global-default/cryptoKeys/compute + location: europe-west8 + project: foo-test-0 + service_config: + - service_account_email: test-cf-kms@foo-test-0.iam.gserviceaccount.com + google_cloudfunctions2_function_iam_binding.binding["$custom_roles:myrole_one"]: + cloud_function: test-cf-kms + condition: [] + members: + - group:test-group@example.com + project: foo-test-0 + location: europe-west8 + role: organizations/366118655033/roles/myRoleOne + google_project_iam_member.default["organizations/366118655033/roles/myRoleOne"]: + condition: [] + member: serviceAccount:test-cf-kms@foo-test-0.iam.gserviceaccount.com + project: foo-test-0 + role: organizations/366118655033/roles/myRoleOne + google_service_account.service_account[0]: + account_id: test-cf-kms + create_ignore_already_exists: null + description: null + disabled: false + display_name: test-cf-kms + email: test-cf-kms@foo-test-0.iam.gserviceaccount.com + member: serviceAccount:test-cf-kms@foo-test-0.iam.gserviceaccount.com + project: foo-test-0 + timeouts: null + google_vpc_access_connector.connector[0]: + ip_cidr_range: null + machine_type: e2-micro + max_instances: 10 + min_instances: 3 + name: test-cf-kms + project: foo-test-0 + region: europe-west8 + subnet: + - name: gce + project_id: foo-dev-net-spoke-0 + +counts: + google_cloudfunctions2_function: 1 + google_cloudfunctions2_function_iam_binding: 1 + google_project_iam_member: 1 + google_service_account: 1 + google_vpc_access_connector: 1 diff --git a/tests/modules/cloud_function_v2/context.tfvars b/tests/modules/cloud_function_v2/context.tfvars new file mode 100644 index 000000000..f6eb5e3e3 --- /dev/null +++ b/tests/modules/cloud_function_v2/context.tfvars @@ -0,0 +1,56 @@ +name = "test-cf-kms" +bucket_name = "bucket" +bundle_config = { + path = "gs://assets/sample-function.zip" +} +context = { + cidr_ranges = { + test = "10.10.20.0/28" + } + custom_roles = { + myrole_one = "organizations/366118655033/roles/myRoleOne" + } + iam_principals = { + mygroup = "group:test-group@example.com" + } + kms_keys = { + test = "projects/foo-prod-sec-core/locations/global/keyRings/prod-global-default/cryptoKeys/compute" + } + locations = { + ew8 = "europe-west8" + } + networks = { + test = "projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0" + } + project_ids = { + test = "foo-test-0" + } + subnets = { + test = "projects/foo-dev-net-spoke-0/regions/europe-west1/subnetworks/gce" + } +} +kms_key = "$kms_keys:test" +iam = { + "$custom_roles:myrole_one" = [ + "$iam_principals:mygroup" + ] +} +project_id = "$project_ids:test" +region = "$locations:ew8" +service_account_config = { + roles = [ + "$custom_roles:myrole_one" + ] +} +vpc_connector = { + create = true + name = "connector_name" +} +vpc_connector_create = { + ip_cidr_range = "$cidr_ranges:test" + network = "$networks:test" + instances = { + max = 10 + min = 3 + } +} diff --git a/tests/modules/cloud_function_v2/context.yaml b/tests/modules/cloud_function_v2/context.yaml new file mode 100644 index 000000000..4f9a08057 --- /dev/null +++ b/tests/modules/cloud_function_v2/context.yaml @@ -0,0 +1,61 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + google_cloudfunctions2_function.function: + kms_key_name: projects/foo-prod-sec-core/locations/global/keyRings/prod-global-default/cryptoKeys/compute + location: europe-west8 + project: foo-test-0 + service_config: + - service_account_email: test-cf-kms@foo-test-0.iam.gserviceaccount.com + google_cloudfunctions2_function_iam_binding.binding["$custom_roles:myrole_one"]: + condition: [] + members: + - group:test-group@example.com + project: foo-test-0 + location: europe-west8 + role: organizations/366118655033/roles/myRoleOne + google_project_iam_member.default["organizations/366118655033/roles/myRoleOne"]: + condition: [] + member: serviceAccount:test-cf-kms@foo-test-0.iam.gserviceaccount.com + project: foo-test-0 + role: organizations/366118655033/roles/myRoleOne + google_service_account.service_account[0]: + account_id: test-cf-kms + create_ignore_already_exists: null + description: null + disabled: false + display_name: test-cf-kms + email: test-cf-kms@foo-test-0.iam.gserviceaccount.com + member: serviceAccount:test-cf-kms@foo-test-0.iam.gserviceaccount.com + project: foo-test-0 + timeouts: null + google_vpc_access_connector.connector[0]: + ip_cidr_range: 10.10.20.0/28 + machine_type: e2-micro + max_instances: 10 + min_instances: 3 + name: test-cf-kms + network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0 + project: foo-test-0 + region: europe-west8 + subnet: [] + timeouts: null + +counts: + google_cloudfunctions2_function: 1 + google_cloudfunctions2_function_iam_binding: 1 + google_project_iam_member: 1 + google_service_account: 1 + google_vpc_access_connector: 1 diff --git a/tests/modules/cloud_function_v2/examples/service-vpc-access-connector-create-sharedvpc.yaml b/tests/modules/cloud_function_v2/examples/service-vpc-access-connector-create-sharedvpc.yaml new file mode 100644 index 000000000..e3cef2cec --- /dev/null +++ b/tests/modules/cloud_function_v2/examples/service-vpc-access-connector-create-sharedvpc.yaml @@ -0,0 +1,73 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + module.cf_http.google_cloudfunctions2_function.function: + build_config: + - entry_point: main + on_deploy_update_policy: [] + runtime: python310 + source: + - repo_source: [] + storage_source: + - bucket: bucket + object: bundle-95c1b0e5b92dae8333539b1e0ad5173b.zip + worker_pool: null + description: Terraform managed. + effective_labels: + goog-terraform-provisioned: 'true' + event_trigger: [] + kms_key_name: null + labels: null + location: europe-west8 + name: test-cf-http + project: project-id + service_config: + - all_traffic_on_latest_revision: true + available_cpu: '0.166' + available_memory: 256M + binary_authorization_policy: null + environment_variables: + LOG_EXECUTION_ID: 'true' + ingress_settings: ALLOW_ALL + max_instance_count: 1 + min_instance_count: 0 + secret_environment_variables: [] + secret_volumes: [] + service_account_email: test-cf-http@project-id.iam.gserviceaccount.com + timeout_seconds: 180 + vpc_connector_egress_settings: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.cf_http.google_vpc_access_connector.connector[0]: + ip_cidr_range: null + machine_type: e2-standard-4 + max_throughput: 300 + min_throughput: 200 + name: test-cf-http + project: project-id + region: europe-west8 + subnet: + - name: fixture-subnet-28 + project_id: test-host + timeouts: null + +counts: + google_cloudfunctions2_function: 1 + google_service_account: 1 + google_storage_bucket_object: 1 + + +outputs: {} diff --git a/tests/modules/cloud_function_v2/examples/service-vpc-access-connector-create.yaml b/tests/modules/cloud_function_v2/examples/service-vpc-access-connector-create.yaml new file mode 100644 index 000000000..ba62ca04a --- /dev/null +++ b/tests/modules/cloud_function_v2/examples/service-vpc-access-connector-create.yaml @@ -0,0 +1,62 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + module.cf_http.google_cloudfunctions2_function.function: + build_config: + - entry_point: main + on_deploy_update_policy: [] + runtime: python310 + source: + - repo_source: [] + storage_source: + - bucket: bucket + object: bundle-95c1b0e5b92dae8333539b1e0ad5173b.zip + worker_pool: null + description: Terraform managed. + effective_labels: + goog-terraform-provisioned: 'true' + event_trigger: [] + kms_key_name: null + labels: null + location: europe-west8 + name: test-cf-http + project: project-id + service_config: + - all_traffic_on_latest_revision: true + available_cpu: '0.166' + available_memory: 256M + binary_authorization_policy: null + environment_variables: + LOG_EXECUTION_ID: 'true' + ingress_settings: ALLOW_ALL + max_instance_count: 1 + min_instance_count: 0 + secret_environment_variables: [] + secret_volumes: [] + service_account_email: test-cf-http@project-id.iam.gserviceaccount.com + timeout_seconds: 180 + vpc_connector_egress_settings: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + +counts: + google_cloudfunctions2_function: 1 + google_project_iam_member: 2 + google_service_account: 1 + google_storage_bucket_object: 1 + + +outputs: {} diff --git a/tests/modules/cloud_function_v2/examples/service-vpc-access-connector.yaml b/tests/modules/cloud_function_v2/examples/service-vpc-access-connector.yaml new file mode 100644 index 000000000..ba62ca04a --- /dev/null +++ b/tests/modules/cloud_function_v2/examples/service-vpc-access-connector.yaml @@ -0,0 +1,62 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + module.cf_http.google_cloudfunctions2_function.function: + build_config: + - entry_point: main + on_deploy_update_policy: [] + runtime: python310 + source: + - repo_source: [] + storage_source: + - bucket: bucket + object: bundle-95c1b0e5b92dae8333539b1e0ad5173b.zip + worker_pool: null + description: Terraform managed. + effective_labels: + goog-terraform-provisioned: 'true' + event_trigger: [] + kms_key_name: null + labels: null + location: europe-west8 + name: test-cf-http + project: project-id + service_config: + - all_traffic_on_latest_revision: true + available_cpu: '0.166' + available_memory: 256M + binary_authorization_policy: null + environment_variables: + LOG_EXECUTION_ID: 'true' + ingress_settings: ALLOW_ALL + max_instance_count: 1 + min_instance_count: 0 + secret_environment_variables: [] + secret_volumes: [] + service_account_email: test-cf-http@project-id.iam.gserviceaccount.com + timeout_seconds: 180 + vpc_connector_egress_settings: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + +counts: + google_cloudfunctions2_function: 1 + google_project_iam_member: 2 + google_service_account: 1 + google_storage_bucket_object: 1 + + +outputs: {} diff --git a/tests/modules/cloud_function_v2/kms.tfvars b/tests/modules/cloud_function_v2/kms.tfvars new file mode 100644 index 000000000..2fbed27c2 --- /dev/null +++ b/tests/modules/cloud_function_v2/kms.tfvars @@ -0,0 +1,9 @@ +project_id = "project" +region = "region" +name = "test-cf-kms" +bucket_name = "bucket" +bundle_config = { + path = "gs://assets/sample-function.zip" +} +kms_key = "kms_key_id" +docker_repository_id = "artifact_registry_id" diff --git a/tests/modules/cloud_function_v2/kms.yaml b/tests/modules/cloud_function_v2/kms.yaml new file mode 100644 index 000000000..882ac992a --- /dev/null +++ b/tests/modules/cloud_function_v2/kms.yaml @@ -0,0 +1,44 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + google_cloudfunctions2_function.function: + build_config: + - docker_repository: artifact_registry_id + source: + - repo_source: [] + storage_source: + - bucket: bucket + object: sample-function.zip + kms_key_name: kms_key_id + name: test-cf-kms + project: project + location: region + service_config: + - service_account_email: test-cf-kms@project.iam.gserviceaccount.com + +counts: + google_cloudfunctions2_function: 1 + +outputs: + bucket: null + bucket_name: bucket + function: __missing__ + function_name: test-cf-kms + id: __missing__ + invoke_command: __missing__ + service_account: __missing__ + service_account_email: test-cf-kms@project.iam.gserviceaccount.com + service_account_iam_email: serviceAccount:test-cf-kms@project.iam.gserviceaccount.com + vpc_connector: null diff --git a/tests/modules/cloud_function_v2/tftest.yaml b/tests/modules/cloud_function_v2/tftest.yaml new file mode 100644 index 000000000..1ed90ec39 --- /dev/null +++ b/tests/modules/cloud_function_v2/tftest.yaml @@ -0,0 +1,21 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +module: modules/cloud-function-v2 +tests: + context: + context-subnet: + context-subnet-project: + kms: + vpcconnector: diff --git a/tests/modules/cloud_function_v2/vpcconnector.tfvars b/tests/modules/cloud_function_v2/vpcconnector.tfvars new file mode 100644 index 000000000..2df2acf7b --- /dev/null +++ b/tests/modules/cloud_function_v2/vpcconnector.tfvars @@ -0,0 +1,11 @@ +project_id = "test-project" +region = "region" +name = "test-cf-vpc" +bucket_name = "bucket" +bundle_config = { + path = "gs://assets/sample-function.zip" +} +vpc_connector = { + name = "projects/test-project/locations/region/connectors/vpc-connector" + egress_settings = "ALL_TRAFFIC" +} diff --git a/tests/modules/cloud_function_v2/vpcconnector.yaml b/tests/modules/cloud_function_v2/vpcconnector.yaml new file mode 100644 index 000000000..d66ace823 --- /dev/null +++ b/tests/modules/cloud_function_v2/vpcconnector.yaml @@ -0,0 +1,44 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + google_cloudfunctions2_function.function: + build_config: + - source: + - repo_source: [] + storage_source: + - bucket: bucket + object: sample-function.zip + name: test-cf-vpc + project: test-project + location: region + service_config: + - service_account_email: test-cf-vpc@test-project.iam.gserviceaccount.com + vpc_connector: projects/test-project/locations/region/connectors/vpc-connector + vpc_connector_egress_settings: ALL_TRAFFIC + +counts: + google_cloudfunctions2_function: 1 + +outputs: + bucket: null + bucket_name: bucket + function: __missing__ + function_name: test-cf-vpc + id: __missing__ + invoke_command: __missing__ + service_account: __missing__ + service_account_email: test-cf-vpc@test-project.iam.gserviceaccount.com + service_account_iam_email: serviceAccount:test-cf-vpc@test-project.iam.gserviceaccount.com + vpc_connector: null diff --git a/tests/modules/cloud_run_v2/examples/service-vpc-access-connector.yaml b/tests/modules/cloud_run_v2/examples/service-vpc-access-connector.yaml index 4c94468c7..bee8ea643 100644 --- a/tests/modules/cloud_run_v2/examples/service-vpc-access-connector.yaml +++ b/tests/modules/cloud_run_v2/examples/service-vpc-access-connector.yaml @@ -14,7 +14,7 @@ values: module.cloud_run.google_cloud_run_v2_service.service[0]: - location: europe-west8 + location: europe-west9 name: hello project: project-id template: @@ -42,4 +42,3 @@ counts: resources: 2 outputs: {} - diff --git a/tools/duplicate-diff.py b/tools/duplicate-diff.py index c22c93b48..2628c0f9f 100755 --- a/tools/duplicate-diff.py +++ b/tools/duplicate-diff.py @@ -29,6 +29,10 @@ duplicates = [ # "fast/stages/2-networking-b-nva/data/cidrs.yaml", "fast/stages/2-networking-c-separate-envs/data/cidrs.yaml", ], + [ + "modules/cloud-function-v1/bundle.tf", + "modules/cloud-function-v2/bundle.tf", + ], [ "modules/cloud-function-v1/serviceaccount.tf", "modules/cloud-function-v2/serviceaccount.tf", @@ -38,9 +42,13 @@ duplicates = [ # "modules/cloud-function-v2/variables-serviceaccount.tf", ], [ - "modules/cloud-function-v1/bundle.tf", - "modules/cloud-function-v2/bundle.tf", - ] + "modules/cloud-function-v1/variables-vpcconnector.tf", + "modules/cloud-function-v2/variables-vpcconnector.tf", + ], + [ + "modules/cloud-function-v1/vpcconnector.tf", + "modules/cloud-function-v2/vpcconnector.tf", + ], ]