Skip to content

Commit

Permalink
Merge pull request #48 from GSA-TTS/test-modules
Browse files Browse the repository at this point in the history
Add module tests
  • Loading branch information
rahearn authored Jun 27, 2024
2 parents 368ee53 + 5eaf4f0 commit f841b60
Show file tree
Hide file tree
Showing 11 changed files with 534 additions and 2 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
path: ["cg_space", "clamav", "database", "domain", "redis", "s3"]
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: terraform validate ${{ matrix.path }}
uses: dflook/terraform-validate@v1
Expand All @@ -31,7 +31,7 @@ jobs:
path: ["cg_space", "clamav", "database", "domain", "redis", "s3"]
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: terraform fmt ${{ matrix.path }}
uses: dflook/terraform-fmt-check@v1
Expand Down
26 changes: 26 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Terraform Test

on:
pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
name: Integration test
strategy:
fail-fast: false
max-parallel: 2
matrix:
module: ["s3", "database", "redis", "cg_space", "domain", "clamav"]
steps:
- uses: actions/checkout@v4

- name: terraform test ${{ matrix.module }}
uses: dflook/terraform-test@v1
env:
CF_USER: ${{ secrets.CF_USER }}
CF_PASSWORD: ${{ secrets.CF_PASSWORD }}
with:
path: ${{ matrix.module }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Local .terraform directories
**/.terraform/*
**/.terraform.lock.hcl

# .tfstate files
*.tfstate
Expand Down
1 change: 1 addition & 0 deletions .terraform-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.8.5
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ Creates a new cloud.gov space, such as when creating an egress space, and output

`managers`, `developers`, and `deployers` are all optional, but you probably want to set at least one of them, depending on your use case.

* `managers` are granted the [Space Manager](https://docs.cloudfoundry.org/concepts/roles.html#activeroles) role
* `developers` are granted the [Space Developer](https://docs.cloudfoundry.org/concepts/roles.html#activeroles) role
* `deployers` are granted both manager and developer roles

```
module "egress_space" {
source = "github.com/18f/terraform-cloudgov//cg_space?ref=v1.0.0"
Expand All @@ -140,3 +144,18 @@ module "egress_space" {
]
}
```

## Testing


> **Warning**
Tests provision resources in the real world when not using `mock_provider`! Take care that `CF_USER`/`CF_PASSWORD` are set to an account in a suitable non-production space. If other providers, such as the AWS provider, are used, ensure the same care is taken with their credentials in your shell before running `terraform test`.

[Terraform tests](https://developer.hashicorp.com/terraform/language/tests) are in progress of being written. To run for any module with a `tests` directory:

1. Set `CF_USER` and `CF_PASSWORD` env variables with SpaceDeployer credentials that can access the space(s) being used for tests
1. cd to module root. Example: `cd s3`
1. Run `terraform init`
1. Run `terraform test`

When updating code, try to cover every input and output variable with at least one test to verify it is connected properly.
87 changes: 87 additions & 0 deletions cg_space/tests/creation.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
mock_provider "cloudfoundry" {
override_data {
target = data.cloudfoundry_user.managers["user.manager@gsa.gov"]
values = {
id = "1e5143a4-aa47-483c-8352-557988d5cc7a"
}
}
override_data {
target = data.cloudfoundry_user.deployers["user.manager@gsa.gov"]
values = {
id = "1e5143a4-aa47-483c-8352-557988d5cc7a"
}
}
override_data {
target = data.cloudfoundry_user.developers["user.developer@gsa.gov"]
values = {
id = "2c945842-13ee-4383-84ad-34ecbcde5ce6"
}
}
}

variables {
cf_org_name = "gsa-tts-devtools-prototyping"
cf_space_name = "terraform-cloudgov-ci-tests-egress"
}

run "test_space_creation" {
assert {
condition = cloudfoundry_space.space.id == output.space_id
error_message = "Space ID output must match the new space"
}

assert {
condition = cloudfoundry_space.space.name == var.cf_space_name
error_message = "Space name should match the cf_space_name variable"
}
}

run "test_manager_only" {
variables {
managers = ["user.manager@gsa.gov"]
}

assert {
condition = cloudfoundry_space_users.space_permissions.managers == toset(["1e5143a4-aa47-483c-8352-557988d5cc7a"])
error_message = "Should be able to set Space Managers"
}

assert {
condition = length(cloudfoundry_space_users.space_permissions.developers) == 0
error_message = "Should not have set any Space Developers"
}
}

run "test_individual_permissions" {
variables {
managers = ["user.manager@gsa.gov"]
developers = ["user.developer@gsa.gov"]
}

assert {
condition = cloudfoundry_space_users.space_permissions.managers == toset(["1e5143a4-aa47-483c-8352-557988d5cc7a"])
error_message = "Should be able to set Space Managers"
}

assert {
condition = cloudfoundry_space_users.space_permissions.developers == toset(["2c945842-13ee-4383-84ad-34ecbcde5ce6"])
error_message = "Should be able to set Space Developers"
}
}

run "test_deployer_permissions" {
variables {
developers = ["user.developer@gsa.gov"]
deployers = ["user.manager@gsa.gov"]
}

assert {
condition = cloudfoundry_space_users.space_permissions.managers == toset(["1e5143a4-aa47-483c-8352-557988d5cc7a"])
error_message = "Should be able to set Space Managers via var.deployers"
}

assert {
condition = cloudfoundry_space_users.space_permissions.developers == toset(["2c945842-13ee-4383-84ad-34ecbcde5ce6", "1e5143a4-aa47-483c-8352-557988d5cc7a"])
error_message = "Should set Space Developers to var.developers + var.deployers"
}
}
121 changes: 121 additions & 0 deletions clamav/tests/creation.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
mock_provider "cloudfoundry" {}

variables {
cf_org_name = "gsa-tts-devtools-prototyping"
cf_space_name = "terraform-cloudgov-ci-tests"
app_name_or_id = "terraform_cloudgov_app"
name = "terraform-cloudgov-clamav-test"
clamav_image = "ghcr.io/gsa-tts/clamav-rest/clamav:TAG"
max_file_size = "30M"
}

run "test_app_creation" {
assert {
condition = cloudfoundry_app.clamav_api.id == output.app_id
error_message = "App ID output must match the clamav app ID"
}

assert {
condition = cloudfoundry_route.clamav_route.id == output.route_id
error_message = "Route ID output must match the ID of the route to the clamav app"
}

assert {
condition = cloudfoundry_route.clamav_route.endpoint == output.endpoint
error_message = "Endpoint output must match the clamav route endpoint"
}

assert {
condition = cloudfoundry_route.clamav_route.hostname == var.name
error_message = "ClamAV route uses the service name for hostname"
}

assert {
condition = cloudfoundry_app.clamav_api.name == var.name
error_message = "App name matches var.name"
}

assert {
condition = cloudfoundry_app.clamav_api.memory == var.clamav_memory
error_message = "App memory is passed as var.clamav_memory"
}

assert {
condition = cloudfoundry_app.clamav_api.docker_image == var.clamav_image
error_message = "Docker image is passed directly in as var.clamav_image"
}

assert {
condition = [for r in cloudfoundry_app.clamav_api.routes : r.route] == [cloudfoundry_route.clamav_route.id]
error_message = "ClamAV app has the route set on the internal domain"
}

assert {
condition = cloudfoundry_app.clamav_api.environment["MAX_FILE_SIZE"] == var.max_file_size
error_message = "Sets the max file size to var.max_file_size"
}

assert {
condition = lookup(cloudfoundry_app.clamav_api.environment, "PROXY_SERVER", null) == null
error_message = "Does not set the PROXY_SERVER environment by default"
}

assert {
condition = lookup(cloudfoundry_app.clamav_api.environment, "PROXY_PORT", null) == null
error_message = "Does not set the PROXY_PORT environment by default"
}

assert {
condition = lookup(cloudfoundry_app.clamav_api.environment, "PROXY_USERNAME", null) == null
error_message = "Does not set the PROXY_USERNAME environment by default"
}

assert {
condition = lookup(cloudfoundry_app.clamav_api.environment, "PROXY_PASSWORD", null) == null
error_message = "Does not set the PROXY_PASSWORD environment by default"
}

assert {
condition = [for policy in cloudfoundry_network_policy.clamav_routing.policy : policy.source_app] == [data.cloudfoundry_app.app.id]
error_message = "Routing policy allows traffic from the source app"
}

assert {
condition = [for policy in cloudfoundry_network_policy.clamav_routing.policy : policy.destination_app] == [cloudfoundry_app.clamav_api.id]
error_message = "Routing policy allows traffic to the clamav app"
}

assert {
condition = [for policy in cloudfoundry_network_policy.clamav_routing.policy : policy.port] == ["61443"]
error_message = "Routing policy opens up traffic on the internal https port"
}
}

run "test_with_proxy" {
variables {
proxy_server = "proxy.server"
proxy_port = "8900"
proxy_username = "username"
proxy_password = "not-a-real-password"
}

assert {
condition = cloudfoundry_app.clamav_api.environment["PROXY_SERVER"] == var.proxy_server
error_message = "Proxy variables are set properly"
}

assert {
condition = cloudfoundry_app.clamav_api.environment["PROXY_PORT"] == var.proxy_port
error_message = "Proxy variables are set properly"
}

assert {
condition = cloudfoundry_app.clamav_api.environment["PROXY_USERNAME"] == var.proxy_username
error_message = "Proxy variables are set properly"
}

assert {
condition = cloudfoundry_app.clamav_api.environment["PROXY_PASSWORD"] == var.proxy_password
error_message = "Proxy variables are set properly"
}
}
47 changes: 47 additions & 0 deletions database/tests/creation.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
mock_provider "cloudfoundry" {
mock_data "cloudfoundry_service" {
defaults = {
service_plans = {
"micro-psql" = "03c93c7b-3e1c-47c5-a6c3-1df151d280dd"
}
}
}
}

variables {
cf_org_name = "gsa-tts-devtools-prototyping"
cf_space_name = "terraform-cloudgov-ci-tests"
rds_plan_name = "micro-psql"
name = "terraform-cloudgov-rds-test"
tags = ["terraform-cloudgov", "tests"]
json_params = jsonencode({
backup_retention_period = 30
})
}

run "test_db_creation" {
assert {
condition = cloudfoundry_service_instance.rds.id == output.instance_id
error_message = "Instance ID output must match the service instance"
}

assert {
condition = cloudfoundry_service_instance.rds.service_plan == data.cloudfoundry_service.rds.service_plans[var.rds_plan_name]
error_message = "Service Plan should match the rds_plan_name variable"
}

assert {
condition = cloudfoundry_service_instance.rds.name == var.name
error_message = "Service instance name should match the name variable"
}

assert {
condition = cloudfoundry_service_instance.rds.tags == var.tags
error_message = "Service instance tags should match the tags variable"
}

assert {
condition = cloudfoundry_service_instance.rds.json_params == "{\"backup_retention_period\":30}"
error_message = "Service instance json_params should be configurable"
}
}
Loading

0 comments on commit f841b60

Please sign in to comment.