diff --git a/Makefile b/Makefile index 36ccd9f..7be14d7 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ # Make will use bash instead of sh SHELL := /usr/bin/env bash -DOCKER_TAG_VERSION_DEVELOPER_TOOLS := 0 +DOCKER_TAG_VERSION_DEVELOPER_TOOLS := 0.13.7 DOCKER_IMAGE_DEVELOPER_TOOLS := cft/developer-tools REGISTRY_URL := gcr.io/cloud-foundation-cicd @@ -73,6 +73,23 @@ docker_test_lint: $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ /usr/local/bin/test_lint.sh +# Execute bats tests within the docker container +.PHONY: docker_test_bats +docker_test_bats: + docker run --rm -it \ + -v $(CURDIR):/workspace \ + $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ + /bin/bash -c 'source /usr/local/bin/task_helper_functions.sh && test_bats' + +# Execute update integration tests within the docker container +.PHONY: docker_test_integration_update +docker_test_integration_update: + docker run --rm -it \ + -e SERVICE_ACCOUNT_JSON \ + -v "$(CURDIR)":/workspace \ + $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ + /bin/bash -c 'source /usr/local/bin/task_helper_functions.sh && test_integration_update' + # Generate documentation .PHONY: docker_generate_docs docker_generate_docs: diff --git a/README.md b/README.md index 6da2598..a3abcae 100644 --- a/README.md +++ b/README.md @@ -1,82 +1,13 @@ # terraform-google-cloud-operations -This module was generated from [terraform-google-module-template](https://github.com/terraform-google-modules/terraform-google-module-template/), which by default generates a module that simply creates a GCS bucket. As the module develops, this README should be updated. - -The resources/services/activations/deletions that this module will create/trigger are: - -- Create a GCS bucket with the provided name +This module is a collection of submodules related to Google Cloud Operations (Logging and Monitoring): +- [Agent Policy](./modules/agent-policy/README.md) ## Usage -Basic usage of this module is as follows: - -```hcl -module "cloud_operations" { - source = "terraform-google-modules/cloud-operations/google" - version = "~> 0.1" - - project_id = "" - bucket_name = "gcs-test-bucket" -} -``` - -Functional examples are included in the -[examples](./examples/) directory. - - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|:----:|:-----:|:-----:| -| bucket\_name | The name of the bucket to create | string | n/a | yes | -| project\_id | The project ID to deploy to | string | n/a | yes | - -## Outputs - -| Name | Description | -|------|-------------| -| bucket\_name | | - - - -## Requirements - -These sections describe requirements for using this module. - -### Software - -The following dependencies must be available: - -- [Terraform][terraform] v0.12 -- [Terraform Provider for GCP][terraform-provider-gcp] plugin v2.0 - -### Service Account - -A service account with the following roles must be used to provision -the resources of this module: - -- Storage Admin: `roles/storage.admin` - -The [Project Factory module][project-factory-module] and the -[IAM module][iam-module] may be used in combination to provision a -service account with the necessary roles applied. - -### APIs - -A project with the following APIs enabled must be used to host the -resources of this module: - -- Google Cloud Storage JSON API: `storage-api.googleapis.com` - -The [Project Factory module][project-factory-module] can be used to -provision a project with the necessary APIs enabled. +Each submodule's usage is documented in the [modules](./modules) folder. Functional examples are included in the [examples](./examples/) directory. ## Contributing Refer to the [contribution guidelines](./CONTRIBUTING.md) for information on contributing to this module. - -[iam-module]: https://registry.terraform.io/modules/terraform-google-modules/iam/google -[project-factory-module]: https://registry.terraform.io/modules/terraform-google-modules/project-factory/google -[terraform-provider-gcp]: https://www.terraform.io/docs/providers/google/index.html -[terraform]: https://www.terraform.io/downloads.html diff --git a/build/int.cloudbuild.yaml b/build/int.cloudbuild.yaml index 4761162..c3d2dc8 100644 --- a/build/int.cloudbuild.yaml +++ b/build/int.cloudbuild.yaml @@ -38,4 +38,4 @@ tags: - 'integration' substitutions: _DOCKER_IMAGE_DEVELOPER_TOOLS: 'cft/developer-tools' - _DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '0' + _DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '0.13.7' diff --git a/build/lint.cloudbuild.yaml b/build/lint.cloudbuild.yaml index 0569972..3451db6 100644 --- a/build/lint.cloudbuild.yaml +++ b/build/lint.cloudbuild.yaml @@ -21,4 +21,4 @@ tags: - 'lint' substitutions: _DOCKER_IMAGE_DEVELOPER_TOOLS: 'cft/developer-tools' - _DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '0' + _DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '0.13.7' diff --git a/examples/simple_example/README.md b/examples/agent_policy_detailed_example/README.md similarity index 71% rename from examples/simple_example/README.md rename to examples/agent_policy_detailed_example/README.md index 4b0e111..d7a94b8 100644 --- a/examples/simple_example/README.md +++ b/examples/agent_policy_detailed_example/README.md @@ -1,21 +1,14 @@ # Simple Example -This example illustrates how to use the `cloud-operations` module. +This example illustrates how to use the `agent-policy` module. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|:----:|:-----:|:-----:| -| bucket\_name | The name of the bucket to create. | string | n/a | yes | | project\_id | The ID of the project in which to provision resources. | string | n/a | yes | -## Outputs - -| Name | Description | -|------|-------------| -| bucket\_name | The name of the bucket. | - To provision this example, run the following from within this directory: diff --git a/examples/agent_policy_detailed_example/main.tf b/examples/agent_policy_detailed_example/main.tf new file mode 100644 index 0000000..1f17847 --- /dev/null +++ b/examples/agent_policy_detailed_example/main.tf @@ -0,0 +1,74 @@ +/** + * Copyright 2020 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.0" +} + +module "agent_policy_detailed" { + source = "./../../modules/agent-policy" + project_id = var.project_id + policy_id = "ops-agents-test-policy-detailed" + description = "an example policy description" + agent_rules = [ + { + type = "logging" + version = "current-major" + package_state = "installed" + enable_autoupgrade = true + }, + { + type = "metrics" + version = "latest" + package_state = "removed" + enable_autoupgrade = false + }, + ] + group_labels = [ + [ + { + name = "env" + value = "prod" + }, + { + name = "product" + value = "myapp" + }, + ], + [ + { + name = "env" + value = "staging" + }, + { + name = "product" + value = "myapp" + }, + ], + ] + os_types = [ + { + short_name = "debian" + version = "10" + }, + ] + zones = [ + "us-central1-c", + "asia-northeast2-b", + "europe-north1-b", + ] + instances = ["zones/us-central1-a/instances/test-instance"] +} diff --git a/test/fixtures/simple_example/variables.tf b/examples/agent_policy_detailed_example/variables.tf similarity index 100% rename from test/fixtures/simple_example/variables.tf rename to examples/agent_policy_detailed_example/variables.tf diff --git a/examples/simple_example/versions.tf b/examples/agent_policy_detailed_example/versions.tf similarity index 100% rename from examples/simple_example/versions.tf rename to examples/agent_policy_detailed_example/versions.tf diff --git a/examples/agent_policy_simple_example/README.md b/examples/agent_policy_simple_example/README.md new file mode 100644 index 0000000..d7a94b8 --- /dev/null +++ b/examples/agent_policy_simple_example/README.md @@ -0,0 +1,18 @@ +# Simple Example + +This example illustrates how to use the `agent-policy` module. + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| project\_id | The ID of the project in which to provision resources. | string | n/a | yes | + + + +To provision this example, run the following from 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/simple_example/main.tf b/examples/agent_policy_simple_example/main.tf similarity index 68% rename from examples/simple_example/main.tf rename to examples/agent_policy_simple_example/main.tf index d033880..289b1dc 100644 --- a/examples/simple_example/main.tf +++ b/examples/agent_policy_simple_example/main.tf @@ -18,9 +18,19 @@ provider "google" { version = "~> 2.0" } -module "cloud_operations" { - source = "../.." - - project_id = var.project_id - bucket_name = var.bucket_name +module "agent_policy_simple" { + source = "./../../modules/agent-policy" + project_id = var.project_id + policy_id = "ops-agents-test-policy-simple" + agent_rules = [ + { + type = "logging" + }, + ] + os_types = [ + { + short_name = "centos" + version = "8" + }, + ] } diff --git a/examples/simple_example/variables.tf b/examples/agent_policy_simple_example/variables.tf similarity index 87% rename from examples/simple_example/variables.tf rename to examples/agent_policy_simple_example/variables.tf index eeadd9d..c1a5c77 100644 --- a/examples/simple_example/variables.tf +++ b/examples/agent_policy_simple_example/variables.tf @@ -18,8 +18,3 @@ variable "project_id" { description = "The ID of the project in which to provision resources." type = string } - -variable "bucket_name" { - description = "The name of the bucket to create." - type = string -} diff --git a/test/fixtures/simple_example/versions.tf b/examples/agent_policy_simple_example/versions.tf similarity index 100% rename from test/fixtures/simple_example/versions.tf rename to examples/agent_policy_simple_example/versions.tf diff --git a/examples/agent_policy_update_example/README.md b/examples/agent_policy_update_example/README.md new file mode 100644 index 0000000..d30a5c6 --- /dev/null +++ b/examples/agent_policy_update_example/README.md @@ -0,0 +1,24 @@ +# Update Example + +This example is specifically for testing update functionality. + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| agent\_rules | A list of agent rules to be enforced by the policy. | list(any) | n/a | yes | +| description | The description of the policy. | string | `"null"` | no | +| group\_labels | A list of label maps to filter instances to apply policies on. | object | `"null"` | no | +| instances | A list of zones to filter instances to apply the policy. | list(string) | `"null"` | no | +| os\_types | A list of label maps to filter instances to apply policies on. | list(any) | n/a | yes | +| project\_id | The ID of the project in which to provision resources. | string | n/a | yes | +| zones | A list of zones to filter instances to apply the policy. | list(string) | `"null"` | no | + + + +To provision this example, run the following from 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/agent_policy_update_example/main.tf b/examples/agent_policy_update_example/main.tf new file mode 100644 index 0000000..7678aa2 --- /dev/null +++ b/examples/agent_policy_update_example/main.tf @@ -0,0 +1,31 @@ +/** + * 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. + */ + +provider "google" { + version = "~> 2.0" +} + +module "agent_policy_update" { + source = "./../../modules/agent-policy" + project_id = var.project_id + policy_id = "ops-agents-test-policy-update" + description = var.description + agent_rules = var.agent_rules + group_labels = var.group_labels + os_types = var.os_types + zones = var.zones + instances = var.instances +} diff --git a/examples/agent_policy_update_example/variables.tf b/examples/agent_policy_update_example/variables.tf new file mode 100644 index 0000000..e50fb2f --- /dev/null +++ b/examples/agent_policy_update_example/variables.tf @@ -0,0 +1,57 @@ +/** + * 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" { + description = "The ID of the project in which to provision resources." + type = string +} + +variable "description" { + description = "The description of the policy." + type = string + default = null +} + +variable "agent_rules" { + description = "A list of agent rules to be enforced by the policy." + type = list(any) +} + +variable "group_labels" { + description = "A list of label maps to filter instances to apply policies on." + type = list(list(object({ + name = string + value = string + }))) + default = null +} + +variable "os_types" { + description = "A list of label maps to filter instances to apply policies on." + type = list(any) +} + +variable "zones" { + description = "A list of zones to filter instances to apply the policy." + type = list(string) + default = null +} + +variable "instances" { + description = "A list of zones to filter instances to apply the policy." + type = list(string) + default = null +} diff --git a/versions.tf b/examples/agent_policy_update_example/versions.tf similarity index 94% rename from versions.tf rename to examples/agent_policy_update_example/versions.tf index 1a9363a..832ec1d 100644 --- a/versions.tf +++ b/examples/agent_policy_update_example/versions.tf @@ -15,5 +15,5 @@ */ terraform { - required_version = "~> 0.12.6" + required_version = ">= 0.12" } diff --git a/kitchen.yml b/kitchen.yml index f3c9c35..31333bd 100644 --- a/kitchen.yml +++ b/kitchen.yml @@ -26,18 +26,36 @@ platforms: - name: default suites: - - name: simple_example + - name: agent_policy_simple_example driver: - root_module_directory: test/fixtures/simple_example/ + root_module_directory: test/fixtures/agent_policy_simple_example/ + verify_version: false verifier: color: false systems: - - name: simple_example local + - name: agent_policy_simple_example local backend: local controls: - gcloud - - gsutil - - name: simple_example gcp - backend: gcp + - name: agent_policy_detailed_example + driver: + root_module_directory: test/fixtures/agent_policy_detailed_example/ + verify_version: false + verifier: + color: false + systems: + - name: agent_policy_detailed_example local + backend: local controls: - - gcp + - gcloud + - name: agent_policy_update_example + driver: + root_module_directory: test/fixtures/agent_policy_update_example/ + verify_version: false + verifier: + color: false + systems: + - name: agent_policy_update_example local + backend: local + controls: + - gcloud diff --git a/modules/agent-policy/README.md b/modules/agent-policy/README.md new file mode 100644 index 0000000..624c82e --- /dev/null +++ b/modules/agent-policy/README.md @@ -0,0 +1,152 @@ +# Agent Policy + +This module is used to install and manage metrics and logging agents in GCE. + +## Usage + +Basic usage of this module is as follows: + +```hcl +module "agent_policy" { + source = "terraform-google-modules/cloud-operations/google/modules/agent-policy" + project_id = "" + policy_id = "ops-agents-example-policy" + agent_rules = [ + { + type = "logging" + }, + ] + os_types = [ + { + short_name = "centos" + version = "8" + }, + ] +} +``` + +Functional examples are included in the [examples](./../../examples) directory. + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| agent\_rules | A list of agent rules to be enforced by the policy. | list(any) | n/a | yes | +| description | The description of the policy. | string | `"null"` | no | +| group\_labels | A list of label maps to filter instances to apply policies on. | object | `"null"` | no | +| instances | A list of instances to filter instances to apply the policy. | list(string) | `"null"` | no | +| os\_types | A list of OS types to filter instances to apply the policy. | list(any) | n/a | yes | +| policy\_id | The ID of the policy. | string | n/a | yes | +| project\_id | The ID of the project in which to provision resources. | string | n/a | yes | +| zones | A list of zones to filter instances to apply the policy. | list(string) | `"null"` | no | + + + +Note that additional validations may be enforced by the API. + +### agent_rules variable + +Each agent rule in the list of agent rules contains the following fields: + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| type | Type of agent to manage. Allowed values: `"logging"`, `"metrics"`. | string | n/a | yes | +| version | Version of the agent to install. Allowed values and formats: `"current-major"`, `"latest"`, `"MAJOR_VERSION.*.*"`, `"MAJOR_VERSION.MINOR_VERSION.PATCH_VERSION"`, `"5.5.2-BUILD_NUMBER"`. `"5.5.2-BUILD_NUMBER"` is only allowed if `type="metrics"`. | string | `"current-major"` | no | +| package\_state | Desired package state of the agent. Allowed values: `"installed"`, `"removed"`. | object | `"installed"` | no | +| enable\_autoupgrade | Whether to enable autoupgrade of the agent. Allowed values: `true`, `false`. | list(string) | `true` | no | + +### group_labels variable + +Group labels are represented as a list of label maps to filter instances that the policy applies to. Each label map is represented by a list of objects, and each object contains the following fields: + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| name | The name of the label. | string | n/a | yes | +| value | The value of the label. | string | n/a | yes | + +Each object in a nested list is related by `AND` and each nested list is related by `OR`. More details can be found in the [ops-agents policy docs][ops-agents-policy-docs]. + +### instances variable + +Each item in the list must be in the format of `zones/ZONE_NAME/instances/INSTANCE_NAME`. To list all existing instances, run `gcloud compute instances list`. If this variable isn't provided, the variable will be set to its default value: `null`. + +### os_types variable + +For now, exactly one OS type needs to be specified. Each OS type contains the following fields: + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| short_name | Short name of the OS. Allowed values: `"centos"`, `"debian"`, `"rhel"`, `"sles"`, `"sles_sap"`, `"ubuntu"`. | string | n/a | yes | +| version | Version of the OS. | string | n/a | no | + +To inspect the exact OS short name and version of an instance, run `gcloud beta compute instances os-inventory describe INSTANCE_NAME`. + +### policy_id variable + +This ID must start with `ops-agents-`, contain only lowercase letters, numbers, and hyphens, end with a number or a letter, be between 1-63 characters, and be unique within the project. + +## Requirements + +These sections describe requirements for using this module. + +### Software + +The following dependencies must be available: + +- [Terraform][terraform] v0.12 +- [Terraform Provider for GCP][terraform-provider-gcp] plugin v2.0 +- [Google Cloud SDK][google-cloud-sdk] +- [curl][curl] + +### Service Account + +A service account with the following roles must be used to provision +the resources of this module: + +- Logging Logs Writer: `roles/logging.logWriter` +- Monitoring Metric Writer: `roles/monitoring.metricWriter` +- OS Config GuestPolicy Admin: `roles/osconfig.guestPolicyAdmin` + +The [Project Factory module][project-factory-module] and the +[IAM module][iam-module] may be used in combination to provision a +service account with the necessary roles applied. + +### APIs + +A project with the following APIs enabled must be used to host the +resources of this module: + +* Google Cloud Logging API: `logging.googleapis.com` +* Google Cloud Monitoring API: `monitoring.googleapis.com` +* Google Cloud OS Config API: `osconfig.googleapis.com` + * [OS Config Metadata][os-config-metadata] + +The [Project Factory module][project-factory-module] can be used to +provision a project with the necessary APIs enabled. + +## Testing + + + +### Integration Testing + +Instructions for how to run integration tests can be found in [CONTRIBUTING.md](./../../CONTRIBUTING.md#integration-testing) + +### Unit Testing + +To run unit tests, navigate to [test/agent-policy-tests](./../../test/agent-policy-tests), then run `./test-runner.py`. + +## Contributing + +Refer to the [contribution guidelines](./../../CONTRIBUTING.md) for +information on contributing to this module. + +[iam-module]: https://registry.terraform.io/modules/terraform-google-modules/iam/google +[project-factory-module]: https://registry.terraform.io/modules/terraform-google-modules/project-factory/google +[terraform-provider-gcp]: https://www.terraform.io/docs/providers/google/index.html +[terraform]: https://www.terraform.io/downloads.html +[curl]: https://curl.haxx.se +[google-cloud-sdk]: https://cloud.google.com/sdk/install +[os-config-metadata]: https://cloud.google.com/compute/docs/manage-os#enable-metadata +[ops-agents-policy-docs]: https://cloud.google.com/sdk/gcloud/reference/alpha/compute/instances/ops-agents/policies/create diff --git a/modules/agent-policy/main.tf b/modules/agent-policy/main.tf new file mode 100644 index 0000000..e6d62f1 --- /dev/null +++ b/modules/agent-policy/main.tf @@ -0,0 +1,44 @@ +/** + * Copyright 2020 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 "gcloud-upsert" { + source = "terraform-google-modules/gcloud/google" + + platform = "linux" + additional_components = ["alpha"] + + create_cmd_entrypoint = abspath("${path.module}/scripts/create-update-script.sh") + create_cmd_body = <<-EOT + ${var.project_id} ${jsonencode(var.policy_id)} \ + ${jsonencode(var.description == null ? "" : var.description)} \ + ${base64encode(jsonencode(var.agent_rules))} \ + ${base64encode(jsonencode(var.group_labels == null ? [] : var.group_labels))} \ + ${base64encode(jsonencode(var.os_types))} \ + ${base64encode(jsonencode(var.zones == null ? [] : var.zones))} \ + ${base64encode(jsonencode(var.instances == null ? [] : var.instances))} + EOT + create_cmd_triggers = { uuid = uuid() } +} + +module "gcloud-destroy" { + source = "terraform-google-modules/gcloud/google" + + platform = "linux" + additional_components = ["alpha"] + + destroy_cmd_entrypoint = abspath("${path.module}/scripts/delete-script.sh") + destroy_cmd_body = "${var.project_id} ${jsonencode(var.policy_id)}" +} diff --git a/modules/agent-policy/scripts/create-update-script.sh b/modules/agent-policy/scripts/create-update-script.sh new file mode 100755 index 0000000..81aca33 --- /dev/null +++ b/modules/agent-policy/scripts/create-update-script.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +# Copyright 2020 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. + +#################################################################### +## This script safely creates or updates an agent policy. +## The script takes eight arguments: PROJECT_ID, POLICY_ID, +## DESCRIPTION, AGENT_RULES_JSON, GROUP_LABELS_JSON, OS_TYPES_JSON, +## ZONES_JSON, and INSTANCES_JSON. This script is run +## during `terraform apply` +#################################################################### + +set -x # debug mode + +PROJECT_ID="$1" +POLICY_ID="$2" +DESCRIPTION="$3" +AGENT_RULES_JSON="$(echo "$4" | base64 --decode)" +GROUP_LABELS_JSON="$(echo "$5" | base64 --decode)" +OS_TYPES_JSON="$(echo "$6" | base64 --decode)" +ZONES_JSON="$(echo "$7" | base64 --decode)" +INSTANCES_JSON="$(echo "$8" | base64 --decode)" + + +# include functions to build gcloud command +SCRIPT_DIR="$( realpath "$( dirname "${BASH_SOURCE[0]}" )" )" +UTILS_ABS_PATH="${SCRIPT_DIR}/script-utils.sh" +# shellcheck disable=SC1090 +source "$UTILS_ABS_PATH" + + +DESCRIBE_COMMAND="$(get_describe_command "$PROJECT_ID" "$POLICY_ID")" +DESCRIBE_OUTPUT=$(eval "$DESCRIBE_COMMAND" 2>/dev/null) +RETURN_CODE="$?" +echo "return code of describe command: $RETURN_CODE" + +if [ "$RETURN_CODE" -eq 0 ]; then + echo "$DESCRIBE_OUTPUT" + echo "$POLICY_ID exists, updating" + ETAG="$(get_etag "$DESCRIBE_OUTPUT")" + echo "etag: $ETAG" + UPDATE_COMMAND="$(get_update_command "$PROJECT_ID" "$POLICY_ID" \ + "$DESCRIPTION" "$AGENT_RULES_JSON" "$GROUP_LABELS_JSON" \ + "$OS_TYPES_JSON" "$ZONES_JSON" "$INSTANCES_JSON" "$ETAG")" + eval "$UPDATE_COMMAND" + RETURN_CODE="$?" + echo "return code of update command: $RETURN_CODE" +else + echo "$POLICY_ID does not exist, creating" + CREATE_COMMAND="$(get_create_command "$PROJECT_ID" "$POLICY_ID" \ + "$DESCRIPTION" "$AGENT_RULES_JSON" "$GROUP_LABELS_JSON" \ + "$OS_TYPES_JSON" "$ZONES_JSON" "$INSTANCES_JSON")" + eval "$CREATE_COMMAND" + RETURN_CODE="$?" + echo "return code of create command: $RETURN_CODE" +fi + diff --git a/modules/agent-policy/scripts/delete-script.sh b/modules/agent-policy/scripts/delete-script.sh new file mode 100755 index 0000000..b7f59ab --- /dev/null +++ b/modules/agent-policy/scripts/delete-script.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Copyright 2020 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. + +#################################################################### +## This script safely deletes an agent policy. The script takes +## two arguments: PROJECT_ID and POLICY_ID. This script is run +## during `terraform destroy` +#################################################################### + +set -x # debug mode + +PROJECT_ID="$1" +POLICY_ID="$2" + +# include functions to build gcloud command +SCRIPT_DIR="$( realpath "$( dirname "${BASH_SOURCE[0]}" )" )" +UTILS_ABS_PATH="${SCRIPT_DIR}/script-utils.sh" +# shellcheck disable=SC1090 +source "$UTILS_ABS_PATH" + +DESCRIBE_COMMAND="$(get_describe_command "$PROJECT_ID" "$POLICY_ID")" +eval "$DESCRIBE_COMMAND" +RETURN_CODE="$?" +echo "return code of describe command: $RETURN_CODE" + +if [ "$RETURN_CODE" -eq 0 ]; then + DELETE_COMMAND="$(get_delete_command "$PROJECT_ID" "$POLICY_ID")" + eval "$DELETE_COMMAND" + RETURN_CODE="$?" + echo "return code of delete command: $RETURN_CODE" +fi diff --git a/modules/agent-policy/scripts/script-utils.sh b/modules/agent-policy/scripts/script-utils.sh new file mode 100644 index 0000000..8d174a5 --- /dev/null +++ b/modules/agent-policy/scripts/script-utils.sh @@ -0,0 +1,332 @@ +#!/usr/bin/env bash + +# Copyright 2020 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. + +#################################################################### +## This script contains util functions. The util functions are used +## in modules/agent-policy/scripts/create-update-script.sh and +## modules/agent-policy/scripts/delete-script.sh +#################################################################### + + +CREATE="create" +UPDATE="update" +LAUNCH_STAGE="alpha" + + +# Params: +# $1 = JSON formatted list(string) +# Return: +# A well-formatted command line flag value for a list of strings +function get_formatted_list_of_strings() { + local formatted + local python="python -c 'import json, sys;" + python="$python list_of_strings = json.load(sys.stdin);" + python="$python print (\",\".join(x for x in list_of_strings))'" + formatted="$(echo "$1" | eval "$python")" + echo "$formatted" +} + + +# Params: +# $1 = JSON formatted list(object) +# Return: +# A well-formatted command line flag value for a list of objects +function get_formatted_list_of_objects() { + local formatted + local python="python -c 'import json, sys;" + python="$python list_of_objs = json.load(sys.stdin);" + python="$python print (\";\".join(\",\".join([\"{}={}\".format(k.replace(\"_\", \"-\")," + python="$python str(v).lower() if type(v) is bool else v) for k, v in obj.items()])" + python="$python for obj in list_of_objs))'" + formatted="$(echo "$1" | eval "$python")" + echo "$formatted" +} + + +# Params: +# $1 = JSON formatted list(list(objects)) +# Return: +# A well-formatted command line flag value for a list of list of objects +function get_formatted_list_of_list_of_objects() { + local formatted + local python="python -c 'import json, sys;" + python="$python list_of_list_of_objs = json.load(sys.stdin);" + python="$python print (\";\".join(\",\".join(\"=\".join(inner_list[x] for x in inner_list)" + python="$python for inner_list in outer_list) for outer_list in list_of_list_of_objs))'" + formatted="$(echo "$1" | eval "$python")" + echo "$formatted" + +} + +# Params: +# $1 = output of successful describe command +# Return: +# the etag in the given string +function get_etag() { + local describe_output="$1" + local etag=${describe_output#*etag: } # removes everything before etag + etag=${etag%id: *} # removes everything after etag + echo "$etag" | tr -d '\040\011\012\015' # removes spaces, tabs, carriage returns, newlines +} + + +# Params: +# $1 = flag name +# $2 = flag value +# Return: +# An empty string if the flag value is empty, otherwise returns the appropriate flag +function get_flag() { + local flag_name="$1" + local flag_value="$2" + local flag="" + if [ -n "$flag_value" ]; then + # flag value is not empty + flag=" --$flag_name='$flag_value'" + fi + echo "$flag" +} + + +# Params: +# $1 = flag name +# $2 = flag value +# Return: +# An appropriate --clear-x flag (where x is instances, group-labels, or zones) +# if the flag value is empty, otherwise returns the appropriate flag +function get_update_flag() { + local flag_name="$1" + local flag_value="$2" + local update_flag="" + if [ -z "$flag_value" ]; then + # flag value is empty + update_flag=" --clear-$flag_name" + fi + echo "$update_flag" +} + + +# Params: +# $1 = group labels flag name +# $2 = group labels flag value +# $3 = zones flag name +# $4 = zones flag value +# $5 = instances flag name +# $5 = instances flag value +# Return: +# The appropriate --clear-x flags (where x is group-labels, zones, or instances) +# based on grloup labels flag value, zones flag value, and instances flag value +function get_update_flags() { + local group_labels_flag_name="$1" + local group_labels_flag_value="$2" + local zones_flag_name="$3" + local zones_flag_value="$4" + local instances_flag_name="$5" + local instances_flag_value="$6" + local clear_group_labels_flag + local clear_zones_flag + local update_flags + + clear_group_labels_flag="$(get_update_flag "$group_labels_flag_name" \ + "$group_labels_flag_value")" + clear_zones_flag=$(get_update_flag "$zones_flag_name" "$zones_flag_value") + clear_instances_flag=$(get_update_flag "$instances_flag_name" "$instances_flag_value") + + local update_flags="$clear_group_labels_flag$clear_zones_flag$clear_instances_flag" + echo "$update_flags" +} + +# Params: +# $1 = project id +# Return: +# The appropriate global flags (--project and --quiet) +function get_global_flags() { + local project_id="$1" + local project_flag_name="project" + local project_flag + project_flag=$(get_flag "$project_flag_name" "$project_id") + local quiet_flag=" --quiet" + + local global_flags="$project_flag$quiet_flag" + echo "$global_flags" +} + +# Params: +# $1 = action (create or update) +# $2 = policy id +# $3 = description of the agent policy +# $4 = agent rules, in json format +# $5 = group labels, in json format +# $6 = os types, in json format +# $7 = zones, in json format +# $8 = instances, in json format +# Return: +# the appropriate gcloud create or update command, given the args +function get_base_upsert_command() { + local action="$1" + local policy_id="$2" + local description="$3" + local agent_rules_json="$4" + local group_labels_json="$5" + local os_types_json="$6" + local zones_json="$7" + local instances_json="$8" + + local description_flag_name="description" + local agent_rules_flag_name="agent-rules" + local group_labels_flag_name="group-labels" + local os_types_flag_name="os-types" + local zones_flag_name="zones" + local instances_flag_name="instances" + + local agent_rules_flag_value + local group_labels_flag_value + local os_types_flag_value + local zones_flag_value + local instances_flag_value + agent_rules_flag_value=$(get_formatted_list_of_objects "$agent_rules_json") + group_labels_flag_value=$(get_formatted_list_of_list_of_objects "$group_labels_json") + os_types_flag_value=$(get_formatted_list_of_objects "$os_types_json") + zones_flag_value=$(get_formatted_list_of_strings "$zones_json") + instances_flag_value=$(get_formatted_list_of_strings "$instances_json") + + local description_flag + local agent_rules_flag + local group_labels_flag + local os_types_flag + local zones_flag + local instances_flag + local project_flag + description_flag=$(get_flag "$description_flag_name" "$description") + agent_rules_flag=$(get_flag "$agent_rules_flag_name" "$agent_rules_flag_value") + group_labels_flag=$(get_flag "$group_labels_flag_name" "$group_labels_flag_value") + os_types_flag=$(get_flag "$os_types_flag_name" "$os_types_flag_value") + zones_flag=$(get_flag "$zones_flag_name" "$zones_flag_value") + instances_flag=$(get_flag "$instances_flag_name" "$instances_flag_value") + + local update_flags="" + if [ "$action" = "$UPDATE" ]; then + update_flags="$(get_update_flags "$group_labels_flag_name" \ + "$group_labels_flag_value" "$zones_flag_name" "$zones_flag_value" \ + "$instances_flag_name" "$instances_flag_value")" + fi + + local command="gcloud $LAUNCH_STAGE compute instances ops-agents policies $action" + command="$command $policy_id$description_flag$agent_rules_flag$group_labels_flag" + command="$command$os_types_flag$zones_flag$instances_flag$update_flags" + echo "$command" +} + +# Params: +# $1 = project id +# $2 = policy id +# $3 = description of the agent policy +# $4 = agent rules, in json format +# $5 = group labels, in json format +# $6 = os types, in json format +# $7 = zones, in json format +# $8 = instances, in json format +# Return: +# the appropriate gcloud create command, given the args +function get_create_command() { + local project_id="$1" + local policy_id="$2" + local description="$3" + local agent_rules_json="$4" + local group_labels_json="$5" + local os_types_json="$6" + local zones_json="$7" + local instances_json="$8" + local base_create_command + local global_flags + + base_create_command="$(get_base_upsert_command "$CREATE" \ + "$policy_id" "$description" "$agent_rules_json" \ + "$group_labels_json" "$os_types_json" "$zones_json" "$instances_json")" + global_flags=$(get_global_flags "$project_id") + + local create_command="$base_create_command$global_flags" + echo "$create_command" +} + +# Params: +# $1 = project id +# $2 = policy id +# $3 = description of the agent policy +# $4 = agent rules, in json format +# $5 = group labels, in json format +# $6 = os types, in json format +# $7 = zones, in json format +# $8 = instances, in json format +# $9 = etag +# Return: +# the appropriate gcloud update command, given the args +function get_update_command() { + local project_id="$1" + local policy_id="$2" + local description="$3" + local agent_rules_json="$4" + local group_labels_json="$5" + local os_types_json="$6" + local zones_json="$7" + local instances_json="$8" + local etag="$9" + local base_update_command + local etag_flag + local global_flags + + base_update_command="$(get_base_upsert_command "$UPDATE" \ + "$policy_id" "$description" "$agent_rules_json" \ + "$group_labels_json" "$os_types_json" "$zones_json" "$instances_json")" + etag_flag=$(get_flag etag "$etag") + global_flags=$(get_global_flags "$project_id") + local update_command="$base_update_command$etag_flag$global_flags" + echo "$update_command" +} + + +# Params: +# $1 = project id +# $2 = policy id +# Return: +# the appropriate gcloud describe command, given the args +function get_describe_command() { + local project_id="$1" + local policy_id="$2" + local project_flag_name="project" + local project_flag + project_flag=$(get_flag "$project_flag_name" "$project_id") + + local command="gcloud $LAUNCH_STAGE compute instances ops-agents policies describe" + command="$command $policy_id$project_flag --quiet" + echo "$command" +} + +# Params: +# $1 = project id +# $2 = policy id +# Return: +# the appropriate gcloud delete command, given the args +function get_delete_command() { + local project_id="$1" + local policy_id="$2" + local project_flag_name="project" + local project_flag + project_flag=$(get_flag "$project_flag_name" "$project_id") + + local command="gcloud $LAUNCH_STAGE compute instances ops-agents policies delete" + command="$command $policy_id$project_flag --quiet" + echo "$command" +} diff --git a/modules/agent-policy/variables.tf b/modules/agent-policy/variables.tf new file mode 100644 index 0000000..4e40270 --- /dev/null +++ b/modules/agent-policy/variables.tf @@ -0,0 +1,76 @@ +/** + * Copyright 2020 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. + */ + +#################################################################### +## Variables for the agent-policy module +#################################################################### + +variable "project_id" { + description = "The ID of the project in which to provision resources." + type = string +} + +variable "policy_id" { + description = "The ID of the policy." + type = string +} + +variable "description" { + description = "The description of the policy." + type = string + default = null +} + +variable "agent_rules" { + description = "A list of agent rules to be enforced by the policy." + type = list(any) + + validation { + condition = can([for agent_rule in var.agent_rules : agent_rule["type"]]) + error_message = "Each agent rule must have a type." + } +} + +variable "group_labels" { + description = "A list of label maps to filter instances to apply policies on." + type = list(list(object({ + name = string + value = string + }))) + default = null +} + +variable "os_types" { + description = "A list of OS types to filter instances to apply the policy." + type = list(any) + + validation { + condition = can([for os_type in var.os_types : os_type["short_name"]]) + error_message = "Each os type must have a short_name." + } +} + +variable "zones" { + description = "A list of zones to filter instances to apply the policy." + type = list(string) + default = null +} + +variable "instances" { + description = "A list of instances to filter instances to apply the policy." + type = list(string) + default = null +} diff --git a/outputs.tf b/modules/agent-policy/versions.tf similarity index 85% rename from outputs.tf rename to modules/agent-policy/versions.tf index fdad215..0bad581 100644 --- a/outputs.tf +++ b/modules/agent-policy/versions.tf @@ -1,5 +1,5 @@ /** - * Copyright 2018 Google LLC + * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,6 @@ * limitations under the License. */ -output "bucket_name" { - value = google_storage_bucket.main.name +terraform { + required_version = ">= 0.12" } diff --git a/test/agent-policy-tests/test-integration-update.sh b/test/agent-policy-tests/test-integration-update.sh new file mode 100755 index 0000000..292adf0 --- /dev/null +++ b/test/agent-policy-tests/test-integration-update.sh @@ -0,0 +1,149 @@ +#! /bin/bash +# Copyright 2020 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. + +SCRIPT_DIR="$( realpath "$( dirname "${BASH_SOURCE[0]}" )" )" +TF_VARS_FILE="${SCRIPT_DIR}/../fixtures/agent_policy_update_example/terraform.tfvars" +ORIGINAL_CONFIG="$(<"$TF_VARS_FILE")" + +set -eu +source /usr/local/bin/task_helper_functions.sh + + +# Params: +# $1 = string pattern before replacement +# $2 = string pattern after replacement +# $3 = replacement string +# This function replaces anything in between the string +# patterns with the given replacement string +function replace_between() { + local file="$ORIGINAL_CONFIG" + local upper=${file%$1 *} # removes everything after $1 + local lower=${file#*$2 } # removes everything before $2 + echo "$upper$1 = $3" > "$TF_VARS_FILE" + echo "$2 $lower" >> "$TF_VARS_FILE" +} + +# Params: +# $1 = string pattern before replacement +# $2 = replacement string +# This function replaces anything after the string pattern +# with the given replacement string +function replace_after() { + local file="$ORIGINAL_CONFIG" + local upper=${file%$1 *} # removes everything after $1 + echo "$upper$1 = $2" > "$TF_VARS_FILE" +} + +function restore_original_config() { + echo "$ORIGINAL_CONFIG" > "$TF_VARS_FILE" +} + +function test_original_state() { + restore_original_config + kitchen_do converge agent-policy-update-example-default + kitchen_do verify agent-policy-update-example-default +} + +function test_agent_rules_update() { + local agent_rules=$'[{\n type = "metrics" \n package_state = "removed" \n ' + agent_rules="$agent_rules"$'version = "latest" \n enable_autoupgrade = false \n }]' + replace_between "agent_rules" "group_labels" "$agent_rules" + kitchen_do converge agent-policy-update-example-default + kitchen_do verify agent-policy-update-example-default +} + +function test_agent_rules() { + test_agent_rules_update + test_original_state +} + +function test_group_labels_update() { + local group_labels=$'[[{\n "name" = "env" \n "value" = "prod" \n}]]' + replace_between "group_labels" "os_types" "$group_labels" + kitchen_do converge agent-policy-update-example-default + kitchen_do verify agent-policy-update-example-default +} + +function test_group_labels() { + test_group_labels_update + test_original_state +} + +function test_os_types_update() { + local os_types=$'[{\n "short_name" = "sles" \n "version" = "15.1" \n}]' + replace_between "os_types" "zones" "$os_types" + kitchen_do converge agent-policy-update-example-default + kitchen_do verify agent-policy-update-example-default +} + +function test_os_types() { + test_os_types_update + test_original_state +} + +function test_zones_update() { + local zones='["us-central1-c", "asia-northeast2-b"]' + replace_between "zones" "instances" "$zones" + kitchen_do converge agent-policy-update-example-default + kitchen_do verify agent-policy-update-example-default +} + +function test_zones() { + test_zones_update + test_original_state +} + +function test_instances_update() { + local instances='["zones/us-central1-a/instances/test-instance"]' + replace_after "instances" "$instances" + kitchen_do converge agent-policy-update-example-default + kitchen_do verify agent-policy-update-example-default +} + +function test_instances() { + test_instances_update + test_original_state +} + +function test_description_update() { + local description=$'"a test description"' + replace_between "description" "agent_rules" "$description" + kitchen_do converge agent-policy-update-example-default + kitchen_do verify agent-policy-update-example-default +} + +function test_description() { + test_description_update +} + +function run_integration_update_tests() { + source_test_env + + kitchen_do create agent-policy-update-example-default + test_original_state + + test_agent_rules + test_group_labels + test_os_types + test_zones + test_instances + test_description + + restore_original_config +} + +setup_trap_handler_integration +init_credentials +run_integration_update_tests diff --git a/test/agent-policy-tests/test-script-utils.bats b/test/agent-policy-tests/test-script-utils.bats new file mode 100644 index 0000000..f388be3 --- /dev/null +++ b/test/agent-policy-tests/test-script-utils.bats @@ -0,0 +1,283 @@ +#!/usr/bin/env bash + +# Copyright 2020 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. + +#################################################################### +## This script contains unit tests for +## modules/agent-policy/scripts/script-utils.sh +## This script is ran via `make docker_test_bats` +#################################################################### + +PROJECT_ID="test-project-id" +POLICY_ID="ops-agents-test-policy" +DESCRIPTION="an example test policy" +AGENT_RULES_JSON_BASIC="[{\"type\":\"metrics\"}]" +OS_TYPES_JSON_BASIC="[{\"short_name\":\"centos\",\"version\":\"8\"}]" +EMPTY_LIST_JSON="[]" +ETAG="db5c5a61-6a05-4f67-8f84-c89a654eb576" + +load "/usr/local/bats-support/load.bash" +load "/usr/local/bats-assert/load.bash" + + +# Setup before every test +setup() { + SCRIPT_DIR="${BATS_TEST_DIRNAME%/}" + UTILS_ABS_PATH="${SCRIPT_DIR}/../../modules/agent-policy/scripts/script-utils.sh" + source "$UTILS_ABS_PATH" +} + + +############################################################## +## get_create_command tests ## +############################################################## + +@test "Tests get_create_command with defaults" { + local description="" + local agent_rules_json="$AGENT_RULES_JSON_BASIC" + local group_labels_json="$EMPTY_LIST_JSON" + local os_types_json="$OS_TYPES_JSON_BASIC" + local zones_json="$EMPTY_LIST_JSON" + local instances_json="$EMPTY_LIST_JSON" + + local expected_command="gcloud alpha compute instances ops-agents" + expected_command="$expected_command policies create ops-agents-test-policy" + expected_command="$expected_command --agent-rules='type=metrics'" + expected_command="$expected_command --os-types='version=8,short-name=centos'" + expected_command="$expected_command --project='test-project-id' --quiet" + + run get_create_command "$PROJECT_ID" "$POLICY_ID" \ + "$description" "$agent_rules_json" "$group_labels_json" "$os_types_json" \ + "$zones_json" "$instances_json" + + assert_equal "$output" "$expected_command" +} + +@test "Tests get_create_command with description" { + local description="$DESCRIPTION" + local agent_rules_json="$AGENT_RULES_JSON_BASIC" + local group_labels_json="$EMPTY_LIST_JSON" + local os_types_json="$OS_TYPES_JSON_BASIC" + local zones_json="$EMPTY_LIST_JSON" + local instances_json="$EMPTY_LIST_JSON" + + local expected_command="gcloud alpha compute instances ops-agents" + expected_command="$expected_command policies create ops-agents-test-policy" + expected_command="$expected_command --description='an example test policy'" + expected_command="$expected_command --agent-rules='type=metrics'" + expected_command="$expected_command --os-types='version=8,short-name=centos'" + expected_command="$expected_command --project='test-project-id' --quiet" + + run get_create_command "$PROJECT_ID" "$POLICY_ID" \ + "$description" "$agent_rules_json" "$group_labels_json" "$os_types_json" \ + "$zones_json" "$instances_json" + + assert_equal "$output" "$expected_command" +} + +@test "Tests get_create_command with agent_rules" { + local description="" + local agent_rules_json="[{\"enable_autoupgrade\":true,\"package_state\":\"installed\"," + agent_rules_json="${agent_rules_json}\"type\":\"logging\",\"version\":\"current-major\"}," + agent_rules_json="${agent_rules_json}{\"type\":\"metrics\"}]" + local group_labels_json="$EMPTY_LIST_JSON" + local os_types_json="$OS_TYPES_JSON_BASIC" + local zones_json="$EMPTY_LIST_JSON" + local instances_json="$EMPTY_LIST_JSON" + + local expected_command="gcloud alpha compute instances ops-agents" + expected_command="$expected_command policies create ops-agents-test-policy" + expected_command="$expected_command --agent-rules='version=current-major," + expected_command="${expected_command}type=logging,enable-autoupgrade=true," + expected_command="${expected_command}package-state=installed;type=metrics'" + expected_command="$expected_command --os-types='version=8,short-name=centos'" + expected_command="$expected_command --project='test-project-id' --quiet" + + run get_create_command "$PROJECT_ID" "$POLICY_ID" \ + "$description" "$agent_rules_json" "$group_labels_json" "$os_types_json" \ + "$zones_json" "$instances_json" + + assert_equal "$output" "$expected_command" +} + +@test "Tests get_create_command with group_labels" { + local description="" + local agent_rules_json="$AGENT_RULES_JSON_BASIC" + local group_labels_json="[[{\"name\":\"env\",\"value\":\"prod\"}," + group_labels_json="${group_labels_json}{\"name\":\"product\",\"value\":\"myapp\"}]," + group_labels_json="${group_labels_json}[{\"name\":\"env\",\"value\":\"staging\"}," + group_labels_json="${group_labels_json}{\"name\":\"product\",\"value\":\"myapp\"}]]" + local os_types_json="$OS_TYPES_JSON_BASIC" + local zones_json="$EMPTY_LIST_JSON" + local instances_json="$EMPTY_LIST_JSON" + + local expected_command="gcloud alpha compute instances ops-agents" + expected_command="$expected_command policies create ops-agents-test-policy" + expected_command="$expected_command --agent-rules='type=metrics'" + expected_command="$expected_command --group-labels='env=prod,product=myapp;" + expected_command="${expected_command}env=staging,product=myapp'" + expected_command="$expected_command --os-types='version=8,short-name=centos'" + expected_command="$expected_command --project='test-project-id' --quiet" + + run get_create_command "$PROJECT_ID" "$POLICY_ID" \ + "$description" "$agent_rules_json" "$group_labels_json" "$os_types_json" \ + "$zones_json" "$instances_json" + + assert_equal "$output" "$expected_command" +} + +@test "Tests get_create_command with zones" { + local description="" + local agent_rules_json="$AGENT_RULES_JSON_BASIC" + local group_labels_json="$EMPTY_LIST_JSON" + local os_types_json="$OS_TYPES_JSON_BASIC" + local zones_json="[\"us-central1-c\",\"asia-northeast2-b\",\"europe-north1-b\"]" + local instances_json="$EMPTY_LIST_JSON" + + local expected_command="gcloud alpha compute instances ops-agents" + expected_command="$expected_command policies create ops-agents-test-policy" + expected_command="$expected_command --agent-rules='type=metrics'" + expected_command="$expected_command --os-types='version=8,short-name=centos'" + expected_command="$expected_command --zones='us-central1-c," + expected_command="${expected_command}asia-northeast2-b,europe-north1-b'" + expected_command="$expected_command --project='test-project-id' --quiet" + + run get_create_command "$PROJECT_ID" "$POLICY_ID" \ + "$description" "$agent_rules_json" "$group_labels_json" "$os_types_json" \ + "$zones_json" "$instances_json" + + assert_equal "$output" "$expected_command" +} + +@test "Tests get_command_create with instances" { + local description="" + local agent_rules_json="$AGENT_RULES_JSON_BASIC" + local group_labels_json="$EMPTY_LIST_JSON" + local os_types_json="$OS_TYPES_JSON_BASIC" + local zones_json="$EMPTY_LIST_JSON" + local instances_json="[\"zones/us-central1-a/instances/test-instance\"]" + + local expected_command="gcloud alpha compute instances ops-agents" + expected_command="$expected_command policies create ops-agents-test-policy" + expected_command="$expected_command --agent-rules='type=metrics'" + expected_command="$expected_command --os-types='version=8,short-name=centos'" + expected_command="$expected_command --instances='zones/us-central1-a/" + expected_command="${expected_command}instances/test-instance'" + expected_command="$expected_command --project='test-project-id' --quiet" + + run get_create_command "$PROJECT_ID" "$POLICY_ID" \ + "$description" "$agent_rules_json" "$group_labels_json" "$os_types_json" \ + "$zones_json" "$instances_json" + + assert_equal "$output" "$expected_command" +} + + + +############################################################## +## get_update_command tests ## +############################################################## + +@test "Tests get_update_command clear filters" { + local description="" + local agent_rules_json="$AGENT_RULES_JSON_BASIC" + local group_labels_json="$EMPTY_LIST_JSON" + local os_types_json="$OS_TYPES_JSON_BASIC" + local zones_json="$EMPTY_LIST_JSON" + local instances_json="$EMPTY_LIST_JSON" + + local expected_command="gcloud alpha compute instances ops-agents" + expected_command="$expected_command policies update ops-agents-test-policy" + expected_command="$expected_command --agent-rules='type=metrics'" + expected_command="$expected_command --os-types='version=8,short-name=centos'" + expected_command="$expected_command --clear-group-labels" + expected_command="$expected_command --clear-zones" + expected_command="$expected_command --clear-instances" + expected_command="$expected_command --etag='db5c5a61-6a05-4f67-8f84-c89a654eb576'" + expected_command="$expected_command --project='test-project-id' --quiet" + + run get_update_command "$PROJECT_ID" "$POLICY_ID" \ + "$description" "$agent_rules_json" "$group_labels_json" "$os_types_json" \ + "$zones_json" "$instances_json" "$ETAG" + + assert_equal "$output" "$expected_command" +} + + + +############################################################## +## get_describe_command tests ## +############################################################## + +@test "Test get_describe_command" { + local expected_command="gcloud alpha compute instances ops-agents" + expected_command="$expected_command policies describe ops-agents-test-policy" + expected_command="$expected_command --project='test-project-id' --quiet" + + run get_describe_command "$PROJECT_ID" "$POLICY_ID" + + assert_equal "$output" "$expected_command" +} + + +############################################################## +## get_delete_command tests ## +############################################################## + +@test "Test get_delete_command" { + local expected_command="gcloud alpha compute instances ops-agents" + expected_command="$expected_command policies delete ops-agents-test-policy" + expected_command="$expected_command --project='test-project-id' --quiet" + + run get_delete_command "$PROJECT_ID" "$POLICY_ID" + + assert_equal "$output" "$expected_command" +} + + +############################################################## +## get_etag tests ## +############################################################## + +@test "Test get_etag simple" { + local describe_output="etag: db5c5a61-6a05-4f67-8f84-c89a654eb576" + local expected_etag="$ETAG" + run get_etag "$describe_output" + + assert_equal "$output" "$expected_etag" +} + +@test "Test get_etag detailed" { + local describe_output="agent_rules: - enable_autoupgrade: + true package_state: installed + type: logging + version: 1.*.* + assignment: + group_labels: [] + instances: [] + os_types: + - short_name: debian + version: '10' + zones: [] + create_time: '2020-08-13T17:53:34.607Z' + description: None + etag: db5c5a61-6a05-4f67-8f84-c89a654eb576 + id: projects/981664706940/guestPolicies/ops-agents-test-policy-simple + update_time: '2020-08-13T17:54:27.267Z'" + local expected_etag="$ETAG" + run get_etag "$describe_output" + + assert_equal "$output" "$expected_etag" +} diff --git a/examples/simple_example/outputs.tf b/test/fixtures/agent_policy_detailed_example/main.tf similarity index 79% rename from examples/simple_example/outputs.tf rename to test/fixtures/agent_policy_detailed_example/main.tf index 108b143..77354a6 100644 --- a/examples/simple_example/outputs.tf +++ b/test/fixtures/agent_policy_detailed_example/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2018 Google LLC + * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,8 @@ * limitations under the License. */ -output "bucket_name" { - description = "The name of the bucket." - value = module.cloud_operations.bucket_name +module "example" { + source = "../../../examples/agent_policy_detailed_example" + + project_id = var.project_id } diff --git a/test/fixtures/simple_example/outputs.tf b/test/fixtures/agent_policy_detailed_example/outputs.tf similarity index 83% rename from test/fixtures/simple_example/outputs.tf rename to test/fixtures/agent_policy_detailed_example/outputs.tf index 2e41354..207cf7e 100644 --- a/test/fixtures/simple_example/outputs.tf +++ b/test/fixtures/agent_policy_detailed_example/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2018 Google LLC + * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,6 @@ * limitations under the License. */ -output "bucket_name" { - description = "The name of the bucket." - value = module.example.bucket_name -} - output "project_id" { description = "The ID of the project in which resources are provisioned." value = var.project_id diff --git a/variables.tf b/test/fixtures/agent_policy_detailed_example/variables.tf similarity index 79% rename from variables.tf rename to test/fixtures/agent_policy_detailed_example/variables.tf index 65ec922..bba3500 100644 --- a/variables.tf +++ b/test/fixtures/agent_policy_detailed_example/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2018 Google LLC + * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,6 @@ */ variable "project_id" { - description = "The project ID to deploy to" -} - -variable "bucket_name" { - description = "The name of the bucket to create" + description = "The ID of the project in which to provision resources." + type = string } diff --git a/main.tf b/test/fixtures/agent_policy_detailed_example/versions.tf similarity index 81% rename from main.tf rename to test/fixtures/agent_policy_detailed_example/versions.tf index bcf1cd9..0bad581 100644 --- a/main.tf +++ b/test/fixtures/agent_policy_detailed_example/versions.tf @@ -1,5 +1,5 @@ /** - * Copyright 2018 Google LLC + * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ * limitations under the License. */ -resource "google_storage_bucket" "main" { - project = var.project_id - name = var.bucket_name +terraform { + required_version = ">= 0.12" } diff --git a/test/fixtures/agent_policy_simple_example/main.tf b/test/fixtures/agent_policy_simple_example/main.tf new file mode 100644 index 0000000..d495c66 --- /dev/null +++ b/test/fixtures/agent_policy_simple_example/main.tf @@ -0,0 +1,21 @@ +/** + * Copyright 2020 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 "example" { + source = "../../../examples/agent_policy_simple_example" + + project_id = var.project_id +} diff --git a/test/fixtures/agent_policy_simple_example/outputs.tf b/test/fixtures/agent_policy_simple_example/outputs.tf new file mode 100644 index 0000000..207cf7e --- /dev/null +++ b/test/fixtures/agent_policy_simple_example/outputs.tf @@ -0,0 +1,20 @@ +/** + * Copyright 2020 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" { + description = "The ID of the project in which resources are provisioned." + value = var.project_id +} diff --git a/test/fixtures/agent_policy_simple_example/variables.tf b/test/fixtures/agent_policy_simple_example/variables.tf new file mode 100644 index 0000000..bba3500 --- /dev/null +++ b/test/fixtures/agent_policy_simple_example/variables.tf @@ -0,0 +1,20 @@ +/** + * Copyright 2020 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" { + description = "The ID of the project in which to provision resources." + type = string +} diff --git a/test/fixtures/agent_policy_simple_example/versions.tf b/test/fixtures/agent_policy_simple_example/versions.tf new file mode 100644 index 0000000..0bad581 --- /dev/null +++ b/test/fixtures/agent_policy_simple_example/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2020 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. + */ + +terraform { + required_version = ">= 0.12" +} diff --git a/test/fixtures/simple_example/main.tf b/test/fixtures/agent_policy_update_example/main.tf similarity index 65% rename from test/fixtures/simple_example/main.tf rename to test/fixtures/agent_policy_update_example/main.tf index 7b799c2..78e144e 100644 --- a/test/fixtures/simple_example/main.tf +++ b/test/fixtures/agent_policy_update_example/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2018 Google LLC + * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,19 +14,14 @@ * limitations under the License. */ -provider "random" { - version = "~> 2.0" -} - -resource "random_pet" "main" { - length = 1 - prefix = "simple-example" - separator = "-" -} - module "example" { - source = "../../../examples/simple_example" + source = "../../../examples/agent_policy_update_example" - project_id = var.project_id - bucket_name = random_pet.main.id + project_id = var.project_id + description = var.description + agent_rules = var.agent_rules + group_labels = var.group_labels + os_types = var.os_types + zones = var.zones + instances = var.instances } diff --git a/test/fixtures/agent_policy_update_example/outputs.tf b/test/fixtures/agent_policy_update_example/outputs.tf new file mode 100644 index 0000000..829f1a2 --- /dev/null +++ b/test/fixtures/agent_policy_update_example/outputs.tf @@ -0,0 +1,52 @@ +/** + * Copyright 2020 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" { + description = "The ID of the project in which resources are provisioned." + value = var.project_id +} + +output "description" { + description = "The description of the policy." + value = var.description +} + +output "agent_rules" { + description = "A list of agent rules to be enforced by the policy." + value = var.agent_rules +} + +output "group_labels" { + description = "A list of label maps to filter instances to apply policies on." + value = var.group_labels +} + +output "os_types" { + description = "A list of label maps to filter instances to apply policies on." + value = var.os_types +} + +output "zones" { + description = "A list of zones to filter instances to apply the policy." + value = var.zones + +} + +output "instances" { + description = "A list of zones to filter instances to apply the policy." + value = var.instances + +} diff --git a/test/fixtures/agent_policy_update_example/variables.tf b/test/fixtures/agent_policy_update_example/variables.tf new file mode 100644 index 0000000..ca838d5 --- /dev/null +++ b/test/fixtures/agent_policy_update_example/variables.tf @@ -0,0 +1,57 @@ +/** + * Copyright 2020 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" { + description = "The ID of the project in which to provision resources." + type = string +} + +variable "description" { + description = "The description of the policy." + type = string + default = null +} + +variable "agent_rules" { + description = "A list of agent rules to be enforced by the policy." + type = list(any) +} + +variable "group_labels" { + description = "A list of label maps to filter instances to apply policies on." + type = list(list(object({ + name = string + value = string + }))) + default = null +} + +variable "os_types" { + description = "A list of label maps to filter instances to apply policies on." + type = list(any) +} + +variable "zones" { + description = "A list of zones to filter instances to apply the policy." + type = list(string) + default = null +} + +variable "instances" { + description = "A list of zones to filter instances to apply the policy." + type = list(string) + default = null +} diff --git a/test/fixtures/agent_policy_update_example/versions.tf b/test/fixtures/agent_policy_update_example/versions.tf new file mode 100644 index 0000000..0bad581 --- /dev/null +++ b/test/fixtures/agent_policy_update_example/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2020 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. + */ + +terraform { + required_version = ">= 0.12" +} diff --git a/test/integration/simple_example/controls/gsutil.rb b/test/integration/agent_policy_detailed_example/controls/gcloud.rb similarity index 51% rename from test/integration/simple_example/controls/gsutil.rb rename to test/integration/agent_policy_detailed_example/controls/gcloud.rb index 692309f..daf7769 100644 --- a/test/integration/simple_example/controls/gsutil.rb +++ b/test/integration/agent_policy_detailed_example/controls/gcloud.rb @@ -1,4 +1,4 @@ -# Copyright 2018 Google LLC +# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,12 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. -control "gsutil" do - title "gsutil" +control "gcloud" do + title "gcloud" - describe command("gsutil ls -p #{attribute("project_id")}") do + describe command("gcloud --project=#{attribute("project_id")} services list --enabled") do + its(:exit_status) { should eq 0 } + its(:stderr) { should eq "" } + its(:stdout) { should match "logging.googleapis.com" } + its(:stdout) { should match "monitoring.googleapis.com" } + its(:stdout) { should match "osconfig.googleapis.com" } + end + + describe command("gcloud alpha compute instances ops-agents policies describe " \ + "ops-agents-test-policy-detailed --project=#{attribute("project_id")} --quiet") do its(:exit_status) { should eq 0 } its(:stderr) { should eq "" } - its(:stdout) { should match "gs://#{attribute("bucket_name")}" } end end diff --git a/test/integration/simple_example/inspec.yml b/test/integration/agent_policy_detailed_example/inspec.yml similarity index 76% rename from test/integration/simple_example/inspec.yml rename to test/integration/agent_policy_detailed_example/inspec.yml index 2fd718c..1166661 100644 --- a/test/integration/simple_example/inspec.yml +++ b/test/integration/agent_policy_detailed_example/inspec.yml @@ -7,6 +7,3 @@ attributes: - name: project_id required: true type: string - - name: bucket_name - required: true - type: string diff --git a/test/integration/simple_example/controls/gcloud.rb b/test/integration/agent_policy_simple_example/controls/gcloud.rb similarity index 62% rename from test/integration/simple_example/controls/gcloud.rb rename to test/integration/agent_policy_simple_example/controls/gcloud.rb index d2a2609..a5ed2ba 100644 --- a/test/integration/simple_example/controls/gcloud.rb +++ b/test/integration/agent_policy_simple_example/controls/gcloud.rb @@ -1,4 +1,4 @@ -# Copyright 2018 Google LLC +# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,14 @@ describe command("gcloud --project=#{attribute("project_id")} services list --enabled") do its(:exit_status) { should eq 0 } its(:stderr) { should eq "" } - its(:stdout) { should match "storage-api.googleapis.com" } + its(:stdout) { should match "logging.googleapis.com" } + its(:stdout) { should match "monitoring.googleapis.com" } + its(:stdout) { should match "osconfig.googleapis.com" } + end + + describe command("gcloud alpha compute instances ops-agents policies describe " \ + "ops-agents-test-policy-simple --project=#{attribute("project_id")} --quiet") do + its(:exit_status) { should eq 0 } + its(:stderr) { should eq "" } end end diff --git a/test/integration/agent_policy_simple_example/inspec.yml b/test/integration/agent_policy_simple_example/inspec.yml new file mode 100644 index 0000000..1166661 --- /dev/null +++ b/test/integration/agent_policy_simple_example/inspec.yml @@ -0,0 +1,9 @@ +name: simple_example +depends: + - name: inspec-gcp + git: https://github.com/inspec/inspec-gcp.git + tag: v0.10.0 +attributes: + - name: project_id + required: true + type: string diff --git a/test/integration/agent_policy_update_example/controls/gcloud.rb b/test/integration/agent_policy_update_example/controls/gcloud.rb new file mode 100644 index 0000000..7de9722 --- /dev/null +++ b/test/integration/agent_policy_update_example/controls/gcloud.rb @@ -0,0 +1,95 @@ +# Copyright 2020 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') +description = attribute('description') +agent_rules = attribute('agent_rules') +group_labels = attribute('group_labels') +os_types = attribute('os_types') +zones = attribute('zones') +instances = attribute('instances') + +control "gcloud" do + title "gcloud" + + describe command("gcloud alpha compute instances ops-agents policies describe " \ + "ops-agents-test-policy-update --project=#{attribute("project_id")} " \ + "--quiet --format=json") do + its(:exit_status) { should eq 0 } + its(:stderr) { should eq "" } + + let!(:data) do + if subject.exit_status == 0 + JSON.parse(subject.stdout) + else + {} + end + end + + + describe "description" do + it "is equal to the description created by the module" do + expect(data['description']).to eq description + end + end + + describe "agent_rules" do + it "is equal to the agent_rules created by the module" do + data['agent_rules'].zip(agent_rules).each do |agent_rule_actual, agent_rule_expected| + agent_rule_actual = agent_rule_actual.transform_keys(&:to_sym) + expect(agent_rule_actual).to eq agent_rule_expected + end + end + end + + describe "group_labels" do + it "is equal to the group_labels created by the module" do + if group_labels == [] + expect(data['assignment']['group_labels']).to eq group_labels + else + data['assignment']['group_labels'].zip(group_labels).each do \ + |group_labels_actual, group_labels_expected| + group_labels_actual.zip(group_labels_expected).each do \ + |group_label_actual, group_label_expected| + expect(group_label_actual[0]).to eq group_label_expected[:name] + expect(group_label_actual[1]).to eq group_label_expected[:value] + end + end + end + end + end + + describe "os_types" do + it "is equal to the os_types created by the module" do + data['assignment']['os_types'].zip(os_types).each do \ + |os_types_actual, os_types_expected| + os_types_actual = os_types_actual.transform_keys(&:to_sym) + expect(os_types_actual).to eq os_types_expected + end + end + end + + describe "zones" do + it "is equal to the zones created by the module" do + expect(data['assignment']['zones']).to eq zones + end + end + + describe "instances" do + it "is equal to the instances created by the module" do + expect(data['assignment']['instances']).to eq instances + end + end + end +end diff --git a/test/integration/agent_policy_update_example/inspec.yml b/test/integration/agent_policy_update_example/inspec.yml new file mode 100644 index 0000000..f07c4e5 --- /dev/null +++ b/test/integration/agent_policy_update_example/inspec.yml @@ -0,0 +1,31 @@ +name: update_example +depends: + - name: inspec-gcp + git: https://github.com/inspec/inspec-gcp.git + tag: v0.10.0 +attributes: + - name: project_id + required: true + type: string + - name: description + required: false + type: string + default: "None" + - name: agent_rules + required: true + type: any + - name: group_labels + required: false + type: any + default: [] + - name: os_types + required: true + type: any + - name: zones + required: false + type: any + default: [] + - name: instances + required: false + type: any + default: [] diff --git a/test/setup/main.tf b/test/setup/main.tf index 4c752ba..dca97cc 100644 --- a/test/setup/main.tf +++ b/test/setup/main.tf @@ -16,18 +16,20 @@ module "project" { source = "terraform-google-modules/project-factory/google" - version = "~> 8.0" + version = "~> 9.0" - name = "ci-cloud_operations" - random_project_id = "true" - org_id = var.org_id - folder_id = var.folder_id - billing_account = var.billing_account + name = "ci-cloud-operations" + random_project_id = "true" + org_id = var.org_id + folder_id = var.folder_id + billing_account = var.billing_account skip_gcloud_download = true activate_apis = [ "cloudresourcemanager.googleapis.com", - "storage-api.googleapis.com", - "serviceusage.googleapis.com" + "serviceusage.googleapis.com", + "logging.googleapis.com", + "monitoring.googleapis.com", + "osconfig.googleapis.com" ] } diff --git a/test/integration/simple_example/controls/gcp.rb b/test/task_helper_functions.sh similarity index 51% rename from test/integration/simple_example/controls/gcp.rb rename to test/task_helper_functions.sh index 3b5382b..99daa98 100644 --- a/test/integration/simple_example/controls/gcp.rb +++ b/test/task_helper_functions.sh @@ -1,10 +1,12 @@ -# Copyright 2018 Google LLC +#!/usr/bin/env bash + +# Copyright 2020 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 +# 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, @@ -12,10 +14,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -control "gcp" do - title "GCP Resources" +function test_bats() { + SCRIPT_DIR="$( realpath "$( dirname "${BASH_SOURCE[0]}" )" )" + TEST_PATH="${SCRIPT_DIR}/agent-policy-tests/test-script-utils.bats" + bats "$TEST_PATH" +} - describe google_storage_bucket(name: attribute("bucket_name")) do - it { should exist } - end -end +function test_integration_update() { + SCRIPT_DIR="$( realpath "$( dirname "${BASH_SOURCE[0]}" )" )" + TEST_PATH="${SCRIPT_DIR}/agent-policy-tests/test-integration-update.sh" + "$TEST_PATH" +}