diff --git a/examples/push_subscription-separate-pub-sub/README.md b/examples/push_subscription-separate-pub-sub/README.md new file mode 100644 index 00000000..52e33662 --- /dev/null +++ b/examples/push_subscription-separate-pub-sub/README.md @@ -0,0 +1,35 @@ +# Simple Example + +This example illustrates how to use the `pub` and `sub` module. + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| project\_id | The project ID to manage the Pub/Sub resources | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| project\_id | The project ID | +| topic\_labels | The labels of the Pub/Sub topic created | +| topic\_name | The name of the Pub/Sub topic created | + + + +## Requirements + +The following sections describe the requirements which must be met in +order to invoke this example. The requirements of the +[root module][root-module-requirements] must be met. + +## Usage + +To provision this example, populate `terraform.tfvars` with the [required variables](#inputs) and run the following commands within +this directory: +- `terraform init` to get the plugins +- `terraform plan` to see the infrastructure plan +- `terraform apply` to apply the infrastructure build +- `terraform destroy` to destroy the built infrastructure diff --git a/examples/push_subscription-separate-pub-sub/main.tf b/examples/push_subscription-separate-pub-sub/main.tf new file mode 100644 index 00000000..8711b378 --- /dev/null +++ b/examples/push_subscription-separate-pub-sub/main.tf @@ -0,0 +1,55 @@ +/** + * Copyright 2018 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 "pub" { + source = "terraform-google-modules/pubsub/google//modules/pub" + version = "~> 7.0" + + project_id = var.project_id + topic = "cft-tf-pub-topic-cr-push" + topic_labels = { + foo_label = "foo_value" + bar_label = "bar_value" + } +} + +module "sub" { + source = "terraform-google-modules/pubsub/google//modules/sub" + version = "~> 7.0" + + project_id = var.project_id + topic = module.pub.topic + + push_subscriptions = [ + { + name = module.cloud-run.service_name + push_endpoint = module.cloud-run.service_uri + oidc_service_account_email = module.cloud-run.service_account_id.email + }, + ] +} + +module "cloud-run" { + source = "GoogleCloudPlatform/cloud-run/google//modules/v2" + version = "~> 0.17" + project_id = var.project_id + location = "us-central1" + service_name = "cr-service" + containers = [{ "container_name" = "", "container_image" = "gcr.io/design-center-container-repo/pubsub-cr-push:latest-1703" }] + service_account_project_roles = ["roles/run.invoker"] + members = ["allUsers"] + cloud_run_deletion_protection = false +} diff --git a/examples/push_subscription-separate-pub-sub/outputs.tf b/examples/push_subscription-separate-pub-sub/outputs.tf new file mode 100644 index 00000000..0d72909f --- /dev/null +++ b/examples/push_subscription-separate-pub-sub/outputs.tf @@ -0,0 +1,30 @@ +/** + * Copyright 2018 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. + */ + +output "project_id" { + value = var.project_id + description = "The project ID" +} + +output "topic_name" { + value = module.pub.topic + description = "The name of the Pub/Sub topic created" +} + +output "topic_labels" { + value = module.pub.topic_labels + description = "The labels of the Pub/Sub topic created" +} diff --git a/examples/push_subscription-separate-pub-sub/variables.tf b/examples/push_subscription-separate-pub-sub/variables.tf new file mode 100644 index 00000000..5abd8d87 --- /dev/null +++ b/examples/push_subscription-separate-pub-sub/variables.tf @@ -0,0 +1,20 @@ +/** + * Copyright 2018 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 "project_id" { + type = string + description = "The project ID to manage the Pub/Sub resources" +} diff --git a/metadata.yaml b/metadata.yaml index 5121ae47..2a587a7e 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -46,6 +46,8 @@ spec: location: examples/cloud_storage-separate-pub-sub - name: kms location: examples/kms + - name: push_subscription-separate-pub-sub + location: examples/push_subscription-separate-pub-sub - name: simple location: examples/simple - name: simple-separate-pub-sub @@ -166,12 +168,19 @@ spec: - roles/resourcemanager.projectIamAdmin - roles/bigquery.admin - roles/storage.admin + - roles/run.admin + - roles/iam.serviceAccountAdmin + - roles/iam.serviceAccountUser + - roles/resourcemanager.projectIamAdmin + - roles/logging.viewer services: - cloudresourcemanager.googleapis.com - pubsub.googleapis.com - serviceusage.googleapis.com - bigquery.googleapis.com - storage.googleapis.com + - run.googleapis.com + - iam.googleapis.com providerVersions: - source: hashicorp/google version: ">= 6.2, < 7" diff --git a/modules/pub/README.md b/modules/pub/README.md index 0eff07dc..62b33c16 100644 --- a/modules/pub/README.md +++ b/modules/pub/README.md @@ -41,6 +41,7 @@ module "pub" { |------|-------------|------|---------|:--------:| | message\_storage\_policy | A map of storage policies. Default - inherit from organization's Resource Location Restriction policy. | `map(any)` | `{}` | no | | project\_id | The project ID to manage the Pub/Sub resources. | `string` | n/a | yes | +| publisher\_service\_accounts | Service account email which required roles/pubsub.publisher role. |
list(object({
id = string
service_account = string
}))
| `[]` | no | | schema | Schema for the topic. |
object({
name = string
type = string
definition = string
encoding = string
})
| `null` | no | | topic | The Pub/Sub topic name. | `string` | n/a | yes | | topic\_kms\_key\_name | The resource name of the Cloud KMS CryptoKey to be used to protect access to messages published on this topic. | `string` | `null` | no | diff --git a/modules/pub/main.tf b/modules/pub/main.tf index 5f565cbf..167a62d8 100644 --- a/modules/pub/main.tf +++ b/modules/pub/main.tf @@ -45,3 +45,12 @@ resource "google_pubsub_topic" "topic" { } depends_on = [google_pubsub_schema.schema] } + +resource "google_pubsub_topic_iam_member" "sa_binding_publisher" { + for_each = { for i in var.publisher_service_accounts : i.id => i if i.service_account != null } + + project = var.project_id + topic = var.topic + role = "roles/pubsub.publisher" + member = "serviceAccount:${each.value.service_account}" +} diff --git a/modules/pub/metadata.display.yaml b/modules/pub/metadata.display.yaml index 9277a821..90d11eef 100644 --- a/modules/pub/metadata.display.yaml +++ b/modules/pub/metadata.display.yaml @@ -37,6 +37,9 @@ spec: project_id: name: project_id title: Project Id + publisher_service_accounts: + name: publisher_service_accounts + title: Publisher Service Accounts schema: name: schema title: Schema diff --git a/modules/pub/metadata.yaml b/modules/pub/metadata.yaml index 12786c92..d76537a5 100644 --- a/modules/pub/metadata.yaml +++ b/modules/pub/metadata.yaml @@ -42,6 +42,8 @@ spec: location: examples/cloud_storage-separate-pub-sub - name: kms location: examples/kms + - name: push_subscription-separate-pub-sub + location: examples/push_subscription-separate-pub-sub - name: simple location: examples/simple - name: simple-separate-pub-sub @@ -81,6 +83,25 @@ spec: definition = string encoding = string }) + - name: publisher_service_accounts + description: Service account email which required roles/pubsub.publisher role. + varType: |- + list(object({ + id = string + service_account = string + })) + defaultValue: [] + connections: + - source: + source: github.com/GoogleCloudPlatform/terraform-google-cloud-run//modules/v2 + version: ">= 0.13" + spec: + outputExpr: "{ \"id\": service_account_id.id, \"service_account\": service_account_id.email }" + - source: + source: github.com/terraform-google-modules/terraform-google-service-accounts//modules/simple-sa + version: ">= 4.4" + spec: + outputExpr: "{ \"id\": account_details.id, \"service_account\": account_details.email }" outputs: - name: id description: The ID of the Pub/Sub topic @@ -98,12 +119,19 @@ spec: - roles/resourcemanager.projectIamAdmin - roles/bigquery.admin - roles/storage.admin + - roles/run.admin + - roles/iam.serviceAccountAdmin + - roles/iam.serviceAccountUser + - roles/resourcemanager.projectIamAdmin + - roles/logging.viewer services: - cloudresourcemanager.googleapis.com - pubsub.googleapis.com - serviceusage.googleapis.com - bigquery.googleapis.com - storage.googleapis.com + - run.googleapis.com + - iam.googleapis.com providerVersions: - source: hashicorp/google version: ">= 6.2, < 7" diff --git a/modules/pub/variables.tf b/modules/pub/variables.tf index b9d50da6..32874a14 100644 --- a/modules/pub/variables.tf +++ b/modules/pub/variables.tf @@ -58,3 +58,12 @@ variable "schema" { description = "Schema for the topic." default = null } + +variable "publisher_service_accounts" { + type = list(object({ + id = string + service_account = string + })) + description = "Service account email which required roles/pubsub.publisher role." + default = [] +} diff --git a/modules/sub/README.md b/modules/sub/README.md index da842577..e57c4471 100644 --- a/modules/sub/README.md +++ b/modules/sub/README.md @@ -71,6 +71,7 @@ module "sub" { | Name | Description | |------|-------------| +| pull\_subscription\_env\_vars | Map of pull subscription IDs, keyed by project\_subscription name for environment variables. | | subscription\_names | The name list of Pub/Sub subscriptions | | subscription\_paths | The path list of Pub/Sub subscriptions | diff --git a/modules/sub/metadata.yaml b/modules/sub/metadata.yaml index 443c879c..1da356c0 100644 --- a/modules/sub/metadata.yaml +++ b/modules/sub/metadata.yaml @@ -42,6 +42,8 @@ spec: location: examples/cloud_storage-separate-pub-sub - name: kms location: examples/kms + - name: push_subscription-separate-pub-sub + location: examples/push_subscription-separate-pub-sub - name: simple location: examples/simple - name: simple-separate-pub-sub @@ -58,6 +60,12 @@ spec: description: The Pub/Sub topic name. varType: string required: true + connections: + - source: + source: github.com/terraform-google-modules/terraform-google-pubsub//modules/pub + version: ">= 7.0.0" + spec: + outputExpr: topic - name: push_subscriptions description: The list of the push subscriptions. varType: |- @@ -79,6 +87,12 @@ spec: enable_message_ordering = optional(bool), })) defaultValue: [] + connections: + - source: + source: github.com/GoogleCloudPlatform/terraform-google-cloud-run//modules/v2 + version: ">= 0.13" + spec: + outputExpr: "{ \"name\": apphub_service_uri.service_id, \"push_endpoint\": service_uri, \"oidc_service_account_email\": service_account_id.email }" - name: pull_subscriptions description: The list of the pull subscriptions. varType: |- @@ -98,6 +112,17 @@ spec: enable_exactly_once_delivery = optional(bool), })) defaultValue: [] + connections: + - source: + source: github.com/GoogleCloudPlatform/terraform-google-cloud-run//modules/v2 + version: ">= 0.13" + spec: + outputExpr: "{ \"name\": service_name, \"service_account\": service_account_id.email }" + - source: + source: github.com/terraform-google-modules/terraform-google-service-accounts//modules/simple-sa + version: ">= 4.4" + spec: + outputExpr: "{ \"name\": account_details.id, \"service_account\": account_details.email }" - name: bigquery_subscriptions description: The list of the Bigquery push subscriptions. varType: |- @@ -119,6 +144,12 @@ spec: minimum_backoff = optional(string) })) defaultValue: [] + connections: + - source: + source: github.com/terraform-google-modules/terraform-google-bigquery + version: ">= 10.0.0" + spec: + outputExpr: "{ \"name\": external_table_ids[0], \"table\": external_table_ids[0]}" - name: cloud_storage_subscriptions description: The list of the Cloud Storage push subscriptions. varType: |- @@ -145,6 +176,12 @@ spec: minimum_backoff = optional(string) })) defaultValue: [] + connections: + - source: + source: github.com/terraform-google-modules/terraform-google-cloud-storage//modules/simple_bucket + version: ">= 9.0.1" + spec: + outputExpr: "{ \"name\": name, \"bucket\": name}" - name: subscription_labels description: A map of labels to assign to every Pub/Sub subscription. varType: map(string) @@ -158,6 +195,8 @@ spec: varType: bool defaultValue: true outputs: + - name: pull_subscription_env_vars + description: Map of pull subscription IDs, keyed by project_subscription name for environment variables. - name: subscription_names description: The name list of Pub/Sub subscriptions - name: subscription_paths @@ -170,12 +209,19 @@ spec: - roles/resourcemanager.projectIamAdmin - roles/bigquery.admin - roles/storage.admin + - roles/run.admin + - roles/iam.serviceAccountAdmin + - roles/iam.serviceAccountUser + - roles/resourcemanager.projectIamAdmin + - roles/logging.viewer services: - cloudresourcemanager.googleapis.com - pubsub.googleapis.com - serviceusage.googleapis.com - bigquery.googleapis.com - storage.googleapis.com + - run.googleapis.com + - iam.googleapis.com providerVersions: - source: hashicorp/google version: ">= 6.2, < 7" diff --git a/modules/sub/outputs.tf b/modules/sub/outputs.tf index f214870f..81354b64 100644 --- a/modules/sub/outputs.tf +++ b/modules/sub/outputs.tf @@ -36,3 +36,10 @@ output "subscription_paths" { description = "The path list of Pub/Sub subscriptions" } +output "pull_subscription_env_vars" { + value = { + for k, v in google_pubsub_subscription.pull_subscriptions : replace(upper("${v.project}_${v.name}"), "-", "_") => v.id + } + + description = "Map of pull subscription IDs, keyed by project_subscription name for environment variables." +} diff --git a/test/integration/push_subscription-separate-pub-sub/push_subscription_separate_pub_sub_test.go b/test/integration/push_subscription-separate-pub-sub/push_subscription_separate_pub_sub_test.go new file mode 100755 index 00000000..3428a099 --- /dev/null +++ b/test/integration/push_subscription-separate-pub-sub/push_subscription_separate_pub_sub_test.go @@ -0,0 +1,60 @@ +// Copyright 2022 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. + +package push_subscription_separate_pub_sub + +import ( + "fmt" + "testing" + "time" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" +) + +func TestPushSubscriptionSeparatePubSub(t *testing.T) { + bpt := tft.NewTFBlueprintTest(t) + + bpt.DefineVerify(func(assert *assert.Assertions) { + bpt.DefaultVerify(assert) + + projectId := bpt.GetStringOutput("project_id") + + op := gcloud.Runf(t, "pubsub topics describe cft-tf-pub-topic-cr-push --project=%s", projectId) + assert.Equal(fmt.Sprintf("projects/%s/topics/cft-tf-pub-topic-cr-push", projectId), op.Get("name").String(), "has expected name") + assert.Equal("bar_value", op.Get("labels.bar_label").String(), "has expected labels") + assert.Equal("foo_value", op.Get("labels.foo_label").String(), "has expected labels") + + op = gcloud.Runf(t, "pubsub subscriptions describe cr-service --project=%s", projectId) + assert.Equal(fmt.Sprintf("projects/%s/subscriptions/cr-service", projectId), op.Get("name").String(), "has expected name") + assert.Equal(fmt.Sprintf("projects/%s/topics/cft-tf-pub-topic-cr-push", projectId), op.Get("topic").String(), "has expected topic") + // Publish a test message + message := "Hello Runner!" + publishCmd := fmt.Sprintf("pubsub topics publish cft-tf-pub-topic-cr-push --message='%s' --project=%s", message, projectId) + gcloud.Runf(t, publishCmd) + + // Wait for a short time to allow the message to be processed. Adjust if necessary. + time.Sleep(30 * time.Second) + + // Check Cloud Run logs for the message + logCmd := fmt.Sprintf("logging read \"resource.type=cloud_run_revision AND resource.labels.service_name=cr-service AND textPayload:\\\"%s\\\"\" --project=%s --limit=1", message, projectId) + logOp := gcloud.Runf(t, logCmd) + + // Assert that the log entry is found + assert.Contains(logOp.String(), message, "Cloud Run logs should contain the published message") + }) + + bpt.Test() +} diff --git a/test/setup/iam.tf b/test/setup/iam.tf index 5a41966c..93379a28 100644 --- a/test/setup/iam.tf +++ b/test/setup/iam.tf @@ -19,7 +19,12 @@ locals { "roles/pubsub.admin", "roles/resourcemanager.projectIamAdmin", "roles/bigquery.admin", - "roles/storage.admin" + "roles/storage.admin", + "roles/run.admin", + "roles/iam.serviceAccountAdmin", + "roles/iam.serviceAccountUser", + "roles/resourcemanager.projectIamAdmin", + "roles/logging.viewer" ] } diff --git a/test/setup/main.tf b/test/setup/main.tf index deaa9e15..d7069bee 100644 --- a/test/setup/main.tf +++ b/test/setup/main.tf @@ -29,6 +29,8 @@ module "project-ci-int-pubsub" { "pubsub.googleapis.com", "serviceusage.googleapis.com", "bigquery.googleapis.com", - "storage.googleapis.com" + "storage.googleapis.com", + "run.googleapis.com", + "iam.googleapis.com" ] }