Cloud Function v1 - contexts and service account interface refactor
This commit is contained in:
@@ -28,7 +28,7 @@ Cloud Function management, with support for IAM roles, optional bucket creation
|
|||||||
|
|
||||||
### HTTP trigger
|
### HTTP trigger
|
||||||
|
|
||||||
This deploys a Cloud Function with an HTTP endpoint, using a pre-existing GCS bucket for deployment, setting the service account to the Cloud Function default one, and delegating access control to the containing project.
|
This deploys a Cloud Function with an HTTP endpoint, using a pre-existing GCS bucket for deployment, creating service account dedicated for this function, granting it `roles/logging.logWriter` and `roles/monitoring.metricWriter` roles, and delegating access control to the containing project.
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "cf-http" {
|
module "cf-http" {
|
||||||
@@ -44,7 +44,7 @@ module "cf-http" {
|
|||||||
google_project_iam_member.bucket_default_compute_account_grant,
|
google_project_iam_member.bucket_default_compute_account_grant,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
# tftest modules=1 resources=5 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e
|
# tftest fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=http-trigger.yaml e2e
|
||||||
```
|
```
|
||||||
|
|
||||||
### PubSub and non-HTTP triggers
|
### PubSub and non-HTTP triggers
|
||||||
@@ -70,7 +70,7 @@ module "cf-http" {
|
|||||||
]
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
# tftest modules=2 resources=7 fixtures=fixtures/pubsub.tf,fixtures/functions-default-sa-iam-grants.tf e2e
|
# tftest inventory=pubsub-non-http-trigger.yaml fixtures=fixtures/pubsub.tf,fixtures/functions-default-sa-iam-grants.tf e2e
|
||||||
```
|
```
|
||||||
|
|
||||||
### Controlling HTTP access
|
### Controlling HTTP access
|
||||||
@@ -125,7 +125,7 @@ module "cf-http" {
|
|||||||
|
|
||||||
### Service account management
|
### Service account management
|
||||||
|
|
||||||
To use a custom service account managed by the module, set `service_account_create` to `true` and leave `service_account` set to `null` value (default).
|
To use a custom service account managed by the module, set `service_account_config.create` to `true`.
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "cf-http" {
|
module "cf-http" {
|
||||||
@@ -137,15 +137,17 @@ module "cf-http" {
|
|||||||
bundle_config = {
|
bundle_config = {
|
||||||
path = "assets/sample-function/"
|
path = "assets/sample-function/"
|
||||||
}
|
}
|
||||||
service_account_create = true
|
service_account_config = {
|
||||||
|
create = true
|
||||||
|
}
|
||||||
depends_on = [
|
depends_on = [
|
||||||
google_project_iam_member.bucket_default_compute_account_grant,
|
google_project_iam_member.bucket_default_compute_account_grant,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
# tftest modules=1 resources=6 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e
|
# tftest inventory=service-account.yaml fixtures=fixtures/functions-default-sa-iam-grants.tf e2e
|
||||||
```
|
```
|
||||||
|
|
||||||
To use an externally managed service account, pass its email in `service_account` and leave `service_account_create` to `false` (the default).
|
To use an externally managed service account, pass its email in `service_account_config.email` and set `service_account_config.create` to `false`.
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "cf-http" {
|
module "cf-http" {
|
||||||
@@ -157,7 +159,10 @@ module "cf-http" {
|
|||||||
bundle_config = {
|
bundle_config = {
|
||||||
path = "assets/sample-function/"
|
path = "assets/sample-function/"
|
||||||
}
|
}
|
||||||
service_account = var.service_account.email
|
service_account_config = {
|
||||||
|
create = false
|
||||||
|
email = var.service_account.email
|
||||||
|
}
|
||||||
depends_on = [
|
depends_on = [
|
||||||
google_project_iam_member.bucket_default_compute_account_grant,
|
google_project_iam_member.bucket_default_compute_account_grant,
|
||||||
]
|
]
|
||||||
@@ -193,7 +198,7 @@ module "cf-http" {
|
|||||||
google_project_iam_member.bucket_default_compute_account_grant,
|
google_project_iam_member.bucket_default_compute_account_grant,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
# tftest modules=1 resources=5 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e
|
# tftest inventory=custom-bundle.yaml fixtures=fixtures/functions-default-sa-iam-grants.tf e2e
|
||||||
```
|
```
|
||||||
|
|
||||||
### Private Cloud Build Pool
|
### Private Cloud Build Pool
|
||||||
@@ -215,7 +220,7 @@ module "cf-http" {
|
|||||||
google_project_iam_member.bucket_default_compute_account_grant,
|
google_project_iam_member.bucket_default_compute_account_grant,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
# tftest modules=1 resources=6 fixtures=fixtures/cloudbuild-custom-pool.tf,fixtures/functions-default-sa-iam-grants.tf e2e
|
# tftest inventory=private-build-pool.yaml fixtures=fixtures/cloudbuild-custom-pool.tf,fixtures/functions-default-sa-iam-grants.tf e2e
|
||||||
```
|
```
|
||||||
|
|
||||||
### Multiple Cloud Functions within project
|
### Multiple Cloud Functions within project
|
||||||
@@ -256,6 +261,8 @@ This provides the latest value of the secret `var_secret` as `VARIABLE_SECRET` e
|
|||||||
|
|
||||||
- `/app/secret/ver1` contains version referenced by `module.secret-manager.version_versions["credentials:v1"]`
|
- `/app/secret/ver1` contains version referenced by `module.secret-manager.version_versions["credentials:v1"]`
|
||||||
|
|
||||||
|
Remember to grant access to secrets to the service account running Cloud Function.
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "cf-http" {
|
module "cf-http" {
|
||||||
source = "./fabric/modules/cloud-function-v1"
|
source = "./fabric/modules/cloud-function-v1"
|
||||||
@@ -288,7 +295,22 @@ module "cf-http" {
|
|||||||
google_project_iam_member.bucket_default_compute_account_grant,
|
google_project_iam_member.bucket_default_compute_account_grant,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
# tftest fixtures=fixtures/secret-credentials.tf,fixtures/functions-default-sa-iam-grants.tf inventory=secrets.yaml e2e skip-tofu
|
|
||||||
|
module "secret-manager" {
|
||||||
|
source = "./fabric/modules/secret-manager"
|
||||||
|
project_id = var.project_id
|
||||||
|
secrets = {
|
||||||
|
credentials = {
|
||||||
|
iam = {
|
||||||
|
"roles/secretmanager.secretAccessor" = [module.cf-http.service_account_iam_email]
|
||||||
|
}
|
||||||
|
versions = {
|
||||||
|
v1 = { data = "manual foo bar spam" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# tftest fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=secrets.yaml e2e skip-tofu
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using CMEK to encrypt function resources
|
### Using CMEK to encrypt function resources
|
||||||
@@ -312,7 +334,7 @@ module "project" {
|
|||||||
]
|
]
|
||||||
iam = {
|
iam = {
|
||||||
# grant compute default service account that is used by Cloud Founction
|
# grant compute default service account that is used by Cloud Founction
|
||||||
# permission to read from the buckets so it can function sources
|
# permission to read from the buckets so it can read function sources
|
||||||
"roles/storage.objectViewer" = [
|
"roles/storage.objectViewer" = [
|
||||||
"serviceAccount:${module.project.default_service_accounts.compute}"
|
"serviceAccount:${module.project.default_service_accounts.compute}"
|
||||||
]
|
]
|
||||||
@@ -369,7 +391,7 @@ module "cf-http" {
|
|||||||
repository = module.artifact-registry.id
|
repository = module.artifact-registry.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# tftest modules=4 resources=25
|
# tftest inventory=cmek.yaml
|
||||||
```
|
```
|
||||||
<!-- BEGIN TFDOC -->
|
<!-- BEGIN TFDOC -->
|
||||||
## Variables
|
## Variables
|
||||||
@@ -378,28 +400,28 @@ module "cf-http" {
|
|||||||
|---|---|:---:|:---:|:---:|
|
|---|---|:---:|:---:|:---:|
|
||||||
| [bucket_name](variables.tf#L27) | Name of the bucket that will be used for the function code. It will be created with prefix prepended if bucket_config is not null. | <code>string</code> | ✓ | |
|
| [bucket_name](variables.tf#L27) | Name of the bucket that will be used for the function code. It will be created with prefix prepended if bucket_config is not null. | <code>string</code> | ✓ | |
|
||||||
| [bundle_config](variables.tf#L45) | Cloud function source. Path can point to a GCS object URI, or a local path. A local path to a zip archive will generate a GCS object using its basename, a folder will be zipped and the GCS object name inferred when not specified. | <code title="object({ path = string folder_options = optional(object({ archive_path = optional(string) excludes = optional(list(string)) }), {}) })">object({…})</code> | ✓ | |
|
| [bundle_config](variables.tf#L45) | Cloud function source. Path can point to a GCS object URI, or a local path. A local path to a zip archive will generate a GCS object using its basename, a folder will be zipped and the GCS object name inferred when not specified. | <code title="object({ path = string folder_options = optional(object({ archive_path = optional(string) excludes = optional(list(string)) }), {}) })">object({…})</code> | ✓ | |
|
||||||
| [name](variables.tf#L140) | Name used for cloud function and associated resources. | <code>string</code> | ✓ | |
|
| [name](variables.tf#L158) | Name used for cloud function and associated resources. | <code>string</code> | ✓ | |
|
||||||
| [project_id](variables.tf#L155) | Project id used for all resources. | <code>string</code> | ✓ | |
|
| [project_id](variables.tf#L173) | Project id used for all resources. | <code>string</code> | ✓ | |
|
||||||
| [region](variables.tf#L160) | Region used for all resources. | <code>string</code> | ✓ | |
|
| [region](variables.tf#L178) | Region used for all resources. | <code>string</code> | ✓ | |
|
||||||
| [bucket_config](variables.tf#L17) | Enable and configure auto-created bucket. Set fields to null to use defaults. | <code title="object({ force_destroy = optional(bool) lifecycle_delete_age_days = optional(number) location = optional(string) })">object({…})</code> | | <code>null</code> |
|
| [bucket_config](variables.tf#L17) | Enable and configure auto-created bucket. Set fields to null to use defaults. | <code title="object({ force_destroy = optional(bool) lifecycle_delete_age_days = optional(number) location = optional(string) })">object({…})</code> | | <code>null</code> |
|
||||||
| [build_environment_variables](variables.tf#L33) | A set of key/value environment variable pairs available during build time. | <code>map(string)</code> | | <code>{}</code> |
|
| [build_environment_variables](variables.tf#L33) | A set of key/value environment variable pairs available during build time. | <code>map(string)</code> | | <code>{}</code> |
|
||||||
| [build_worker_pool](variables.tf#L39) | Build worker pool, in projects/<PROJECT-ID>/locations/<REGION>/workerPools/<POOL_NAME> format. | <code>string</code> | | <code>null</code> |
|
| [build_worker_pool](variables.tf#L39) | Build worker pool, in projects/<PROJECT-ID>/locations/<REGION>/workerPools/<POOL_NAME> format. | <code>string</code> | | <code>null</code> |
|
||||||
| [description](variables.tf#L78) | Optional description. | <code>string</code> | | <code>"Terraform managed."</code> |
|
| [context](variables.tf#L78) | Context-specific interpolations. | <code title="object({ condition_vars = optional(map(map(string)), {}) # not needed here? cidr_ranges = optional(map(string), {}) custom_roles = optional(map(string), {}) iam_principals = optional(map(string), {}) kms_keys = optional(map(string), {}) locations = optional(map(string), {}) networks = optional(map(string), {}) project_ids = optional(map(string), {}) subnets = optional(map(string), {}) tag_values = optional(map(string), {}) # not needed here? })">object({…})</code> | | <code>{}</code> |
|
||||||
| [environment_variables](variables.tf#L84) | Cloud function environment variables. | <code>map(string)</code> | | <code>{}</code> |
|
| [description](variables.tf#L96) | Optional description. | <code>string</code> | | <code>"Terraform managed."</code> |
|
||||||
| [function_config](variables.tf#L90) | Cloud function configuration. Defaults to using main as entrypoint, 1 instance with 256MiB of memory, and 180 second timeout. | <code title="object({ entry_point = optional(string, "main") instance_count = optional(number, 1) memory_mb = optional(number, 256) # Memory in MB cpu = optional(string, "0.166") runtime = optional(string, "python310") timeout_seconds = optional(number, 180) })">object({…})</code> | | <code title="{ entry_point = "main" instance_count = 1 memory_mb = 256 cpu = "0.166" runtime = "python310" timeout_seconds = 180 }">{…}</code> |
|
| [environment_variables](variables.tf#L102) | Cloud function environment variables. | <code>map(string)</code> | | <code>{}</code> |
|
||||||
| [https_security_level](variables.tf#L110) | The security level for the function: Allowed values are SECURE_ALWAYS, SECURE_OPTIONAL. | <code>string</code> | | <code>null</code> |
|
| [function_config](variables.tf#L108) | Cloud function configuration. Defaults to using main as entrypoint, 1 instance with 256MiB of memory, and 180 second timeout. | <code title="object({ entry_point = optional(string, "main") instance_count = optional(number, 1) memory_mb = optional(number, 256) # Memory in MB cpu = optional(string, "0.166") runtime = optional(string, "python310") timeout_seconds = optional(number, 180) })">object({…})</code> | | <code title="{ entry_point = "main" instance_count = 1 memory_mb = 256 cpu = "0.166" runtime = "python310" timeout_seconds = 180 }">{…}</code> |
|
||||||
| [iam](variables.tf#L116) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
| [https_security_level](variables.tf#L128) | The security level for the function: Allowed values are SECURE_ALWAYS, SECURE_OPTIONAL. | <code>string</code> | | <code>null</code> |
|
||||||
| [ingress_settings](variables.tf#L122) | Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL, ALLOW_INTERNAL_AND_GCLB and ALLOW_INTERNAL_ONLY . | <code>string</code> | | <code>null</code> |
|
| [iam](variables.tf#L134) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||||
| [kms_key](variables.tf#L128) | Resource name of a KMS crypto key (managed by the user) used to encrypt/decrypt function resources in key id format. If specified, you must also provide an artifact registry repository using the docker_repository field that was created with the same KMS crypto key. | <code>string</code> | | <code>null</code> |
|
| [ingress_settings](variables.tf#L140) | Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL, ALLOW_INTERNAL_AND_GCLB and ALLOW_INTERNAL_ONLY . | <code>string</code> | | <code>null</code> |
|
||||||
| [labels](variables.tf#L134) | Resource labels. | <code>map(string)</code> | | <code>{}</code> |
|
| [kms_key](variables.tf#L146) | Resource name of a KMS crypto key (managed by the user) used to encrypt/decrypt function resources in key id format. If specified, you must also provide an artifact registry repository using the docker_repository field that was created with the same KMS crypto key. | <code>string</code> | | <code>null</code> |
|
||||||
| [prefix](variables.tf#L145) | Optional prefix used for resource names. | <code>string</code> | | <code>null</code> |
|
| [labels](variables.tf#L152) | Resource labels. | <code>map(string)</code> | | <code>{}</code> |
|
||||||
| [repository_settings](variables.tf#L165) | Docker Registry to use for storing the function's Docker images and specific repository. If kms_key is provided, the repository must have already been encrypted with the key. | <code title="object({ registry = optional(string) repository = optional(string) })">object({…})</code> | | <code title="{ registry = "ARTIFACT_REGISTRY" }">{…}</code> |
|
| [prefix](variables.tf#L163) | Optional prefix used for resource names. | <code>string</code> | | <code>null</code> |
|
||||||
| [secrets](variables.tf#L176) | Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format. | <code title="map(object({ is_volume = bool project_id = string secret = string versions = list(string) }))">map(object({…}))</code> | | <code>{}</code> |
|
| [repository_settings](variables.tf#L183) | Docker Registry to use for storing the function's Docker images and specific repository. If kms_key is provided, the repository must have already been encrypted with the key. | <code title="object({ registry = optional(string) repository = optional(string) })">object({…})</code> | | <code title="{ registry = "ARTIFACT_REGISTRY" }">{…}</code> |
|
||||||
| [service_account](variables.tf#L188) | Service account email. Unused if service account is auto-created. | <code>string</code> | | <code>null</code> |
|
| [secrets](variables.tf#L194) | Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format. | <code title="map(object({ is_volume = bool project_id = string secret = string versions = list(string) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [service_account_create](variables.tf#L194) | Auto-create service account. | <code>bool</code> | | <code>false</code> |
|
| [service_account_config](variables-serviceaccount.tf#L17) | Service account configurations. | <code title="object({ create = optional(bool, true) display_name = optional(string) email = optional(string) name = optional(string) roles = optional(list(string), [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ]) })">object({…})</code> | | <code>{}</code> |
|
||||||
| [trigger_config](variables.tf#L200) | Function trigger configuration. Leave null for HTTP trigger. | <code title="object({ event = string resource = string retry = optional(bool) })">object({…})</code> | | <code>null</code> |
|
| [trigger_config](variables.tf#L206) | Function trigger configuration. Leave null for HTTP trigger. | <code title="object({ event = string resource = string retry = optional(bool) })">object({…})</code> | | <code>null</code> |
|
||||||
| [vpc_connector](variables.tf#L210) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | <code title="object({ create = bool name = string egress_settings = string })">object({…})</code> | | <code>null</code> |
|
| [vpc_connector](variables.tf#L216) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | <code title="object({ create = optional(bool, false) name = optional(string) egress_settings = optional(string) })">object({…})</code> | | <code>{}</code> |
|
||||||
| [vpc_connector_config](variables.tf#L220) | VPC connector network configuration. Must be provided if new VPC connector is being created. | <code title="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) })) })">object({…})</code> | | <code>null</code> |
|
| [vpc_connector_config](variables.tf#L227) | VPC connector network configuration. Must be provided if new VPC connector is being created. | <code title="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) })) })">object({…})</code> | | <code>null</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
||||||
@@ -421,5 +443,4 @@ module "cf-http" {
|
|||||||
- [cloudbuild-custom-pool.tf](../../tests/fixtures/cloudbuild-custom-pool.tf)
|
- [cloudbuild-custom-pool.tf](../../tests/fixtures/cloudbuild-custom-pool.tf)
|
||||||
- [functions-default-sa-iam-grants.tf](../../tests/fixtures/functions-default-sa-iam-grants.tf)
|
- [functions-default-sa-iam-grants.tf](../../tests/fixtures/functions-default-sa-iam-grants.tf)
|
||||||
- [pubsub.tf](../../tests/fixtures/pubsub.tf)
|
- [pubsub.tf](../../tests/fixtures/pubsub.tf)
|
||||||
- [secret-credentials.tf](../../tests/fixtures/secret-credentials.tf)
|
|
||||||
<!-- END TFDOC -->
|
<!-- END TFDOC -->
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2024 Google LLC
|
* Copyright 2025 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -29,13 +29,13 @@ locals {
|
|||||||
|
|
||||||
resource "google_storage_bucket" "bucket" {
|
resource "google_storage_bucket" "bucket" {
|
||||||
count = var.bucket_config == null ? 0 : 1
|
count = var.bucket_config == null ? 0 : 1
|
||||||
project = var.project_id
|
project = local.project_id
|
||||||
name = "${local.prefix}${var.bucket_name}"
|
name = "${local.prefix}${var.bucket_name}"
|
||||||
uniform_bucket_level_access = true
|
uniform_bucket_level_access = true
|
||||||
location = (
|
location = (
|
||||||
var.bucket_config.location == null
|
var.bucket_config.location == null
|
||||||
? var.region
|
? local.location
|
||||||
: var.bucket_config.location
|
: lookup(local.ctx.locations, var.bucket_config.location, var.bucket_config.location)
|
||||||
)
|
)
|
||||||
labels = var.labels
|
labels = var.labels
|
||||||
dynamic "lifecycle_rule" {
|
dynamic "lifecycle_rule" {
|
||||||
@@ -66,7 +66,7 @@ data "archive_file" "bundle" {
|
|||||||
output_path = (
|
output_path = (
|
||||||
var.bundle_config.folder_options.archive_path != null
|
var.bundle_config.folder_options.archive_path != null
|
||||||
? pathexpand(var.bundle_config.folder_options.archive_path)
|
? pathexpand(var.bundle_config.folder_options.archive_path)
|
||||||
: "/tmp/bundle-${var.project_id}-${var.name}.zip"
|
: "/tmp/bundle-${local.project_id}-${var.name}.zip"
|
||||||
)
|
)
|
||||||
output_file_mode = "0644"
|
output_file_mode = "0644"
|
||||||
excludes = var.bundle_config.folder_options.excludes
|
excludes = var.bundle_config.folder_options.excludes
|
||||||
@@ -76,13 +76,20 @@ data "archive_file" "bundle" {
|
|||||||
|
|
||||||
resource "google_storage_bucket_object" "bundle" {
|
resource "google_storage_bucket_object" "bundle" {
|
||||||
count = local.bundle_type != "gcs" ? 1 : 0
|
count = local.bundle_type != "gcs" ? 1 : 0
|
||||||
name = try(
|
name = (
|
||||||
"bundle-${data.archive_file.bundle[0].output_md5}.zip",
|
local.bundle_type == "local-folder"
|
||||||
basename(var.bundle_config.path)
|
? "bundle-${data.archive_file.bundle[0].output_md5}.zip"
|
||||||
|
: basename(var.bundle_config.path)
|
||||||
)
|
)
|
||||||
bucket = local.bucket
|
bucket = local.bucket
|
||||||
source = try(
|
source = (
|
||||||
data.archive_file.bundle[0].output_path,
|
local.bundle_type == "local-folder"
|
||||||
pathexpand(var.bundle_config.path)
|
? data.archive_file.bundle[0].output_path
|
||||||
|
: pathexpand(var.bundle_config.path)
|
||||||
|
)
|
||||||
|
source_md5hash = (
|
||||||
|
local.bundle_type == "local-folder"
|
||||||
|
? data.archive_file.bundle[0].output_md5
|
||||||
|
: filemd5(pathexpand(var.bundle_config.path))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2022 Google LLC
|
* Copyright 2025 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -15,6 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
|
_ctx_p = "$"
|
||||||
|
ctx = {
|
||||||
|
for k, v in var.context : k => {
|
||||||
|
for kk, vv in v : "${local._ctx_p}${k}:${kk}" => vv
|
||||||
|
} if k != "condition_vars"
|
||||||
|
}
|
||||||
bucket = (
|
bucket = (
|
||||||
var.bucket_config == null
|
var.bucket_config == null
|
||||||
? var.bucket_name
|
? var.bucket_name
|
||||||
@@ -24,17 +30,14 @@ locals {
|
|||||||
: null
|
: null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
prefix = var.prefix == null ? "" : "${var.prefix}-"
|
location = lookup(local.ctx.locations, var.region, var.region)
|
||||||
service_account_email = (
|
prefix = var.prefix == null ? "" : "${var.prefix}-"
|
||||||
var.service_account_create
|
project_id = lookup(local.ctx.project_ids, var.project_id, var.project_id)
|
||||||
? google_service_account.service_account[0].email
|
|
||||||
: var.service_account
|
|
||||||
)
|
|
||||||
vpc_connector = (
|
vpc_connector = (
|
||||||
var.vpc_connector == null
|
var.vpc_connector.name == null
|
||||||
? null
|
? null
|
||||||
: (
|
: (
|
||||||
try(var.vpc_connector.create, false) == false
|
var.vpc_connector.create == false
|
||||||
? var.vpc_connector.name
|
? var.vpc_connector.name
|
||||||
: google_vpc_access_connector.connector[0].id
|
: google_vpc_access_connector.connector[0].id
|
||||||
)
|
)
|
||||||
@@ -42,12 +45,17 @@ locals {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "google_vpc_access_connector" "connector" {
|
resource "google_vpc_access_connector" "connector" {
|
||||||
count = try(var.vpc_connector.create, false) == true ? 1 : 0
|
count = var.vpc_connector.create == true ? 1 : 0
|
||||||
project = var.project_id
|
project = local.project_id
|
||||||
name = var.vpc_connector.name
|
name = var.vpc_connector.name
|
||||||
region = var.region
|
region = local.location
|
||||||
ip_cidr_range = var.vpc_connector_config.ip_cidr_range
|
ip_cidr_range = lookup(local.ctx.cidr_ranges,
|
||||||
network = var.vpc_connector_config.network
|
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)
|
max_instances = try(var.vpc_connector_config.instances.max, null)
|
||||||
min_instances = try(var.vpc_connector_config.instances.min, null)
|
min_instances = try(var.vpc_connector_config.instances.min, null)
|
||||||
max_throughput = try(var.vpc_connector_config.throughput.max, null)
|
max_throughput = try(var.vpc_connector_config.throughput.max, null)
|
||||||
@@ -55,8 +63,8 @@ resource "google_vpc_access_connector" "connector" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "google_cloudfunctions_function" "function" {
|
resource "google_cloudfunctions_function" "function" {
|
||||||
project = var.project_id
|
project = local.project_id
|
||||||
region = var.region
|
region = local.location
|
||||||
name = "${local.prefix}${var.name}"
|
name = "${local.prefix}${var.name}"
|
||||||
description = var.description
|
description = var.description
|
||||||
runtime = var.function_config.runtime
|
runtime = var.function_config.runtime
|
||||||
@@ -78,7 +86,7 @@ resource "google_cloudfunctions_function" "function" {
|
|||||||
ingress_settings = var.ingress_settings
|
ingress_settings = var.ingress_settings
|
||||||
build_worker_pool = var.build_worker_pool
|
build_worker_pool = var.build_worker_pool
|
||||||
build_environment_variables = var.build_environment_variables
|
build_environment_variables = var.build_environment_variables
|
||||||
kms_key_name = var.kms_key
|
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_registry = try(var.repository_settings.registry, "ARTIFACT_REGISTRY")
|
||||||
docker_repository = try(var.repository_settings.repository, null)
|
docker_repository = try(var.repository_settings.repository, null)
|
||||||
vpc_connector = local.vpc_connector
|
vpc_connector = local.vpc_connector
|
||||||
@@ -132,16 +140,12 @@ resource "google_cloudfunctions_function" "function" {
|
|||||||
|
|
||||||
resource "google_cloudfunctions_function_iam_binding" "default" {
|
resource "google_cloudfunctions_function_iam_binding" "default" {
|
||||||
for_each = var.iam
|
for_each = var.iam
|
||||||
project = var.project_id
|
project = local.project_id
|
||||||
region = var.region
|
region = local.location
|
||||||
cloud_function = google_cloudfunctions_function.function.id
|
cloud_function = google_cloudfunctions_function.function.id
|
||||||
role = each.key
|
role = each.key
|
||||||
members = each.value
|
members = each.value
|
||||||
}
|
lifecycle {
|
||||||
|
replace_triggered_by = [google_cloudfunctions_function.function]
|
||||||
resource "google_service_account" "service_account" {
|
}
|
||||||
count = var.service_account_create ? 1 : 0
|
|
||||||
project = var.project_id
|
|
||||||
account_id = "tf-cf-${var.name}"
|
|
||||||
display_name = "Terraform Cloud Function ${var.name}."
|
|
||||||
}
|
}
|
||||||
|
|||||||
53
modules/cloud-function-v1/serviceaccount.tf
Normal file
53
modules/cloud-function-v1/serviceaccount.tf
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
service_account_email = (
|
||||||
|
var.service_account_config.create
|
||||||
|
? google_service_account.service_account[0].email
|
||||||
|
: lookup(
|
||||||
|
local.ctx.iam_principals,
|
||||||
|
var.service_account_config.email,
|
||||||
|
var.service_account_config.email
|
||||||
|
)
|
||||||
|
)
|
||||||
|
service_account_roles = [
|
||||||
|
for role in var.service_account_config.roles
|
||||||
|
: lookup(local.ctx.custom_roles, role, role)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_service_account" "service_account" {
|
||||||
|
count = var.service_account_config.create ? 1 : 0
|
||||||
|
project = local.project_id
|
||||||
|
account_id = coalesce(var.service_account_config.name, var.name)
|
||||||
|
display_name = coalesce(
|
||||||
|
var.service_account_config.display_name,
|
||||||
|
var.service_account_config.name,
|
||||||
|
var.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_project_iam_member" "default" {
|
||||||
|
for_each = (
|
||||||
|
var.service_account_config.create
|
||||||
|
? toset(local.service_account_roles)
|
||||||
|
: toset([])
|
||||||
|
)
|
||||||
|
role = each.key
|
||||||
|
project = local.project_id
|
||||||
|
member = google_service_account.service_account[0].member
|
||||||
|
}
|
||||||
31
modules/cloud-function-v1/variables-serviceaccount.tf
Normal file
31
modules/cloud-function-v1/variables-serviceaccount.tf
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 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 "service_account_config" {
|
||||||
|
description = "Service account configurations."
|
||||||
|
type = object({
|
||||||
|
create = optional(bool, true)
|
||||||
|
display_name = optional(string)
|
||||||
|
email = optional(string)
|
||||||
|
name = optional(string)
|
||||||
|
roles = optional(list(string), [
|
||||||
|
"roles/logging.logWriter",
|
||||||
|
"roles/monitoring.metricWriter"
|
||||||
|
])
|
||||||
|
})
|
||||||
|
nullable = false
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2022 Google LLC
|
* Copyright 2025 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -75,6 +75,24 @@ variable "bundle_config" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "context" {
|
||||||
|
description = "Context-specific interpolations."
|
||||||
|
type = object({
|
||||||
|
condition_vars = optional(map(map(string)), {}) # not needed here?
|
||||||
|
cidr_ranges = optional(map(string), {})
|
||||||
|
custom_roles = optional(map(string), {})
|
||||||
|
iam_principals = optional(map(string), {})
|
||||||
|
kms_keys = optional(map(string), {})
|
||||||
|
locations = optional(map(string), {})
|
||||||
|
networks = optional(map(string), {})
|
||||||
|
project_ids = optional(map(string), {})
|
||||||
|
subnets = optional(map(string), {})
|
||||||
|
tag_values = optional(map(string), {}) # not needed here?
|
||||||
|
})
|
||||||
|
nullable = false
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
|
|
||||||
variable "description" {
|
variable "description" {
|
||||||
description = "Optional description."
|
description = "Optional description."
|
||||||
type = string
|
type = string
|
||||||
@@ -185,18 +203,6 @@ variable "secrets" {
|
|||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "service_account" {
|
|
||||||
description = "Service account email. Unused if service account is auto-created."
|
|
||||||
type = string
|
|
||||||
default = null
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "service_account_create" {
|
|
||||||
description = "Auto-create service account."
|
|
||||||
type = bool
|
|
||||||
default = false
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "trigger_config" {
|
variable "trigger_config" {
|
||||||
description = "Function trigger configuration. Leave null for HTTP trigger."
|
description = "Function trigger configuration. Leave null for HTTP trigger."
|
||||||
type = object({
|
type = object({
|
||||||
@@ -210,11 +216,12 @@ variable "trigger_config" {
|
|||||||
variable "vpc_connector" {
|
variable "vpc_connector" {
|
||||||
description = "VPC connector configuration. Set create to 'true' if a new connector needs to be created."
|
description = "VPC connector configuration. Set create to 'true' if a new connector needs to be created."
|
||||||
type = object({
|
type = object({
|
||||||
create = bool
|
create = optional(bool, false)
|
||||||
name = string
|
name = optional(string)
|
||||||
egress_settings = string
|
egress_settings = optional(string)
|
||||||
})
|
})
|
||||||
default = null
|
nullable = false
|
||||||
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "vpc_connector_config" {
|
variable "vpc_connector_config" {
|
||||||
|
|||||||
@@ -27,10 +27,9 @@ values:
|
|||||||
name: test-bucket
|
name: test-bucket
|
||||||
|
|
||||||
counts:
|
counts:
|
||||||
|
archive_file: 1
|
||||||
google_cloudfunctions_function: 1
|
google_cloudfunctions_function: 1
|
||||||
google_storage_bucket: 1
|
google_storage_bucket: 1
|
||||||
google_storage_bucket_object: 1
|
google_storage_bucket_object: 1
|
||||||
modules: 1
|
|
||||||
resources: 6
|
|
||||||
|
|
||||||
outputs: {}
|
outputs: {}
|
||||||
|
|||||||
73
tests/modules/cloud_function_v1/examples/cmek.yaml
Normal file
73
tests/modules/cloud_function_v1/examples/cmek.yaml
Normal file
@@ -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.artifact-registry.google_artifact_registry_repository.registry:
|
||||||
|
cleanup_policies: []
|
||||||
|
cleanup_policy_dry_run: null
|
||||||
|
description: Terraform-managed registry
|
||||||
|
docker_config: []
|
||||||
|
effective_labels:
|
||||||
|
goog-terraform-provisioned: 'true'
|
||||||
|
format: DOCKER
|
||||||
|
labels: null
|
||||||
|
location: europe-west9
|
||||||
|
maven_config: []
|
||||||
|
mode: STANDARD_REPOSITORY
|
||||||
|
project: test-cf-v1
|
||||||
|
remote_repository_config: []
|
||||||
|
repository_id: registry
|
||||||
|
terraform_labels:
|
||||||
|
goog-terraform-provisioned: 'true'
|
||||||
|
timeouts: null
|
||||||
|
virtual_repository_config: []
|
||||||
|
vulnerability_scanning_config:
|
||||||
|
- enablement_config: null
|
||||||
|
module.artifact-registry.google_artifact_registry_repository_iam_binding.authoritative["roles/artifactregistry.createOnPushWriter"]:
|
||||||
|
condition: []
|
||||||
|
location: europe-west9
|
||||||
|
project: test-cf-v1
|
||||||
|
role: roles/artifactregistry.createOnPushWriter
|
||||||
|
module.kms.google_kms_crypto_key.default["key-regional"]:
|
||||||
|
effective_labels:
|
||||||
|
goog-terraform-provisioned: 'true'
|
||||||
|
labels: null
|
||||||
|
name: key-regional
|
||||||
|
purpose: ENCRYPT_DECRYPT
|
||||||
|
rotation_period: null
|
||||||
|
skip_initial_version_creation: false
|
||||||
|
terraform_labels:
|
||||||
|
goog-terraform-provisioned: 'true'
|
||||||
|
timeouts: null
|
||||||
|
module.kms.google_kms_key_ring.default[0]:
|
||||||
|
location: europe-west9
|
||||||
|
name: test-keyring
|
||||||
|
project: test-cf-v1
|
||||||
|
timeouts: null
|
||||||
|
module.kms.google_kms_key_ring_iam_binding.authoritative["roles/cloudkms.cryptoKeyEncrypterDecrypter"]:
|
||||||
|
condition: []
|
||||||
|
role: roles/cloudkms.cryptoKeyEncrypterDecrypter
|
||||||
|
module.project.google_project_iam_binding.authoritative["roles/storage.objectViewer"]:
|
||||||
|
condition: []
|
||||||
|
project: test-cf-v1
|
||||||
|
role: roles/storage.objectViewer
|
||||||
|
|
||||||
|
counts:
|
||||||
|
google_artifact_registry_repository: 1
|
||||||
|
google_artifact_registry_repository_iam_binding: 1
|
||||||
|
google_cloudfunctions_function: 1
|
||||||
|
google_kms_crypto_key: 1
|
||||||
|
google_kms_key_ring: 1
|
||||||
|
google_kms_key_ring_iam_binding: 1
|
||||||
113
tests/modules/cloud_function_v1/examples/custom-bundle.yaml
Normal file
113
tests/modules/cloud_function_v1/examples/custom-bundle.yaml
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# 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_project_iam_member.artifact_writer:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:123-compute@developer.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/artifactregistry.createOnPushWriter
|
||||||
|
google_project_iam_member.bucket_default_compute_account_grant:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:123-compute@developer.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/storage.objectViewer
|
||||||
|
module.cf-http.data.archive_file.bundle[0]:
|
||||||
|
exclude_symlink_directories: null
|
||||||
|
excludes:
|
||||||
|
- __pycache__
|
||||||
|
output_file_mode: '0644'
|
||||||
|
output_path: bundle.zip
|
||||||
|
source: []
|
||||||
|
source_content: null
|
||||||
|
source_content_filename: null
|
||||||
|
source_dir: assets/sample-function/
|
||||||
|
source_file: null
|
||||||
|
type: zip
|
||||||
|
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-west9
|
||||||
|
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
|
||||||
|
vpc_connector: null
|
||||||
|
module.cf-http.google_project_iam_member.default["roles/logging.logWriter"]:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/logging.logWriter
|
||||||
|
module.cf-http.google_project_iam_member.default["roles/monitoring.metricWriter"]:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/monitoring.metricWriter
|
||||||
|
module.cf-http.google_service_account.service_account[0]:
|
||||||
|
account_id: test-cf-http
|
||||||
|
create_ignore_already_exists: null
|
||||||
|
description: null
|
||||||
|
disabled: false
|
||||||
|
display_name: test-cf-http
|
||||||
|
email: test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
timeouts: null
|
||||||
|
module.cf-http.google_storage_bucket_object.bundle[0]:
|
||||||
|
bucket: bucket
|
||||||
|
cache_control: null
|
||||||
|
content_disposition: null
|
||||||
|
content_encoding: null
|
||||||
|
content_language: null
|
||||||
|
customer_encryption: []
|
||||||
|
deletion_policy: null
|
||||||
|
detect_md5hash: null
|
||||||
|
event_based_hold: null
|
||||||
|
force_empty_content_type: null
|
||||||
|
metadata: null
|
||||||
|
retention: []
|
||||||
|
source: bundle.zip
|
||||||
|
temporary_hold: null
|
||||||
|
timeouts: null
|
||||||
|
|
||||||
|
counts:
|
||||||
|
archive_file: 1
|
||||||
|
google_cloudfunctions_function: 1
|
||||||
|
google_project_iam_member: 4
|
||||||
|
google_service_account: 1
|
||||||
|
google_storage_bucket_object: 1
|
||||||
115
tests/modules/cloud_function_v1/examples/http-trigger.yaml
Normal file
115
tests/modules/cloud_function_v1/examples/http-trigger.yaml
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# 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_project_iam_member.artifact_writer:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:123-compute@developer.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/artifactregistry.createOnPushWriter
|
||||||
|
google_project_iam_member.bucket_default_compute_account_grant:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:123-compute@developer.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/storage.objectViewer
|
||||||
|
module.cf-http.data.archive_file.bundle[0]:
|
||||||
|
exclude_symlink_directories: null
|
||||||
|
excludes: null
|
||||||
|
output_file_mode: '0644'
|
||||||
|
output_path: /tmp/bundle-project-id-test-cf-http.zip
|
||||||
|
source: []
|
||||||
|
source_content: null
|
||||||
|
source_content_filename: null
|
||||||
|
source_dir: assets/sample-function/
|
||||||
|
source_file: null
|
||||||
|
type: zip
|
||||||
|
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-west9
|
||||||
|
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
|
||||||
|
vpc_connector: null
|
||||||
|
module.cf-http.google_project_iam_member.default["roles/logging.logWriter"]:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/logging.logWriter
|
||||||
|
module.cf-http.google_project_iam_member.default["roles/monitoring.metricWriter"]:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/monitoring.metricWriter
|
||||||
|
module.cf-http.google_service_account.service_account[0]:
|
||||||
|
account_id: test-cf-http
|
||||||
|
create_ignore_already_exists: null
|
||||||
|
description: null
|
||||||
|
disabled: false
|
||||||
|
display_name: test-cf-http
|
||||||
|
email: test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
timeouts: null
|
||||||
|
module.cf-http.google_storage_bucket_object.bundle[0]:
|
||||||
|
bucket: bucket
|
||||||
|
cache_control: null
|
||||||
|
content_disposition: null
|
||||||
|
content_encoding: null
|
||||||
|
content_language: null
|
||||||
|
customer_encryption: []
|
||||||
|
deletion_policy: null
|
||||||
|
detect_md5hash: null
|
||||||
|
event_based_hold: null
|
||||||
|
force_empty_content_type: null
|
||||||
|
metadata: null
|
||||||
|
retention: []
|
||||||
|
source: /tmp/bundle-project-id-test-cf-http.zip
|
||||||
|
temporary_hold: null
|
||||||
|
timeouts: null
|
||||||
|
|
||||||
|
counts:
|
||||||
|
archive_file: 1
|
||||||
|
google_cloudfunctions_function: 1
|
||||||
|
google_project_iam_member: 4
|
||||||
|
google_service_account: 1
|
||||||
|
google_storage_bucket_object: 1
|
||||||
|
|
||||||
|
|
||||||
|
outputs: {}
|
||||||
@@ -22,7 +22,9 @@ values:
|
|||||||
role: roles/cloudfunctions.invoker
|
role: roles/cloudfunctions.invoker
|
||||||
|
|
||||||
counts:
|
counts:
|
||||||
|
archive_file: 1
|
||||||
google_cloudfunctions_function: 1
|
google_cloudfunctions_function: 1
|
||||||
|
google_cloudfunctions_function_iam_binding: 1
|
||||||
|
google_project_iam_member: 4
|
||||||
|
google_service_account: 1
|
||||||
google_storage_bucket_object: 1
|
google_storage_bucket_object: 1
|
||||||
modules: 1
|
|
||||||
resources: 6
|
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ values:
|
|||||||
source: /tmp/bundle-project-id-test-cf-http-two.zip
|
source: /tmp/bundle-project-id-test-cf-http-two.zip
|
||||||
|
|
||||||
counts:
|
counts:
|
||||||
|
archive_file: 1
|
||||||
google_cloudfunctions_function: 2
|
google_cloudfunctions_function: 2
|
||||||
|
google_project_iam_member: 6
|
||||||
|
google_service_account: 2
|
||||||
google_storage_bucket_object: 2
|
google_storage_bucket_object: 2
|
||||||
modules: 2
|
|
||||||
resources: 7
|
|
||||||
|
|||||||
125
tests/modules/cloud_function_v1/examples/private-build-pool.yaml
Normal file
125
tests/modules/cloud_function_v1/examples/private-build-pool.yaml
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
# 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_cloudbuild_worker_pool.pool:
|
||||||
|
annotations: null
|
||||||
|
display_name: null
|
||||||
|
location: europe-west9
|
||||||
|
name: custom-pool
|
||||||
|
network_config: []
|
||||||
|
private_service_connect: []
|
||||||
|
project: project-id
|
||||||
|
timeouts: null
|
||||||
|
worker_config:
|
||||||
|
- disk_size_gb: 100
|
||||||
|
machine_type: e2-standard-4
|
||||||
|
no_external_ip: false
|
||||||
|
google_project_iam_member.artifact_writer:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:123-compute@developer.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/artifactregistry.createOnPushWriter
|
||||||
|
google_project_iam_member.bucket_default_compute_account_grant:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:123-compute@developer.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/storage.objectViewer
|
||||||
|
module.cf-http.data.archive_file.bundle[0]:
|
||||||
|
exclude_symlink_directories: null
|
||||||
|
excludes: null
|
||||||
|
output_file_mode: '0644'
|
||||||
|
output_path: /tmp/bundle-project-id-test-cf-http.zip
|
||||||
|
source: []
|
||||||
|
source_content: null
|
||||||
|
source_content_filename: null
|
||||||
|
source_dir: assets/sample-function/
|
||||||
|
source_file: null
|
||||||
|
type: zip
|
||||||
|
module.cf-http.google_cloudfunctions_function.function:
|
||||||
|
available_memory_mb: 256
|
||||||
|
build_environment_variables: 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-west9
|
||||||
|
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
|
||||||
|
vpc_connector: null
|
||||||
|
module.cf-http.google_project_iam_member.default["roles/logging.logWriter"]:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/logging.logWriter
|
||||||
|
module.cf-http.google_project_iam_member.default["roles/monitoring.metricWriter"]:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/monitoring.metricWriter
|
||||||
|
module.cf-http.google_service_account.service_account[0]:
|
||||||
|
account_id: test-cf-http
|
||||||
|
create_ignore_already_exists: null
|
||||||
|
description: null
|
||||||
|
disabled: false
|
||||||
|
display_name: test-cf-http
|
||||||
|
email: test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
timeouts: null
|
||||||
|
module.cf-http.google_storage_bucket_object.bundle[0]:
|
||||||
|
bucket: bucket
|
||||||
|
cache_control: null
|
||||||
|
content_disposition: null
|
||||||
|
content_encoding: null
|
||||||
|
content_language: null
|
||||||
|
customer_encryption: []
|
||||||
|
deletion_policy: null
|
||||||
|
detect_md5hash: null
|
||||||
|
event_based_hold: null
|
||||||
|
force_empty_content_type: null
|
||||||
|
metadata: null
|
||||||
|
retention: []
|
||||||
|
source: /tmp/bundle-project-id-test-cf-http.zip
|
||||||
|
temporary_hold: null
|
||||||
|
timeouts: null
|
||||||
|
|
||||||
|
counts:
|
||||||
|
archive_file: 1
|
||||||
|
google_cloudbuild_worker_pool: 1
|
||||||
|
google_cloudfunctions_function: 1
|
||||||
|
google_project_iam_member: 4
|
||||||
|
google_service_account: 1
|
||||||
|
google_storage_bucket_object: 1
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
# 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
|
||||||
|
event_trigger:
|
||||||
|
- event_type: google.pubsub.topic.publish
|
||||||
|
resource: topic
|
||||||
|
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-west9
|
||||||
|
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: null
|
||||||
|
vpc_connector: null
|
||||||
|
module.pubsub.google_pubsub_topic.default:
|
||||||
|
effective_labels:
|
||||||
|
goog-terraform-provisioned: 'true'
|
||||||
|
ingestion_data_source_settings: []
|
||||||
|
kms_key_name: null
|
||||||
|
labels: null
|
||||||
|
message_retention_duration: null
|
||||||
|
message_transforms: []
|
||||||
|
name: topic
|
||||||
|
project: project-id
|
||||||
|
schema_settings: []
|
||||||
|
terraform_labels:
|
||||||
|
goog-terraform-provisioned: 'true'
|
||||||
|
timeouts: null
|
||||||
|
module.pubsub.google_pubsub_topic_iam_binding.authoritative["roles/pubsub.subscriber"]:
|
||||||
|
condition: []
|
||||||
|
members:
|
||||||
|
- serviceAccount:123-compute@developer.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/pubsub.subscriber
|
||||||
|
topic: topic
|
||||||
|
|
||||||
|
counts:
|
||||||
|
archive_file: 1
|
||||||
|
google_cloudfunctions_function: 1
|
||||||
|
google_project_iam_member: 4
|
||||||
|
google_pubsub_topic: 1
|
||||||
|
google_pubsub_topic_iam_binding: 1
|
||||||
|
google_service_account: 1
|
||||||
|
google_storage_bucket_object: 1
|
||||||
|
|
||||||
|
|
||||||
|
outputs: {}
|
||||||
@@ -30,5 +30,3 @@ values:
|
|||||||
counts:
|
counts:
|
||||||
google_cloudfunctions_function: 1
|
google_cloudfunctions_function: 1
|
||||||
google_storage_bucket_object: 1
|
google_storage_bucket_object: 1
|
||||||
modules: 2
|
|
||||||
resources: 8
|
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# 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-west9
|
||||||
|
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
|
||||||
|
vpc_connector: null
|
||||||
|
module.cf-http.google_project_iam_member.default["roles/logging.logWriter"]:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/logging.logWriter
|
||||||
|
module.cf-http.google_project_iam_member.default["roles/monitoring.metricWriter"]:
|
||||||
|
condition: []
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
role: roles/monitoring.metricWriter
|
||||||
|
module.cf-http.google_service_account.service_account[0]:
|
||||||
|
account_id: test-cf-http
|
||||||
|
create_ignore_already_exists: null
|
||||||
|
description: null
|
||||||
|
disabled: false
|
||||||
|
display_name: test-cf-http
|
||||||
|
email: test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
member: serviceAccount:test-cf-http@project-id.iam.gserviceaccount.com
|
||||||
|
project: project-id
|
||||||
|
timeouts: null
|
||||||
|
|
||||||
|
counts:
|
||||||
|
archive_file: 1
|
||||||
|
google_cloudfunctions_function: 1
|
||||||
|
google_project_iam_member: 4
|
||||||
|
google_service_account: 1
|
||||||
|
google_storage_bucket_object: 1
|
||||||
11
tests/modules/cloud_function_v1/kms.tfvars
Normal file
11
tests/modules/cloud_function_v1/kms.tfvars
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
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"
|
||||||
|
repository_settings = {
|
||||||
|
repository = "artifact_registry_id"
|
||||||
|
}
|
||||||
39
tests/modules/cloud_function_v1/kms.yaml
Normal file
39
tests/modules/cloud_function_v1/kms.yaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# 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:
|
||||||
|
docker_repository: artifact_registry_id
|
||||||
|
kms_key_name: kms_key_id
|
||||||
|
name: test-cf-kms
|
||||||
|
project: project
|
||||||
|
region: region
|
||||||
|
service_account_email: test-cf-kms@project.iam.gserviceaccount.com
|
||||||
|
source_archive_bucket: bucket
|
||||||
|
source_archive_object: sample-function.zip
|
||||||
|
|
||||||
|
counts:
|
||||||
|
google_cloudfunctions_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
|
||||||
17
tests/modules/cloud_function_v1/tftest.yaml
Normal file
17
tests/modules/cloud_function_v1/tftest.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# 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-v1
|
||||||
|
tests:
|
||||||
|
kms:
|
||||||
Reference in New Issue
Block a user