diff --git a/README.md b/README.md index be33e2b..adb73e5 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ module "pubsub" { | Name | Description | Type | Default | Required | |------|-------------|:----:|:-----:|:-----:| +| create\_topic | Specify true if you want to create a topic | bool | `"true"` | no | | message\_storage\_policy | A map of storage policies. Default - inherit from organization's Resource Location Restriction policy. | map | `` | no | | project\_id | The project ID to manage the Pub/Sub resources | string | n/a | yes | | pull\_subscriptions | The list of the pull subscriptions | list(map(string)) | `` | no | diff --git a/examples/cloudiot/README.md b/examples/cloudiot/README.md new file mode 100644 index 0000000..c5b573d --- /dev/null +++ b/examples/cloudiot/README.md @@ -0,0 +1,35 @@ +# Cloud IoT Example + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| name | The name for the Cloud IoT registry | string | n/a | yes | +| project\_id | The project ID to manage the Pub/Sub resources | string | n/a | yes | +| region | The region for the IoT resources | string | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| project\_id | The project ID | +| region | The region for the IoT resources | +| registry\_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 +[cloudiot module](../../modules/cloudiot) 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/cloudiot/main.tf b/examples/cloudiot/main.tf new file mode 100644 index 0000000..aa6998f --- /dev/null +++ b/examples/cloudiot/main.tf @@ -0,0 +1,82 @@ +/** + * Copyright 2019 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. + */ + +provider "google" { + version = "~> 2.13" + region = var.region +} + +resource "tls_private_key" "private_keys" { + count = 2 + algorithm = "RSA" +} + +resource "tls_self_signed_cert" "certs" { + count = 2 + key_algorithm = "RSA" + private_key_pem = tls_private_key.private_keys[count.index].private_key_pem + subject { + common_name = "example.com" + organization = "ACME Examples, Inc" + } + validity_period_hours = 12 + allowed_uses = [] +} + +module "iot" { + source = "../../modules/cloudiot" + name = var.name + region = var.region + project_id = var.project_id + mqtt_enabled_state = "MQTT_ENABLED" + http_enabled_state = "HTTP_DISABLED" + public_key_certificates = [ + { + format = "X509_CERTIFICATE_PEM" + certificate = tls_self_signed_cert.certs[0].cert_pem + }, + { + format = "X509_CERTIFICATE_PEM" + certificate = tls_self_signed_cert.certs[1].cert_pem + }, + ] + event_notification_config = { + topic = "${var.name}-event-topic" + topic_labels = {} + create_topic = true + push_subscriptions = [] + pull_subscriptions = [ + { + name = "${var.name}-event-pull" + ack_deadline_seconds = 20 + } + ] + } + state_notification_config = { + topic = "${var.name}-state-topic" + topic_labels = {} + create_topic = true + push_subscriptions = [ + { + name = "${var.name}-state-push" + push_endpoint = "https://${var.project_id}.appspot.com/" + x-goog-version = "v1beta1" + ack_deadline_seconds = 20 + }, + ] + pull_subscriptions = [] + } +} diff --git a/examples/cloudiot/outputs.tf b/examples/cloudiot/outputs.tf new file mode 100644 index 0000000..6ee47e2 --- /dev/null +++ b/examples/cloudiot/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 "region" { + value = module.iot.region + description = "The region for the IoT resources" +} + +output "registry_name" { + value = module.iot.name + description = "The name of the Pub/Sub topic created" +} diff --git a/examples/cloudiot/variables.tf b/examples/cloudiot/variables.tf new file mode 100644 index 0000000..afc417e --- /dev/null +++ b/examples/cloudiot/variables.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. + */ + +variable "project_id" { + type = string + description = "The project ID to manage the Pub/Sub resources" +} + +variable "region" { + type = string + description = "The region for the IoT resources" +} + +variable "name" { + type = string + description = "The name for the Cloud IoT registry" +} diff --git a/kitchen.yml b/kitchen.yml index 17d9bd2..b68fc52 100644 --- a/kitchen.yml +++ b/kitchen.yml @@ -31,7 +31,11 @@ platforms: - name: local suites: - - name: default + - name: pubsub driver: name: terraform - root_module_directory: test/fixtures + root_module_directory: test/fixtures/pubsub + - name: cloudiot + driver: + name: terraform + root_module_directory: test/fixtures/cloudiot diff --git a/main.tf b/main.tf index 503db0b..536c983 100644 --- a/main.tf +++ b/main.tf @@ -19,6 +19,7 @@ locals { } resource "google_pubsub_topic" "topic" { + count = var.create_topic ? 1 : 0 project = var.project_id name = var.topic labels = var.topic_labels @@ -32,9 +33,9 @@ resource "google_pubsub_topic" "topic" { } resource "google_pubsub_subscription" "push_subscriptions" { - count = length(var.push_subscriptions) + count = var.create_topic ? length(var.push_subscriptions) : 0 name = var.push_subscriptions[count.index].name - topic = google_pubsub_topic.topic.name + topic = google_pubsub_topic.topic.0.name project = var.project_id ack_deadline_seconds = lookup( var.push_subscriptions[count.index], @@ -56,9 +57,9 @@ resource "google_pubsub_subscription" "push_subscriptions" { } resource "google_pubsub_subscription" "pull_subscriptions" { - count = length(var.pull_subscriptions) + count = var.create_topic ? length(var.pull_subscriptions) : 0 name = var.pull_subscriptions[count.index].name - topic = google_pubsub_topic.topic.name + topic = google_pubsub_topic.topic.0.name project = var.project_id ack_deadline_seconds = lookup( var.pull_subscriptions[count.index], diff --git a/modules/cloudiot/README.md b/modules/cloudiot/README.md new file mode 100644 index 0000000..f64b8a0 --- /dev/null +++ b/modules/cloudiot/README.md @@ -0,0 +1,102 @@ +# terraform-google-pubsub for Cloud IoT + +## Overview + +In the early stage, this module will simply be implemented by using [existing pubsub module](https://github.com/terraform-google-modules/terraform-google-pubsub) and [one resource](https://www.terraform.io/docs/providers/google/r/cloudiot_registry.html). + +This module may not improve drastically efficiency. However, after implementing new resources like [terraform-provider-google#1495](https://github.com/terraform-providers/terraform-provider-google/issues/1495), this module will get more efficient by adopting the new resources. + +## Usage + +Let's seeing a simple usage of the module. See also a simple setup provided in the example directory. + +```hcl +module "iot" { + source = "terraform-google-modules/pubsub/iot" + name = "sample-iot" + region = "us-central1" + project_id = "tf-project" + + mqtt_enabled_state = "MQTT_ENABLED" + http_enabled_state = "HTTP_DISABLED" + + public_key_certificates = [ + { + format = "X509_CERTIFICATE_PEM" + certificate = file(var.cert_path) + }, + ] + + event_notification_config = { + topic = "iot-event-topic" + topic_labels = {} + create_topic = true + push_subscriptions = [] + pull_subscriptions = [ + { + name = "iot-event-pull" + ack_deadline_seconds = 20 + }, + ] + } + state_notification_config = { + topic = "iot-state-topic" + topic_labels = {} + create_topic = true + push_subscriptions = [] + pull_subscriptions = [ + { + name = "iot-state-pull" + ack_deadline_seconds = 20 + }, + ] + } +} +``` + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| event\_notification\_config | The event notification configuration for the Cloud IoT registry. This contains `topic`, `topic_labels`, `pull_subscriptions` and `push_subscriptions` and `create_topic`. | object | `` | no | +| http\_enabled\_state | The field allows HTTP_ENABLED or HTTP_DISABLED | string | `"HTTP_DISABLED"` | no | +| mqtt\_enabled\_state | The field allows MQTT_ENABLED or MQTT_DISABLED | string | `"MQTT_ENABLED"` | no | +| name | The Cloud IoT registry name | string | n/a | yes | +| project\_id | The project ID to manage the Cloud IoT resources | string | n/a | yes | +| public\_key\_certificates | The list for public key certificates | object | `` | no | +| region | The region to host the registry | string | n/a | yes | +| state\_notification\_config | The state notification configuration for the Cloud IoT registry. This contains `topic`, `topic_labels`, `pull_subscriptions` and `push_subscriptions` and `create_topic`. | object | `` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| credentials | The credentials for Cloud IoT registry | +| event\_notification\_subscription\_names | The name list of Pub/Sub subscriptions associated with the registry | +| event\_notification\_subscription\_paths | The path list of Pub/Sub subscriptions associated with the registry | +| event\_notification\_topic | The name of the Pub/Sub topic associated with the registry | +| event\_notification\_topic\_id | The id of the Pub/Sub topic associated with the registry | +| name | The name of the Cloud IoT registry | +| region | The region of the Cloud IoT registry | +| registry | The registry being created by this module | +| state\_notification\_subscription\_names | The name list of Pub/Sub subscriptions associated with the registry | +| state\_notification\_subscription\_paths | The path list of Pub/Sub subscriptions associated with the registry | +| state\_notification\_topic | The name of the Pub/Sub topic associated with the registry | +| state\_notification\_topic\_id | The id of the Pub/Sub topic associated with the registry | + + + +## Requirements + +## Enable API + +In order to operate with the service account you must activate the following API on the project where the service account was created. + +- Cloud IoT API + +## Configure a Service Account + +In addition to the pubsub module's requirements, the following role should be attached to the service account. + +- Cloud IoT Editor diff --git a/modules/cloudiot/main.tf b/modules/cloudiot/main.tf new file mode 100644 index 0000000..f642c82 --- /dev/null +++ b/modules/cloudiot/main.tf @@ -0,0 +1,96 @@ +/** + * Copyright 2019 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 { + state_notification_enabled = var.state_notification_config.topic != "" ? "enabled" : "disabled" + state_notification_configs = { + disabled = null + enabled = { + pubsub_topic_name = "projects/${var.project_id}/topics/${var.state_notification_config.topic}" + } + } + state_notification_config = local.state_notification_configs[local.state_notification_enabled] + + event_notification_enabled = var.event_notification_config.topic != "" ? "enabled" : "disabled" + event_notification_configs = { + disabled = [] + enabled = [{ + pubsub_topic_name = "projects/${var.project_id}/topics/${var.event_notification_config.topic}" + }] + } + event_notification_config = local.event_notification_configs[local.event_notification_enabled] +} + +resource "google_cloudiot_registry" "default" { + name = var.name + project = var.project_id + region = var.region + + http_config = { + http_enabled_state = var.http_enabled_state + } + mqtt_config = { + mqtt_enabled_state = var.mqtt_enabled_state + } + + dynamic "event_notification_configs" { + for_each = local.event_notification_config + iterator = c + content { + pubsub_topic_name = c.value.pubsub_topic_name + } + } + + state_notification_config = local.state_notification_config + + dynamic "credentials" { + for_each = [for c in var.public_key_certificates : { + public_key_certificate = { + format = c.format + certificate = c.certificate + } + }] + content { + public_key_certificate = credentials.value.public_key_certificate + } + } + depends_on = [ + module.event_notification_topic, + module.state_notification_topic, + ] +} + +module "event_notification_topic" { + source = "../../" + project_id = var.project_id + + topic = var.event_notification_config.topic + topic_labels = var.event_notification_config.topic_labels + push_subscriptions = var.event_notification_config.push_subscriptions + pull_subscriptions = var.event_notification_config.pull_subscriptions + create_topic = var.event_notification_config.create_topic +} + +module "state_notification_topic" { + source = "../../" + project_id = var.project_id + + topic = var.state_notification_config.topic + topic_labels = var.state_notification_config.topic_labels + push_subscriptions = var.state_notification_config.push_subscriptions + pull_subscriptions = var.state_notification_config.pull_subscriptions + create_topic = var.state_notification_config.create_topic +} diff --git a/modules/cloudiot/outputs.tf b/modules/cloudiot/outputs.tf new file mode 100644 index 0000000..680880b --- /dev/null +++ b/modules/cloudiot/outputs.tf @@ -0,0 +1,75 @@ +/** + * Copyright 2019 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 "name" { + value = google_cloudiot_registry.default.name + description = "The name of the Cloud IoT registry" +} + +output "registry" { + value = google_cloudiot_registry.default + description = "The registry being created by this module" +} + +output "region" { + value = google_cloudiot_registry.default.region + description = "The region of the Cloud IoT registry" +} + +output "credentials" { + value = google_cloudiot_registry.default.credentials.* + description = "The credentials for Cloud IoT registry" +} + +output "event_notification_topic" { + value = module.event_notification_topic.topic + description = "The name of the Pub/Sub topic associated with the registry" +} + +output "event_notification_topic_id" { + value = module.event_notification_topic.id + description = "The id of the Pub/Sub topic associated with the registry" +} + +output "event_notification_subscription_names" { + value = module.event_notification_topic.subscription_names + description = "The name list of Pub/Sub subscriptions associated with the registry" +} + +output "event_notification_subscription_paths" { + value = module.event_notification_topic.subscription_paths + description = "The path list of Pub/Sub subscriptions associated with the registry" +} + +output "state_notification_topic" { + value = module.state_notification_topic.topic + description = "The name of the Pub/Sub topic associated with the registry" +} + +output "state_notification_topic_id" { + value = module.state_notification_topic.id + description = "The id of the Pub/Sub topic associated with the registry" +} + +output "state_notification_subscription_names" { + value = module.state_notification_topic.subscription_names + description = "The name list of Pub/Sub subscriptions associated with the registry" +} + +output "state_notification_subscription_paths" { + value = module.state_notification_topic.subscription_paths + description = "The path list of Pub/Sub subscriptions associated with the registry" +} diff --git a/modules/cloudiot/variables.tf b/modules/cloudiot/variables.tf new file mode 100644 index 0000000..938c364 --- /dev/null +++ b/modules/cloudiot/variables.tf @@ -0,0 +1,84 @@ +/** + * Copyright 2019 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 Cloud IoT resources" +} + +variable "region" { + type = string + description = "The region to host the registry" +} + +variable "name" { + type = string + description = "The Cloud IoT registry name" +} + +variable "mqtt_enabled_state" { + type = string + description = "The field allows MQTT_ENABLED or MQTT_DISABLED" + default = "MQTT_ENABLED" +} + +variable "http_enabled_state" { + type = string + description = "The field allows HTTP_ENABLED or HTTP_DISABLED" + default = "HTTP_DISABLED" +} + +variable "public_key_certificates" { + type = list(object({ format = string, certificate = string })) + description = "The list for public key certificates" + default = [] +} + +variable "event_notification_config" { + type = object({ + topic = string + topic_labels = map(string) + push_subscriptions = list(map(string)) + pull_subscriptions = list(map(string)) + create_topic = bool + }) + description = "The event notification configuration for the Cloud IoT registry. This contains `topic`, `topic_labels`, `pull_subscriptions` and `push_subscriptions` and `create_topic`." + default = { + topic = "" + topic_labels = {} + push_subscriptions = [] + pull_subscriptions = [] + create_topic = false + } +} + +variable "state_notification_config" { + type = object({ + topic = string + topic_labels = map(string) + push_subscriptions = list(map(string)) + pull_subscriptions = list(map(string)) + create_topic = bool + }) + description = "The state notification configuration for the Cloud IoT registry. This contains `topic`, `topic_labels`, `pull_subscriptions` and `push_subscriptions` and `create_topic`." + default = { + topic = "" + topic_labels = {} + push_subscriptions = [] + pull_subscriptions = [] + create_topic = false + } +} diff --git a/outputs.tf b/outputs.tf index 75054c5..5dfd865 100644 --- a/outputs.tf +++ b/outputs.tf @@ -15,22 +15,22 @@ */ output "topic" { - value = google_pubsub_topic.topic.name + value = google_pubsub_topic.topic.0.name description = "The name of the Pub/Sub topic" } output "topic_labels" { - value = google_pubsub_topic.topic.labels + value = google_pubsub_topic.topic.0.labels description = "Labels assigned to the Pub/Sub topic" } output "id" { - value = google_pubsub_topic.topic.id + value = google_pubsub_topic.topic.0.id description = "The ID of the Pub/Sub topic" } output "uri" { - value = "pubsub.googleapis.com/${google_pubsub_topic.topic.id}" + value = "pubsub.googleapis.com/${google_pubsub_topic.topic.0.id}" description = "The URI of the Pub/Sub topic" } diff --git a/test/fixtures/cloudiot/main.tf b/test/fixtures/cloudiot/main.tf new file mode 100644 index 0000000..875b505 --- /dev/null +++ b/test/fixtures/cloudiot/main.tf @@ -0,0 +1,22 @@ +/** + * Copyright 2019 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 "iot" { + source = "../../../examples/cloudiot" + project_id = var.project_id + name = "cft-ci-iot-registry" + region = "us-central1" +} diff --git a/test/fixtures/cloudiot/outputs.tf b/test/fixtures/cloudiot/outputs.tf new file mode 100644 index 0000000..e2eb08a --- /dev/null +++ b/test/fixtures/cloudiot/outputs.tf @@ -0,0 +1,30 @@ +/** + * Copyright 2019 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 "registry_name" { + value = module.iot.registry_name + description = "The name of the IoT registry" +} + +output "region" { + value = module.iot.region + description = "The region of the IoT registry" +} diff --git a/test/fixtures/cloudiot/variables.tf b/test/fixtures/cloudiot/variables.tf new file mode 100644 index 0000000..349ac12 --- /dev/null +++ b/test/fixtures/cloudiot/variables.tf @@ -0,0 +1,20 @@ +/** + * Copyright 2019 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 to run tests against" +} diff --git a/test/fixtures/main.tf b/test/fixtures/pubsub/main.tf similarity index 81% rename from test/fixtures/main.tf rename to test/fixtures/pubsub/main.tf index 6afd34e..fce6fda 100644 --- a/test/fixtures/main.tf +++ b/test/fixtures/pubsub/main.tf @@ -14,14 +14,10 @@ * limitations under the License. */ -resource "random_id" "random_suffix" { - byte_length = 2 -} - module "example" { - source = "../../examples/simple" + source = "../../../examples/simple" project_id = var.project_id - topic_name = "ci-int-topic-${random_id.random_suffix.hex}" + topic_name = "cft-tf-pubsub-topic" topic_labels = { foo_label = "foo_value" bar_label = "bar_value" diff --git a/test/fixtures/outputs.tf b/test/fixtures/pubsub/outputs.tf similarity index 100% rename from test/fixtures/outputs.tf rename to test/fixtures/pubsub/outputs.tf diff --git a/test/fixtures/variables.tf b/test/fixtures/pubsub/variables.tf similarity index 100% rename from test/fixtures/variables.tf rename to test/fixtures/pubsub/variables.tf diff --git a/test/integration/cloudiot/controls/iot.rb b/test/integration/cloudiot/controls/iot.rb new file mode 100644 index 0000000..fe37c83 --- /dev/null +++ b/test/integration/cloudiot/controls/iot.rb @@ -0,0 +1,53 @@ +# Copyright 2019 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 +# +# https://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. + +project_id = attribute('project_id') +registry = attribute('registry_name') +region = attribute('region') +event_topic = "#{registry}-event-topic" +state_topic = "#{registry}-state-topic" + +describe command("gcloud --project='#{project_id}' iot registries describe #{registry} --region=#{region} --format=json") do + let(:stdout) { JSON.parse(subject.stdout, symbolize_names: true) } + its(:exit_status) { should be_zero } + it { expect(stdout).to include(name: "projects/#{project_id}/locations/#{region}/registries/#{registry}") } +end + +describe command("gcloud --project='#{project_id}' pubsub topics describe #{event_topic} --format=json") do + let(:stdout) { JSON.parse(subject.stdout, symbolize_names: true) } + its(:exit_status) { should be_zero } + it { expect(stdout).to include(name: "projects/#{project_id}/topics/#{event_topic}") } +end + +describe command("gcloud --project='#{project_id}' pubsub topics describe #{state_topic} --format=json") do + let(:stdout) { JSON.parse(subject.stdout, symbolize_names: true) } + its(:exit_status) { should be_zero } + it { expect(stdout).to include(name: "projects/#{project_id}/topics/#{state_topic}") } +end + +describe command("gcloud --project='#{project_id}' pubsub subscriptions describe #{registry}-event-pull --format=json") do + let(:stdout) { JSON.parse(subject.stdout, symbolize_names: true) } + its(:exit_status) { should be_zero } + it { expect(stdout).to include(name: "projects/#{project_id}/subscriptions/#{registry}-event-pull") } + it { expect(stdout).to include(topic: "projects/#{project_id}/topics/#{event_topic}") } + it { expect(stdout).to include(ackDeadlineSeconds: 20) } +end + +describe command("gcloud --project='#{project_id}' pubsub subscriptions describe #{registry}-state-push --format=json") do + let(:stdout) { JSON.parse(subject.stdout, symbolize_names: true) } + its(:exit_status) { should be_zero } + it { expect(stdout).to include(name: "projects/#{project_id}/subscriptions/#{registry}-state-push") } + it { expect(stdout).to include(topic: "projects/#{project_id}/topics/#{state_topic}") } + it { expect(stdout).to include(ackDeadlineSeconds: 20) } +end diff --git a/test/integration/cloudiot/inspec.yml b/test/integration/cloudiot/inspec.yml new file mode 100644 index 0000000..814358c --- /dev/null +++ b/test/integration/cloudiot/inspec.yml @@ -0,0 +1,28 @@ +# Copyright 2019 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. + +name: cloud-iot +title: Google Cloud IoT +version: 0.1.0 +inspec_version: '~> 3.9.3' +attributes: + - name: project_id + type: string + required: true + - name: registry_name + type: string + required: true + - name: region + type: string + required: true diff --git a/test/integration/default/controls/pubsub.rb b/test/integration/pubsub/controls/pubsub.rb similarity index 100% rename from test/integration/default/controls/pubsub.rb rename to test/integration/pubsub/controls/pubsub.rb diff --git a/test/integration/default/inspec.yml b/test/integration/pubsub/inspec.yml similarity index 94% rename from test/integration/default/inspec.yml rename to test/integration/pubsub/inspec.yml index 6e861c7..2052e44 100644 --- a/test/integration/default/inspec.yml +++ b/test/integration/pubsub/inspec.yml @@ -14,6 +14,8 @@ name: cloud-pubsub title: Google Cloud Pub/Sub +version: 0.1.0 +inspec_version: '~> 3.9.3' attributes: - name: project_id type: string diff --git a/test/setup/iam.tf b/test/setup/iam.tf index 60eb753..adf9d1b 100644 --- a/test/setup/iam.tf +++ b/test/setup/iam.tf @@ -16,7 +16,8 @@ locals { int_required_roles = [ - "roles/pubsub.editor", + "roles/cloudiot.admin", + "roles/pubsub.editor" ] } @@ -41,3 +42,13 @@ resource "google_project_iam_member" "int_test" { resource "google_service_account_key" "int_test" { service_account_id = google_service_account.int_test.id } + +// Even if granting roles/cloudiot.admin to the service account in advance, +// the roles cannot be applied immediately. As a result, our test will fail. +// To avoid that, we use null_resource for `sleep`ing 60 seconds. +resource "null_resource" "delay" { + provisioner "local-exec" { + command = "sleep 60" + } + depends_on = [google_project_iam_member.int_test] +} diff --git a/test/setup/main.tf b/test/setup/main.tf index 9fa5b0f..356d0af 100644 --- a/test/setup/main.tf +++ b/test/setup/main.tf @@ -25,6 +25,7 @@ module "project-ci-int-pubsub" { billing_account = var.billing_account activate_apis = [ + "cloudiot.googleapis.com", "cloudresourcemanager.googleapis.com", "pubsub.googleapis.com", "serviceusage.googleapis.com" diff --git a/test/setup/make_source.sh b/test/setup/make_source.sh index ffdc48e..ae7798a 100755 --- a/test/setup/make_source.sh +++ b/test/setup/make_source.sh @@ -20,5 +20,5 @@ project_id=$(terraform output project_id) echo "export TF_VAR_project_id='$project_id'" >> ../source.sh sa_json=$(terraform output sa_key) -# shellcheck disable=SC2086 +# shellcheck disable=SC2086,SC2129 echo "export SERVICE_ACCOUNT_JSON='$(echo $sa_json | base64 --decode)'" >> ../source.sh diff --git a/variables.tf b/variables.tf index 313a9ed..97e29ff 100644 --- a/variables.tf +++ b/variables.tf @@ -24,6 +24,12 @@ variable "topic" { description = "The Pub/Sub topic name" } +variable "create_topic" { + type = bool + description = "Specify true if you want to create a topic" + default = true +} + variable "topic_labels" { type = map(string) description = "A map of labels to assign to the Pub/Sub topic"