diff --git a/modules/cloud-function-v1/README.md b/modules/cloud-function-v1/README.md index 5fb264ace4..d5431854a6 100644 --- a/modules/cloud-function-v1/README.md +++ b/modules/cloud-function-v1/README.md @@ -17,6 +17,7 @@ Cloud Function management, with support for IAM roles, optional bucket creation - [Using CMEK to encrypt function resources](#using-cmek-to-encrypt-function-resources) - [Variables](#variables) - [Outputs](#outputs) +- [Fixtures](#fixtures) ## TODO @@ -33,14 +34,14 @@ This deploys a Cloud Function with an HTTP endpoint, using a pre-existing GCS bu module "cf-http" { source = "./fabric/modules/cloud-function-v1" project_id = var.project_id - region = "europe-west1" + region = var.regions.secondary name = "test-cf-http" bucket_name = var.bucket bundle_config = { path = "assets/sample-function/" } } -# tftest modules=1 resources=2 e2e +# tftest modules=1 resources=5 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e ``` ### PubSub and non-HTTP triggers @@ -50,19 +51,19 @@ Other trigger types other than HTTP are configured via the `trigger_config` vari ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v1" - project_id = "my-project" - region = "europe-west1" + project_id = var.project_id + region = var.regions.secondary name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { path = "assets/sample-function/" } trigger_config = { event = "google.pubsub.topic.publish" - resource = "local.my-topic" + resource = module.pubsub.topic.name } } -# tftest modules=1 resources=2 +# tftest modules=2 resources=7 fixtures=fixtures/pubsub.tf,fixtures/functions-default-sa-iam-grants.tf e2e ``` ### Controlling HTTP access @@ -72,10 +73,10 @@ To allow anonymous access to the function, grant the `roles/cloudfunctions.invok ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v1" - project_id = "my-project" - region = "europe-west1" + project_id = var.project_id + region = var.regions.secondary name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { path = "assets/sample-function/" } @@ -83,7 +84,7 @@ module "cf-http" { "roles/cloudfunctions.invoker" = ["allUsers"] } } -# tftest modules=1 resources=3 inventory=iam.yaml +# tftest modules=1 resources=6 fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=iam.yaml e2e ``` ### GCS bucket creation @@ -93,19 +94,20 @@ You can have the module auto-create the GCS bucket used for deployment via the ` ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v1" - project_id = "my-project" - region = "europe-west1" - prefix = "my-prefix" + project_id = var.project_id + region = var.regions.secondary + prefix = var.prefix name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bucket_config = { + force_destroy = true lifecycle_delete_age_days = 1 } bundle_config = { path = "assets/sample-function/" } } -# tftest modules=1 resources=3 inventory=bucket-creation.yaml +# tftest modules=1 resources=6 fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=bucket-creation.yaml e2e ``` ### Service account management @@ -115,16 +117,16 @@ To use a custom service account managed by the module, set `service_account_crea ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v1" - project_id = "my-project" - region = "europe-west1" + project_id = var.project_id + region = var.regions.secondary name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { path = "assets/sample-function/" } service_account_create = true } -# tftest modules=1 resources=3 +# tftest modules=1 resources=6 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e ``` To use an externally managed service account, pass its email in `service_account` and leave `service_account_create` to `false` (the default). @@ -132,16 +134,16 @@ To use an externally managed service account, pass its email in `service_account ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v1" - project_id = "my-project" - region = "europe-west1" + project_id = var.project_id + region = var.regions.secondary name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { path = "assets/sample-function/" } - service_account = "non-existent@serice.account.email" + service_account = var.service_account.email } -# tftest modules=1 resources=2 +# tftest modules=1 resources=5 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e ``` ### Custom bundle config @@ -157,19 +159,19 @@ When a GCS URI or a local zip file are used, a change in their names will trigge ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v1" - project_id = "my-project" - region = "europe-west1" + project_id = var.project_id + region = var.regions.secondary name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" folder_options = { archive_path = "bundle.zip" excludes = ["__pycache__"] } } } -# tftest modules=1 resources=2 +# tftest modules=1 resources=5 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e ``` ### Private Cloud Build Pool @@ -179,16 +181,16 @@ This deploys a Cloud Function with an HTTP endpoint, using a pre-existing GCS bu ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v1" - project_id = "my-project" - region = "europe-west1" + project_id = var.project_id + region = var.regions.secondary name = "test-cf-http" - bucket_name = "test-cf-bundles" - build_worker_pool = "projects/my-project/locations/europe-west1/workerPools/my_build_worker_pool" + bucket_name = var.bucket + build_worker_pool = google_cloudbuild_worker_pool.pool.id bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } } -# tftest modules=1 resources=2 +# tftest modules=1 resources=6 fixtures=fixtures/cloudbuild-custom-pool.tf,fixtures/functions-default-sa-iam-grants.tf e2e ``` ### Multiple Cloud Functions within project @@ -198,68 +200,64 @@ When deploying multiple functions do not reuse `bundle_config.archive_path` betw ```hcl module "cf-http-one" { source = "./fabric/modules/cloud-function-v1" - project_id = "my-project" - region = "europe-west1" + project_id = var.project_id + region = var.regions.secondary name = "test-cf-http-one" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } } module "cf-http-two" { source = "./fabric/modules/cloud-function-v1" - project_id = "my-project" - region = "europe-west1" + project_id = var.project_id + region = var.regions.secondary name = "test-cf-http-two" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } } -# tftest modules=2 resources=4 inventory=multiple_functions.yaml +# tftest modules=2 resources=7 fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=multiple_functions.yaml e2e ``` ### Mounting secrets from Secret Manager This provides the latest value of the secret `var_secret` as `VARIABLE_SECRET` environment variable and three values of `path_secret` mounted in filesystem: -- `/app/secret/first` contains version 1 -- `/app/secret/second` contains version 2 -- `/app/secret/latest` contains latest version of the secret +- `/app/secret/ver1` contains version referenced by `module.secret-manager.version_versions["credentials:v1"]` ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v1" - project_id = "my-project" - region = "europe-west1" + project_id = var.project_id + region = var.regions.secondary name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } secrets = { VARIABLE_SECRET = { is_volume = false - project_id = 1234567890 - secret = "var_secret" + project_id = var.project_number # use project_number to avoid perm-diff + secret = reverse(split("/", module.secret-manager.secrets["credentials"].name))[0] versions = [ "latest" ] } "/app/secret" = { is_volume = true - project_id = 1234567890 - secret = "path_secret" + project_id = var.project_number # use project_number to avoid perm-diff + secret = reverse(split("/", module.secret-manager.secrets["credentials"].name))[0] versions = [ - "1:first", - "2:second", - "latest:latest" + "${module.secret-manager.version_versions["credentials:v1"]}:/ver1" ] } } } -# tftest modules=1 resources=2 inventory=secrets.yaml +# tftest modules=2 resources=8 fixtures=fixtures/secret-credentials.tf,fixtures/functions-default-sa-iam-grants.tf inventory=secrets.yaml e2e ``` ### Using CMEK to encrypt function resources @@ -267,51 +265,82 @@ module "cf-http" { This encrypt bucket _gcf-sources-*_ with the provided kms key. The repository has to be encrypted with the same kms key. ```hcl +module "kms" { + source = "./fabric/modules/kms" + project_id = var.project_id + keyring = { + location = var.regions.secondary + name = "function-cmek" + } + keys = { + "key" = {} + } + iam = { + "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ + "serviceAccount:service-${var.project_number}@gcf-admin-robot.iam.gserviceaccount.com", + "serviceAccount:service-${var.project_number}@gcp-sa-artifactregistry.iam.gserviceaccount.com", + "serviceAccount:service-${var.project_number}@gs-project-accounts.iam.gserviceaccount.com", + ] + } +} + +module "artifact-registry" { + source = "./fabric/modules/artifact-registry" + project_id = var.project_id + location = var.regions.secondary + name = "registry" + format = { docker = { standard = {} } } + encryption_key = module.kms.key_ids["key"] + depends_on = [ + module.kms + ] +} + module "cf-http" { source = "./fabric/modules/cloud-function-v1" - project_id = "my-project" - region = "europe-west1" + project_id = var.project_id + region = var.regions.secondary name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } - kms_key = "projects/my-project/locations/europe-west1/keyRings/mykeyring/cryptoKeys/mykey" + kms_key = module.kms.key_ids["key"] repository_settings = { - repository = "projects/my-project/locations/europe-west1/repositories/myrepo" + repository = module.artifact-registry.id } } -# tftest modules=1 resources=2 +# tftest modules=3 resources=9 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e ``` ## Variables | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [bucket_name](variables.tf#L26) | Name of the bucket that will be used for the function code. It will be created with prefix prepended if bucket_config is not null. | string | ✓ | | -| [bundle_config](variables.tf#L44) | Cloud function source. Path can point to a GCS object URI, or a local path. A local path to a zip archive will generate a GCS object using its basename, a folder will be zipped and the GCS object name inferred when not specified. | object({…}) | ✓ | | -| [name](variables.tf#L139) | Name used for cloud function and associated resources. | string | ✓ | | -| [project_id](variables.tf#L154) | Project id used for all resources. | string | ✓ | | -| [region](variables.tf#L159) | Region used for all resources. | string | ✓ | | -| [bucket_config](variables.tf#L17) | Enable and configure auto-created bucket. Set fields to null to use defaults. | object({…}) | | null | -| [build_environment_variables](variables.tf#L32) | A set of key/value environment variable pairs available during build time. | map(string) | | {} | -| [build_worker_pool](variables.tf#L38) | Build worker pool, in projects//locations//workerPools/ format. | string | | null | -| [description](variables.tf#L77) | Optional description. | string | | "Terraform managed." | -| [environment_variables](variables.tf#L83) | Cloud function environment variables. | map(string) | | {} | -| [function_config](variables.tf#L89) | Cloud function configuration. Defaults to using main as entrypoint, 1 instance with 256MiB of memory, and 180 second timeout. | object({…}) | | {…} | -| [https_security_level](variables.tf#L109) | The security level for the function: Allowed values are SECURE_ALWAYS, SECURE_OPTIONAL. | string | | null | -| [iam](variables.tf#L115) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} | -| [ingress_settings](variables.tf#L121) | Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL, ALLOW_INTERNAL_AND_GCLB and ALLOW_INTERNAL_ONLY . | string | | null | -| [kms_key](variables.tf#L127) | Resource name of a KMS crypto key (managed by the user) used to encrypt/decrypt function resources in key id format. If specified, you must also provide an artifact registry repository using the docker_repository field that was created with the same KMS crypto key. | string | | null | -| [labels](variables.tf#L133) | Resource labels. | map(string) | | {} | -| [prefix](variables.tf#L144) | Optional prefix used for resource names. | string | | null | -| [repository_settings](variables.tf#L164) | Docker Registry to use for storing the function's Docker images and specific repository. If kms_key is provided, the repository must have already been encrypted with the key. | object({…}) | | {…} | -| [secrets](variables.tf#L175) | Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format. | map(object({…})) | | {} | -| [service_account](variables.tf#L187) | Service account email. Unused if service account is auto-created. | string | | null | -| [service_account_create](variables.tf#L193) | Auto-create service account. | bool | | false | -| [trigger_config](variables.tf#L199) | Function trigger configuration. Leave null for HTTP trigger. | object({…}) | | null | -| [vpc_connector](variables.tf#L209) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | null | -| [vpc_connector_config](variables.tf#L219) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null | +| [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. | string | ✓ | | +| [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. | object({…}) | ✓ | | +| [name](variables.tf#L140) | Name used for cloud function and associated resources. | string | ✓ | | +| [project_id](variables.tf#L155) | Project id used for all resources. | string | ✓ | | +| [region](variables.tf#L160) | Region used for all resources. | string | ✓ | | +| [bucket_config](variables.tf#L17) | Enable and configure auto-created bucket. Set fields to null to use defaults. | object({…}) | | null | +| [build_environment_variables](variables.tf#L33) | A set of key/value environment variable pairs available during build time. | map(string) | | {} | +| [build_worker_pool](variables.tf#L39) | Build worker pool, in projects//locations//workerPools/ format. | string | | null | +| [description](variables.tf#L78) | Optional description. | string | | "Terraform managed." | +| [environment_variables](variables.tf#L84) | Cloud function environment variables. | map(string) | | {} | +| [function_config](variables.tf#L90) | Cloud function configuration. Defaults to using main as entrypoint, 1 instance with 256MiB of memory, and 180 second timeout. | object({…}) | | {…} | +| [https_security_level](variables.tf#L110) | The security level for the function: Allowed values are SECURE_ALWAYS, SECURE_OPTIONAL. | string | | null | +| [iam](variables.tf#L116) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} | +| [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 . | string | | null | +| [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. | string | | null | +| [labels](variables.tf#L134) | Resource labels. | map(string) | | {} | +| [prefix](variables.tf#L145) | Optional prefix used for resource names. | string | | null | +| [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. | object({…}) | | {…} | +| [secrets](variables.tf#L176) | Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format. | map(object({…})) | | {} | +| [service_account](variables.tf#L188) | Service account email. Unused if service account is auto-created. | string | | null | +| [service_account_create](variables.tf#L194) | Auto-create service account. | bool | | false | +| [trigger_config](variables.tf#L200) | Function trigger configuration. Leave null for HTTP trigger. | object({…}) | | null | +| [vpc_connector](variables.tf#L210) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | null | +| [vpc_connector_config](variables.tf#L220) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null | ## Outputs @@ -326,4 +355,11 @@ module "cf-http" { | [service_account_email](outputs.tf#L49) | Service account email. | | | [service_account_iam_email](outputs.tf#L54) | Service account email. | | | [vpc_connector](outputs.tf#L62) | VPC connector resource if created. | | + +## Fixtures + +- [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) +- [secret-credentials.tf](../../tests/fixtures/secret-credentials.tf) diff --git a/modules/cloud-function-v1/bundle.tf b/modules/cloud-function-v1/bundle.tf index 43ad5c8ee2..661ece8423 100644 --- a/modules/cloud-function-v1/bundle.tf +++ b/modules/cloud-function-v1/bundle.tf @@ -54,6 +54,7 @@ resource "google_storage_bucket" "bucket" { enabled = true } } + force_destroy = var.bucket_config.force_destroy } # compress bundle in a zip archive if it's a folder diff --git a/modules/cloud-function-v1/variables.tf b/modules/cloud-function-v1/variables.tf index 1c7c7e433d..d29d5e0cd6 100644 --- a/modules/cloud-function-v1/variables.tf +++ b/modules/cloud-function-v1/variables.tf @@ -17,8 +17,9 @@ variable "bucket_config" { description = "Enable and configure auto-created bucket. Set fields to null to use defaults." type = object({ - location = optional(string) + force_destroy = optional(bool) lifecycle_delete_age_days = optional(number) + location = optional(string) }) default = null } @@ -176,7 +177,7 @@ variable "secrets" { description = "Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format." type = map(object({ is_volume = bool - project_id = number + project_id = string secret = string versions = list(string) })) diff --git a/modules/cloud-function-v2/README.md b/modules/cloud-function-v2/README.md index 0c68b2eb17..45a9a66884 100644 --- a/modules/cloud-function-v2/README.md +++ b/modules/cloud-function-v2/README.md @@ -16,6 +16,7 @@ Cloud Function management, with support for IAM roles, optional bucket creation - [Mounting secrets from Secret Manager](#mounting-secrets-from-secret-manager) - [Variables](#variables) - [Outputs](#outputs) +- [Fixtures](#fixtures) ## TODO @@ -31,15 +32,15 @@ This deploys a Cloud Function with an HTTP endpoint, using a pre-existing GCS bu ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v2" - project_id = "my-project" + project_id = var.project_id region = var.region name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } } -# tftest modules=1 resources=2 +# tftest modules=1 resources=5 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e ``` ### PubSub and non-HTTP triggers @@ -49,10 +50,10 @@ Other trigger types other than HTTP are configured via the `trigger_config` vari ```hcl module "trigger-service-account" { source = "./fabric/modules/iam-service-account" - project_id = "my-project" + project_id = var.project_id name = "sa-cloudfunction" iam_project_roles = { - "my-project" = [ + (var.project_id) = [ "roles/run.invoker" ] } @@ -60,20 +61,20 @@ module "trigger-service-account" { module "cf-http" { source = "./fabric/modules/cloud-function-v2" - project_id = "my-project" + project_id = var.project_id region = var.region name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } trigger_config = { event_type = "google.cloud.pubsub.topic.v1.messagePublished" - pubsub_topic = "local.my-topic" + pubsub_topic = module.pubsub.topic.id service_account_email = module.trigger-service-account.email } } -# tftest modules=2 resources=4 +# tftest modules=3 resources=9 fixtures=fixtures/pubsub.tf,fixtures/functions-default-sa-iam-grants.tf e2e ``` Ensure that pubsub service identity (`service-[project number]@gcp-sa-pubsub.iam.gserviceaccount.com` has `roles/iam.serviceAccountTokenCreator` @@ -86,18 +87,18 @@ To allow anonymous access to the function, grant the `roles/run.invoker` role to ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v2" - project_id = "my-project" + project_id = var.project_id region = var.region name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } iam = { "roles/run.invoker" = ["allUsers"] } } -# tftest modules=1 resources=3 inventory=iam.yaml +# tftest modules=1 resources=6 fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=iam.yaml e2e ``` ### GCS bucket creation @@ -107,19 +108,20 @@ You can have the module auto-create the GCS bucket used for deployment via the ` ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v2" - project_id = "my-project" + project_id = var.project_id region = var.region - prefix = "my-prefix" + prefix = var.prefix name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bucket_config = { + force_destroy = true lifecycle_delete_age_days = 1 } bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } } -# tftest modules=1 resources=3 inventory=bucket-creation.yaml +# tftest modules=1 resources=6 fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=bucket-creation.yaml e2e ``` ### Service account management @@ -129,16 +131,16 @@ To use a custom service account managed by the module, set `service_account_crea ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v2" - project_id = "my-project" + project_id = var.project_id region = var.region name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } service_account_create = true } -# tftest modules=1 resources=3 +# tftest modules=1 resources=6 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e ``` To use an externally managed service account, pass its email in `service_account` and leave `service_account_create` to `false` (the default). @@ -146,16 +148,16 @@ To use an externally managed service account, pass its email in `service_account ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v2" - project_id = "my-project" + project_id = var.project_id region = var.region name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } - service_account = "non-existent@serice.account.email" + service_account = var.service_account.email } -# tftest modules=1 resources=2 +# tftest modules=1 resources=5 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e ``` ### Custom bundle config @@ -171,19 +173,19 @@ When a GCS URI or a local zip file are used, a change in their names will trigge ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v2" - project_id = "my-project" + project_id = var.project_id region = var.region name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" folder_options = { archive_path = "bundle.zip" excludes = ["__pycache__"] } } } -# tftest modules=1 resources=2 +# tftest modules=1 resources=5 fixtures=fixtures/functions-default-sa-iam-grants.tf e2e ``` ### Private Cloud Build Pool @@ -193,16 +195,16 @@ This deploys a Cloud Function with an HTTP endpoint, using a pre-existing GCS bu ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v2" - project_id = "my-project" + project_id = var.project_id region = var.region name = "test-cf-http" - bucket_name = "test-cf-bundles" - build_worker_pool = "projects/my-project/locations/europe-west1/workerPools/my_build_worker_pool" + bucket_name = var.bucket + build_worker_pool = google_cloudbuild_worker_pool.pool.id bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } } -# tftest modules=1 resources=2 +# tftest modules=1 resources=6 fixtures=fixtures/functions-default-sa-iam-grants.tf,fixtures/cloudbuild-custom-pool.tf e2e ``` ### Multiple Cloud Functions within project @@ -212,98 +214,95 @@ When deploying multiple functions via local folders do not reuse `bundle_config. ```hcl module "cf-http-one" { source = "./fabric/modules/cloud-function-v2" - project_id = "my-project" + project_id = var.project_id region = var.region name = "test-cf-http-one" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets" + path = "assets/sample-function/" } } module "cf-http-two" { source = "./fabric/modules/cloud-function-v2" - project_id = "my-project" + project_id = var.project_id region = var.region name = "test-cf-http-two" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets" + path = "assets/sample-function/" } } -# tftest modules=2 resources=4 inventory=multiple_functions.yaml +# tftest modules=2 resources=7 fixtures=fixtures/functions-default-sa-iam-grants.tf inventory=multiple_functions.yaml e2e ``` ### Mounting secrets from Secret Manager This provides the latest value of the secret `var_secret` as `VARIABLE_SECRET` environment variable and three values of `path_secret` mounted in filesystem: -- `/app/secret/first` contains version 1 -- `/app/secret/second` contains version 2 -- `/app/secret/latest` contains latest version of the secret +- `/app/secret/ver1` contains version referenced by `module.secret-manager.version_versions["credentials:v1"]` ```hcl module "cf-http" { source = "./fabric/modules/cloud-function-v2" - project_id = "my-project" + project_id = var.project_id region = var.region name = "test-cf-http" - bucket_name = "test-cf-bundles" + bucket_name = var.bucket bundle_config = { - path = "fabric/assets/" + path = "assets/sample-function/" } secrets = { VARIABLE_SECRET = { is_volume = false - project_id = 1234567890 - secret = "var_secret" + project_id = var.project_id + secret = reverse(split("/", module.secret-manager.secrets["credentials"].name))[0] versions = [ "latest" ] } "/app/secret" = { is_volume = true - project_id = 1234567890 - secret = "path_secret" + project_id = var.project_id + secret = reverse(split("/", module.secret-manager.secrets["credentials"].name))[0] versions = [ - "1:first", - "2:second", - "latest:latest" + "${module.secret-manager.version_versions["credentials:v1"]}:ver1" ] } } } -# tftest modules=1 resources=2 inventory=secrets.yaml +# tftest modules=2 resources=8 fixtures=fixtures/secret-credentials.tf,fixtures/functions-default-sa-iam-grants.tf inventory=secrets.yaml e2e ``` ## Variables | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [bucket_name](variables.tf#L26) | Name of the bucket that will be used for the function code. It will be created with prefix prepended if bucket_config is not null. | string | ✓ | | -| [bundle_config](variables.tf#L44) | Cloud function source. Path can point to a GCS object URI, or a local path. A local path to a zip archive will generate a GCS object using its basename, a folder will be zipped and the GCS object name inferred when not specified. | object({…}) | ✓ | | -| [name](variables.tf#L139) | Name used for cloud function and associated resources. | string | ✓ | | -| [project_id](variables.tf#L154) | Project id used for all resources. | string | ✓ | | -| [region](variables.tf#L159) | Region used for all resources. | string | ✓ | | -| [bucket_config](variables.tf#L17) | Enable and configure auto-created bucket. Set fields to null to use defaults. | object({…}) | | null | -| [build_service_account](variables.tf#L32) | Build service account email. | string | | null | -| [build_worker_pool](variables.tf#L38) | Build worker pool, in projects//locations//workerPools/ format. | string | | null | -| [description](variables.tf#L77) | Optional description. | string | | "Terraform managed." | -| [docker_repository_id](variables.tf#L83) | User managed repository created in Artifact Registry. | string | | null | -| [environment_variables](variables.tf#L89) | Cloud function environment variables. | map(string) | | {} | -| [function_config](variables.tf#L95) | Cloud function configuration. Defaults to using main as entrypoint, 1 instance with 256MiB of memory, and 180 second timeout. | object({…}) | | {…} | -| [iam](variables.tf#L115) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} | -| [ingress_settings](variables.tf#L121) | Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL, ALLOW_INTERNAL_AND_GCLB and ALLOW_INTERNAL_ONLY . | string | | null | -| [kms_key](variables.tf#L127) | 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_id field that was created with the same KMS crypto key. | string | | null | -| [labels](variables.tf#L133) | Resource labels. | map(string) | | {} | -| [prefix](variables.tf#L144) | Optional prefix used for resource names. | string | | null | -| [secrets](variables.tf#L164) | Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format. | map(object({…})) | | {} | -| [service_account](variables.tf#L176) | Service account email. Unused if service account is auto-created. | string | | null | -| [service_account_create](variables.tf#L182) | Auto-create service account. | bool | | false | -| [trigger_config](variables.tf#L188) | Function trigger configuration. Leave null for HTTP trigger. | object({…}) | | null | -| [vpc_connector](variables.tf#L206) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | null | -| [vpc_connector_config](variables.tf#L216) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null | +| [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. | string | ✓ | | +| [bundle_config](variables.tf#L51) | Cloud function source. Path can point to a GCS object URI, or a local path. A local path to a zip archive will generate a GCS object using its basename, a folder will be zipped and the GCS object name inferred when not specified. | object({…}) | ✓ | | +| [name](variables.tf#L148) | Name used for cloud function and associated resources. | string | ✓ | | +| [project_id](variables.tf#L163) | Project id used for all resources. | string | ✓ | | +| [region](variables.tf#L168) | Region used for all resources. | string | ✓ | | +| [bucket_config](variables.tf#L17) | Enable and configure auto-created bucket. Set fields to null to use defaults. | object({…}) | | null | +| [build_environment_variables](variables.tf#L33) | A set of key/value environment variable pairs available during build time. | map(string) | | {} | +| [build_service_account](variables.tf#L39) | Build service account email. | string | | null | +| [build_worker_pool](variables.tf#L45) | Build worker pool, in projects//locations//workerPools/ format. | string | | null | +| [description](variables.tf#L84) | Optional description. | string | | "Terraform managed." | +| [docker_repository_id](variables.tf#L90) | User managed repository created in Artifact Registry. | string | | null | +| [environment_variables](variables.tf#L96) | Cloud function environment variables. | map(string) | | {…} | +| [function_config](variables.tf#L104) | Cloud function configuration. Defaults to using main as entrypoint, 1 instance with 256MiB of memory, and 180 second timeout. | object({…}) | | {…} | +| [iam](variables.tf#L124) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} | +| [ingress_settings](variables.tf#L130) | Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL, ALLOW_INTERNAL_AND_GCLB and ALLOW_INTERNAL_ONLY . | string | | null | +| [kms_key](variables.tf#L136) | 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_id field that was created with the same KMS crypto key. | string | | null | +| [labels](variables.tf#L142) | Resource labels. | map(string) | | {} | +| [prefix](variables.tf#L153) | Optional prefix used for resource names. | string | | null | +| [secrets](variables.tf#L173) | Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format. | map(object({…})) | | {} | +| [service_account](variables.tf#L185) | Service account email. Unused if service account is auto-created. | string | | null | +| [service_account_create](variables.tf#L191) | Auto-create service account. | bool | | false | +| [trigger_config](variables.tf#L197) | Function trigger configuration. Leave null for HTTP trigger. | object({…}) | | null | +| [vpc_connector](variables.tf#L215) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | null | +| [vpc_connector_config](variables.tf#L225) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null | ## Outputs @@ -322,4 +321,11 @@ module "cf-http" { | [trigger_service_account_iam_email](outputs.tf#L72) | Service account email. | | | [uri](outputs.tf#L80) | Cloud function service uri. | | | [vpc_connector](outputs.tf#L85) | VPC connector resource if created. | | + +## Fixtures + +- [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) +- [secret-credentials.tf](../../tests/fixtures/secret-credentials.tf) diff --git a/modules/cloud-function-v2/bundle.tf b/modules/cloud-function-v2/bundle.tf index 43ad5c8ee2..661ece8423 100644 --- a/modules/cloud-function-v2/bundle.tf +++ b/modules/cloud-function-v2/bundle.tf @@ -54,6 +54,7 @@ resource "google_storage_bucket" "bucket" { enabled = true } } + force_destroy = var.bucket_config.force_destroy } # compress bundle in a zip archive if it's a folder diff --git a/modules/cloud-function-v2/main.tf b/modules/cloud-function-v2/main.tf index 0089a89996..f85c84efec 100644 --- a/modules/cloud-function-v2/main.tf +++ b/modules/cloud-function-v2/main.tf @@ -70,7 +70,7 @@ resource "google_cloudfunctions2_function" "function" { worker_pool = var.build_worker_pool runtime = var.function_config.runtime entry_point = var.function_config.entry_point - environment_variables = var.environment_variables + environment_variables = var.build_environment_variables docker_repository = var.docker_repository_id source { storage_source { diff --git a/modules/cloud-function-v2/variables.tf b/modules/cloud-function-v2/variables.tf index d347e24fda..c960aad756 100644 --- a/modules/cloud-function-v2/variables.tf +++ b/modules/cloud-function-v2/variables.tf @@ -17,8 +17,9 @@ variable "bucket_config" { description = "Enable and configure auto-created bucket. Set fields to null to use defaults." type = object({ - location = optional(string) + force_destroy = optional(bool) lifecycle_delete_age_days = optional(number) + location = optional(string) }) default = null } @@ -29,6 +30,12 @@ variable "bucket_name" { nullable = false } +variable "build_environment_variables" { + description = "A set of key/value environment variable pairs available during build time." + type = map(string) + default = {} +} + variable "build_service_account" { description = "Build service account email." type = string @@ -89,7 +96,9 @@ variable "docker_repository_id" { variable "environment_variables" { description = "Cloud function environment variables." type = map(string) - default = {} + default = { + LOG_EXECUTION_ID = "true" + } } variable "function_config" { @@ -165,7 +174,7 @@ variable "secrets" { description = "Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format." type = map(object({ is_volume = bool - project_id = number + project_id = string secret = string versions = list(string) })) @@ -198,7 +207,7 @@ variable "trigger_config" { })), []) service_account_email = optional(string) service_account_create = optional(bool, false) - retry_policy = optional(string) + retry_policy = optional(string, "RETRY_POLICY_DO_NOT_RETRY") # default to avoid permadiff }) default = null } diff --git a/tests/examples_e2e/setup_module/main.tf b/tests/examples_e2e/setup_module/main.tf index f27b90e523..b1e6005ee2 100644 --- a/tests/examples_e2e/setup_module/main.tf +++ b/tests/examples_e2e/setup_module/main.tf @@ -22,8 +22,10 @@ locals { services = [ # trimmed down list of services, to be extended as needed "alloydb.googleapis.com", - "assuredworkloads.googleapis.com", + "analyticshub.googleapis.com", "apigee.googleapis.com", + "artifactregistry.googleapis.com", + "assuredworkloads.googleapis.com", "bigquery.googleapis.com", "cloudbuild.googleapis.com", "cloudfunctions.googleapis.com", @@ -31,10 +33,16 @@ locals { "cloudresourcemanager.googleapis.com", "compute.googleapis.com", "container.googleapis.com", + "dataform.googleapis.com", + "dataplex.googleapis.com", "dataproc.googleapis.com", "dns.googleapis.com", "eventarc.googleapis.com", "iam.googleapis.com", + "logging.googleapis.com", + "monitoring.googleapis.com", + "networkconnectivity.googleapis.com", + "pubsub.googleapis.com", "run.googleapis.com", "secretmanager.googleapis.com", "servicenetworking.googleapis.com", diff --git a/tests/fixtures/cloudbuild-custom-pool.tf b/tests/fixtures/cloudbuild-custom-pool.tf new file mode 100644 index 0000000000..2ee762f091 --- /dev/null +++ b/tests/fixtures/cloudbuild-custom-pool.tf @@ -0,0 +1,26 @@ +/** + * 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. + */ + +resource "google_cloudbuild_worker_pool" "pool" { + project = var.project_id + name = "custom-pool" + location = var.regions.secondary + worker_config { + disk_size_gb = 100 + machine_type = "e2-standard-4" + no_external_ip = false + } +} diff --git a/tests/fixtures/functions-default-sa-iam-grants.tf b/tests/fixtures/functions-default-sa-iam-grants.tf new file mode 100644 index 0000000000..784a5ef264 --- /dev/null +++ b/tests/fixtures/functions-default-sa-iam-grants.tf @@ -0,0 +1,34 @@ +/** + * 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. + */ + +resource "google_project_iam_member" "bucket_default_compute_account_grant" { + project = var.project_id + member = "serviceAccount:${var.project_number}-compute@developer.gserviceaccount.com" + role = "roles/storage.objectViewer" + depends_on = [google_project_iam_member.artifact_writer] +} + +resource "google_project_iam_member" "debugging_grant" { + project = var.project_id + member = "serviceAccount:${var.project_number}-compute@developer.gserviceaccount.com" + role = "roles/logging.logWriter" +} + +resource "google_project_iam_member" "artifact_writer" { + project = var.project_id + member = "serviceAccount:${var.project_number}-compute@developer.gserviceaccount.com" + role = "roles/artifactregistry.createOnPushWriter" +} diff --git a/tests/fixtures/secret-credentials.tf b/tests/fixtures/secret-credentials.tf index 2207e6a29b..7e584041a4 100644 --- a/tests/fixtures/secret-credentials.tf +++ b/tests/fixtures/secret-credentials.tf @@ -22,7 +22,10 @@ module "secret-manager" { } iam = { credentials = { - "roles/secretmanager.secretAccessor" = ["serviceAccount:${var.project_number}-compute@developer.gserviceaccount.com"] + "roles/secretmanager.secretAccessor" = [ + "serviceAccount:${var.project_number}-compute@developer.gserviceaccount.com", + "serviceAccount:${var.project_id}@appspot.gserviceaccount.com", + ] } } versions = { diff --git a/tests/modules/cloud_function_v1/examples/bucket-creation.yaml b/tests/modules/cloud_function_v1/examples/bucket-creation.yaml index b864f908c9..9d08d9ae60 100644 --- a/tests/modules/cloud_function_v1/examples/bucket-creation.yaml +++ b/tests/modules/cloud_function_v1/examples/bucket-creation.yaml @@ -14,9 +14,9 @@ values: module.cf-http.google_cloudfunctions_function.function: - name: my-prefix-test-cf-http - project: my-project - source_archive_bucket: my-prefix-test-cf-bundles + name: test-test-cf-http + project: project-id + source_archive_bucket: test-bucket module.cf-http.google_storage_bucket.bucket[0]: lifecycle_rule: @@ -24,13 +24,13 @@ values: - type: Delete condition: - age: 1 - name: my-prefix-test-cf-bundles + name: test-bucket counts: google_cloudfunctions_function: 1 google_storage_bucket: 1 google_storage_bucket_object: 1 modules: 1 - resources: 3 + resources: 6 -outputs: {} \ No newline at end of file +outputs: {} diff --git a/tests/modules/cloud_function_v1/examples/iam.yaml b/tests/modules/cloud_function_v1/examples/iam.yaml index 363f970b6a..8473e6f3d1 100644 --- a/tests/modules/cloud_function_v1/examples/iam.yaml +++ b/tests/modules/cloud_function_v1/examples/iam.yaml @@ -17,12 +17,12 @@ values: condition: [] members: - allUsers - project: my-project - region: europe-west1 + project: project-id + region: europe-west9 role: roles/cloudfunctions.invoker counts: google_cloudfunctions_function: 1 google_storage_bucket_object: 1 modules: 1 - resources: 3 + resources: 6 diff --git a/tests/modules/cloud_function_v1/examples/multiple_functions.yaml b/tests/modules/cloud_function_v1/examples/multiple_functions.yaml index 2fa803f7db..f550b2c754 100644 --- a/tests/modules/cloud_function_v1/examples/multiple_functions.yaml +++ b/tests/modules/cloud_function_v1/examples/multiple_functions.yaml @@ -14,12 +14,12 @@ values: module.cf-http-one.google_storage_bucket_object.bundle[0]: - source: /tmp/bundle-my-project-test-cf-http-one.zip + source: /tmp/bundle-project-id-test-cf-http-one.zip module.cf-http-two.google_storage_bucket_object.bundle[0]: - source: /tmp/bundle-my-project-test-cf-http-two.zip + source: /tmp/bundle-project-id-test-cf-http-two.zip counts: google_cloudfunctions_function: 2 google_storage_bucket_object: 2 modules: 2 - resources: 4 + resources: 7 diff --git a/tests/modules/cloud_function_v1/examples/secrets.yaml b/tests/modules/cloud_function_v1/examples/secrets.yaml index 47447a62fd..dc5d432bd2 100644 --- a/tests/modules/cloud_function_v1/examples/secrets.yaml +++ b/tests/modules/cloud_function_v1/examples/secrets.yaml @@ -16,24 +16,19 @@ values: module.cf-http.google_cloudfunctions_function.function: secret_environment_variables: - key: VARIABLE_SECRET - project_id: '1234567890' - secret: var_secret + project_id: "123" # actually, project number + # secret: var_secret # known after apply version: latest secret_volumes: - mount_path: /app/secret - project_id: '1234567890' - secret: path_secret + project_id: "123" # actually, project number + # secret: path_secret # known after apply versions: - - path: first - version: '1' - - path: second - version: '2' - - path: latest - version: latest + - {} counts: google_cloudfunctions_function: 1 google_storage_bucket_object: 1 - modules: 1 - resources: 2 + modules: 2 + resources: 8 diff --git a/tests/modules/cloud_function_v2/assets/sample-function/main.py b/tests/modules/cloud_function_v2/assets/sample-function/main.py new file mode 100644 index 0000000000..0e09377c1f --- /dev/null +++ b/tests/modules/cloud_function_v2/assets/sample-function/main.py @@ -0,0 +1,20 @@ +# Copyright 2023 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. + +import functions_framework + + +@functions_framework.http +def main(request): + return "Hello World!" diff --git a/tests/modules/cloud_function_v2/examples/bucket-creation.yaml b/tests/modules/cloud_function_v2/examples/bucket-creation.yaml index abaaf32afc..1e74e9575c 100644 --- a/tests/modules/cloud_function_v2/examples/bucket-creation.yaml +++ b/tests/modules/cloud_function_v2/examples/bucket-creation.yaml @@ -17,17 +17,17 @@ values: build_config: - source: - storage_source: - - bucket: my-prefix-test-cf-bundles - name: my-prefix-test-cf-http - project: my-project + - bucket: test-bucket + name: test-test-cf-http + project: project-id module.cf-http.google_storage_bucket.bucket[0]: lifecycle_rule: - action: - type: Delete condition: - age: 1 - name: my-prefix-test-cf-bundles - project: my-project + name: test-bucket + project: project-id versioning: - enabled: true @@ -36,6 +36,6 @@ counts: google_storage_bucket: 1 google_storage_bucket_object: 1 modules: 1 - resources: 3 + resources: 6 -outputs: {} \ No newline at end of file +outputs: {} diff --git a/tests/modules/cloud_function_v2/examples/iam.yaml b/tests/modules/cloud_function_v2/examples/iam.yaml index 08dc5c430d..2720c26783 100644 --- a/tests/modules/cloud_function_v2/examples/iam.yaml +++ b/tests/modules/cloud_function_v2/examples/iam.yaml @@ -18,22 +18,20 @@ values: location: europe-west8 members: - allUsers - project: my-project + project: project-id role: roles/run.invoker service: test-cf-http module.cf-http.google_cloudfunctions2_function.function: {} module.cf-http.google_storage_bucket_object.bundle[0]: - bucket: test-cf-bundles + bucket: bucket customer_encryption: [] detect_md5hash: different hash - name: bundle-6f1ece136848fee658e335b05fe2d79d.zip - source: /tmp/bundle-my-project-test-cf-http.zip + name: bundle-95c1b0e5b92dae8333539b1e0ad5173b.zip + source: /tmp/bundle-project-id-test-cf-http.zip counts: google_cloud_run_service_iam_binding: 1 google_cloudfunctions2_function: 1 google_storage_bucket_object: 1 modules: 1 - resources: 3 - - + resources: 6 diff --git a/tests/modules/cloud_function_v2/examples/multiple_functions.yaml b/tests/modules/cloud_function_v2/examples/multiple_functions.yaml index e7cf10d540..65b7a18b9b 100644 --- a/tests/modules/cloud_function_v2/examples/multiple_functions.yaml +++ b/tests/modules/cloud_function_v2/examples/multiple_functions.yaml @@ -14,12 +14,12 @@ values: module.cf-http-one.google_storage_bucket_object.bundle[0]: - source: /tmp/bundle-my-project-test-cf-http-one.zip + source: /tmp/bundle-project-id-test-cf-http-one.zip module.cf-http-two.google_storage_bucket_object.bundle[0]: - source: /tmp/bundle-my-project-test-cf-http-two.zip + source: /tmp/bundle-project-id-test-cf-http-two.zip counts: google_cloudfunctions2_function: 2 google_storage_bucket_object: 2 modules: 2 - resources: 4 + resources: 7 diff --git a/tests/modules/cloud_function_v2/examples/secrets.yaml b/tests/modules/cloud_function_v2/examples/secrets.yaml index 1dccd340aa..77a36c8c63 100644 --- a/tests/modules/cloud_function_v2/examples/secrets.yaml +++ b/tests/modules/cloud_function_v2/examples/secrets.yaml @@ -18,24 +18,18 @@ values: service_config: - secret_environment_variables: - key: VARIABLE_SECRET - project_id: '1234567890' - secret: var_secret + project_id: project-id + # secret: var_secret # known after apply version: latest secret_volumes: - mount_path: /app/secret - project_id: '1234567890' - secret: path_secret + project_id: project-id + # secret: var_secret # known after apply versions: - - path: first - version: '1' - - path: second - version: '2' - - path: latest - version: latest + - {} counts: google_cloudfunctions2_function: 1 google_storage_bucket_object: 1 - modules: 1 - resources: 2 - + modules: 2 + resources: 8 diff --git a/tools/create_e2e_sandbox.sh b/tools/create_e2e_sandbox.sh index 206a274a74..9ce75b96b0 100755 --- a/tools/create_e2e_sandbox.sh +++ b/tools/create_e2e_sandbox.sh @@ -28,7 +28,7 @@ # set -e -DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && cd .. && pwd ) +DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && cd .. && pwd) DEST=$1 INFRA="${DEST}/infra" TIMESTAMP=$(date +%s) @@ -42,18 +42,18 @@ cp "${SETUP_MODULE}/main.tf" "${SETUP_MODULE}/variables.tf" "${SETUP_MODULE}/e2e cp "${DIR}/tests/examples/variables.tf" "${DEST}" -if [ ! -f "${INFRA}/randomizer.auto.tfvars" ] ; then - echo "suffix=0" > "${INFRA}/randomizer.auto.tfvars" - echo "timestamp=${TIMESTAMP}" >> "${INFRA}/randomizer.auto.tfvars" +if [ ! -f "${INFRA}/randomizer.auto.tfvars" ]; then + echo "suffix=0" >"${INFRA}/randomizer.auto.tfvars" + echo "timestamp=${TIMESTAMP}" >>"${INFRA}/randomizer.auto.tfvars" fi # TODO correct environment variable prefix -export | sed -e 's/^declare -x //' | grep '^TFTEST_E2E_' | sed -e 's/^TFTEST_E2E_//' > "${INFRA}/terraform.tfvars" +export | sed -e 's/^declare -x //' | grep '^TFTEST_E2E_' | sed -e 's/^TFTEST_E2E_//' >"${INFRA}/terraform.tfvars" ( - cd "${INFRA}" - terraform init - terraform apply -auto-approve - ln -sfT "${INFRA}/e2e_tests.tfvars" "${DEST}/e2e_tests.auto.tfvars" + cd "${INFRA}" + terraform init + terraform apply -auto-approve + ln -sfT "${INFRA}/e2e_tests.tfvars" "${DEST}/e2e_tests.auto.tfvars" ) -tocuh "${DEST}/main.tf" +touch "${DEST}/main.tf"