diff --git a/.github/workflows/auto.yml b/.github/workflows/auto.yml index 305c7f72..eb9cef71 100644 --- a/.github/workflows/auto.yml +++ b/.github/workflows/auto.yml @@ -63,6 +63,15 @@ jobs: ${{ github.workspace }}/${m} done + - name: Lint tests directory in a loop + run: | + for m in $(ls -1d tests/*/) + do + tflint \ + --config ${{ github.workspace }}/.tflint.hcl \ + ${{ github.workspace }}/${m} + done + - name: Lint examples directory in a loop run: | for m in $(ls -1d examples/*/) diff --git a/.github/workflows/dispatcher.yml b/.github/workflows/dispatcher.yml new file mode 100644 index 00000000..7f1c6ed5 --- /dev/null +++ b/.github/workflows/dispatcher.yml @@ -0,0 +1,29 @@ +name: Pull Request Dispatcher + +on: + issue_comment: + types: + - created + +jobs: + slash_command_dispatch: + name: Slash Command Dispatcher + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Slash Command Dispatch + uses: peter-evans/slash-command-dispatch@a28ee6cd74d5200f99e247ebc7b365c03ae0ef3c # v3.0.1 + with: + # The `public_repo` scope is required by this token to create repository_dispatch and workflow_dispatch + # events on public repositories. The default GITHUB_TOKEN does not support the `public_repo` scope. + token: ${{ secrets.GH_DISPATCH_TOKEN }} + reaction-token: ${{ secrets.GITHUB_TOKEN }} + commands: | + test + destroy + help + permission: maintain + issue-type: pull-request + event-type-suffix: -command + \ No newline at end of file diff --git a/.github/workflows/handler-destroy.yml b/.github/workflows/handler-destroy.yml new file mode 100644 index 00000000..77e44a34 --- /dev/null +++ b/.github/workflows/handler-destroy.yml @@ -0,0 +1,208 @@ +name: Pull Request Destroy Handler + +on: + repository_dispatch: + types: + - destroy-command + +jobs: + public_active_active: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/destroy.yml@main + secrets: inherit + name: Destroy Public Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'public-active-active' }} + with: + cloud: Azure + test_name: Public Active/Active + utility_test: false + is_replicated_deployment: false + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + work_dir: ./tests/public-active-active + TFC_token_secret_name: PUBLIC_ACTIVE_ACTIVE_TFC_TOKEN + + private_active_active: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/destroy.yml@main + secrets: inherit + name: Destroy Private Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'private-active-active' }} + with: + cloud: Azure + test_name: Private Active/Active + utility_test: false + is_replicated_deployment: false + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + work_dir: ./tests/private-active-active + TFC_token_secret_name: PRIVATE_ACTIVE_ACTIVE_TFC_TOKEN + + private_tcp_active_active: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/destroy.yml@main + secrets: inherit + name: Destroy Private TCP Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'private-tcp-active-active' }} + with: + cloud: Azure + test_name: Private TCP Active/Active + utility_test: false + is_replicated_deployment: false + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + work_dir: ./tests/private-tcp-active-active + TFC_token_secret_name: PRIVATE_TCP_ACTIVE_ACTIVE_TFC_TOKEN + + standalone_external: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/destroy.yml@main + secrets: inherit + name: Destroy Standalone External + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'standalone-external' }} + with: + cloud: Azure + test_name: Standalone External + utility_test: false + is_replicated_deployment: false + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + work_dir: ./tests/standalone-external + TFC_token_secret_name: STANDALONE_EXTERNAL_TFC_TOKEN + TFC_workspace_substitution_pattern: 's/terraform {/terraform {\n\ + backend "remote" {\n\ + organization = "terraform-enterprise-modules-test"\n\ + workspaces {\n\ + name = "azure-standalone-external"\n\ + }\n\ + }\n/' + + standalone_mounted_disk: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/destroy.yml@main + secrets: inherit + name: Destroy Standalone Mounted Disk + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'standalone-mounted-disk' }} + with: + cloud: Azure + test_name: Standalone Mounted Disk + utility_test: false + is_replicated_deployment: false + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + work_dir: ./tests/standalone-mounted-disk + TFC_token_secret_name: STANDALONE_MOUNTED_DISK_TFC_TOKEN + TFC_workspace_substitution_pattern: 's/terraform {/terraform {\n\ + backend "remote" {\n\ + organization = "terraform-enterprise-modules-test"\n\ + workspaces {\n\ + name = "azure-standalone-mounted-disk"\n\ + }\n\ + }\n/' + + public_active_active_replicated: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/destroy.yml@main + secrets: inherit + name: Destroy Public Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'public-active-active-replicated' }} + with: + cloud: Azure + test_name: Public Active/Active + utility_test: false + is_replicated_deployment: true + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + work_dir: ./tests/public-active-active + TFC_token_secret_name: PUBLIC_ACTIVE_ACTIVE_REPLICATED_TFC_TOKEN + TFC_workspace_substitution_pattern: s/azure-public-active-active/azure-public-active-active-replicated/ + + private_active_active_replicated: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/destroy.yml@main + secrets: inherit + name: Destroy Private Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'private-active-active-replicated' }} + with: + cloud: Azure + test_name: Private Active/Active + utility_test: false + is_replicated_deployment: true + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + work_dir: ./tests/private-active-active + TFC_token_secret_name: PRIVATE_ACTIVE_ACTIVE_REPLICATED_TFC_TOKEN + TFC_workspace_substitution_pattern: s/azure-private-active-active/azure-private-active-active-replicated/ + + private_tcp_active_active_replicated: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/destroy.yml@main + secrets: inherit + name: Destroy Private TCP Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'private-tcp-active-active-replicated' }} + with: + cloud: Azure + test_name: Private TCP Active/Active + utility_test: false + is_replicated_deployment: true + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + work_dir: ./tests/private-tcp-active-active + TFC_token_secret_name: PRIVATE_TCP_ACTIVE_ACTIVE_REPLICATED_TFC_TOKEN + TFC_workspace_substitution_pattern: s/azure-private-tcp-active-active/azure-private-tcp-active-active-replicated/ + + standalone_external_replicated: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/destroy.yml@main + secrets: inherit + name: Destroy Standalone External + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'standalone-external-replicated' }} + with: + cloud: Azure + test_name: Standalone External + utility_test: false + is_replicated_deployment: true + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + work_dir: ./tests/standalone-external + TFC_token_secret_name: STANDALONE_EXTERNAL_REPLICATED_TFC_TOKEN + TFC_workspace_substitution_pattern: 's/terraform {/terraform {\n\ + backend "remote" {\n\ + organization = "terraform-enterprise-modules-test"\n\ + workspaces {\n\ + name = "azure-standalone-external-replicated"\n\ + }\n\ + }\n/' + + standalone_mounted_disk_replicated: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/destroy.yml@main + secrets: inherit + name: Destroy Standalone Mounted Disk + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'standalone-mounted-disk-replicated' }} + with: + cloud: Azure + test_name: Standalone Mounted Disk + utility_test: false + is_replicated_deployment: true + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + work_dir: ./tests/standalone-mounted-disk + TFC_token_secret_name: STANDALONE_MOUNTED_DISK_REPLICATED_TFC_TOKEN + TFC_workspace_substitution_pattern: 's/terraform {/terraform {\n\ + backend "remote" {\n\ + organization = "terraform-enterprise-modules-test"\n\ + workspaces {\n\ + name = "azure-standalone-mounted-disk-replicated"\n\ + }\n\ + }\n/' diff --git a/.github/workflows/handler-help.yml b/.github/workflows/handler-help.yml new file mode 100644 index 00000000..a74aef20 --- /dev/null +++ b/.github/workflows/handler-help.yml @@ -0,0 +1,43 @@ +name: Pull Request Help Handler + +on: + repository_dispatch: + types: + - help-command + +jobs: + help: + name: Run help + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Update comment + uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + repository: ${{ github.event.client_payload.github.payload.repository.full_name }} + comment-id: ${{ github.event.client_payload.github.payload.comment.id }} + body: | + > | Command | Description | + > | ------- | ----------- | + > | /test [destroy=false] | Run the Terraform test workflow on the modules in the tests/ directory. Unnamed arguments can be "all" to run all test cases or specific test case names to only run selected cases. The named argument "destroy=false" will disable the destruction of test infrastructure for debugging purposes. | + > | /destroy | Destroy any resources that may still be in Terraform state from previous tests. Unnamed arguments can be "all" to destroy all resources from all test cases or specific test case names to only destroy selected test case resources. | + > | /help | Shows this help message | + > + > ## Test Case Names + > + > ### FDO + > * private-active-active + > * private-tcp-active-active + > * public-active-active + > * standalone-external + > * standalone-mounted-disk + > + > ### Replicated + > * private-active-active-replicated + > * private-tcp-active-active-replicated + > * public-active-active-replicated + > * standalone-external-replicated + > * standalone-mounted-disk-replicated + reaction-type: confused diff --git a/.github/workflows/handler-test.yml b/.github/workflows/handler-test.yml new file mode 100644 index 00000000..32a1f025 --- /dev/null +++ b/.github/workflows/handler-test.yml @@ -0,0 +1,212 @@ +name: Pull Request Test Handler + +on: + repository_dispatch: + types: + - test-command + +jobs: + standalone_external: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/azure-tests.yml@main + secrets: inherit + name: Standalone External + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'standalone-external' }} + with: + test_name: Standalone External + is_replicated_deployment: false + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + work_dir: ./tests/standalone-external + k6_work_dir: ./tests/tfe-load-test + utility_test: false + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + TFC_token_secret_name: STANDALONE_EXTERNAL_TFC_TOKEN + TFC_workspace_substitution_pattern: 's/terraform {/terraform {\n\ + backend "remote" {\n\ + organization = "terraform-enterprise-modules-test"\n\ + workspaces {\n\ + name = "azure-standalone-external"\n\ + }\n\ + }\n/' + + standalone_mounted_disk: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/azure-tests.yml@main + secrets: inherit + name: Standalone Mounted Disk + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'standalone-mounted-disk' }} + with: + test_name: Standalone Mounted Disk + is_replicated_deployment: false + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + work_dir: ./tests/standalone-mounted-disk + k6_work_dir: ./tests/tfe-load-test + utility_test: false + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + TFC_token_secret_name: STANDALONE_MOUNTED_DISK_TFC_TOKEN + TFC_workspace_substitution_pattern: 's/terraform {/terraform {\n\ + backend "remote" {\n\ + organization = "terraform-enterprise-modules-test"\n\ + workspaces {\n\ + name = "azure-standalone-mounted-disk"\n\ + }\n\ + }\n/' + + public_active_active: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/azure-tests.yml@main + secrets: inherit + name: Public Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'public-active-active' }} + with: + test_name: Public Active/Active + is_replicated_deployment: false + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + work_dir: ./tests/public-active-active + k6_work_dir: ./tests/tfe-load-test + utility_test: false + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + TFC_token_secret_name: PUBLIC_ACTIVE_ACTIVE_TFC_TOKEN + + private_active_active: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/azure-tests.yml@main + secrets: inherit + name: Private Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'private-active-active' }} + with: + test_name: Private Active/Active + is_replicated_deployment: false + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + work_dir: ./tests/private-active-active + k6_work_dir: ./tests/tfe-load-test + utility_test: false + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + TFC_token_secret_name: PRIVATE_ACTIVE_ACTIVE_TFC_TOKEN + bastion_ssh_private_key_secret_name: PRIVATE_ACTIVE_ACTIVE_BASTION_SSH_KEY_BASE64 + + private_tcp_active_active: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/azure-tests.yml@main + secrets: inherit + name: Private TCP Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'private-tcp-active-active' }} + with: + test_name: Private TCP Active/Active + is_replicated_deployment: false + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + work_dir: ./tests/private-tcp-active-active + k6_work_dir: ./tests/tfe-load-test + utility_test: false + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + TFC_token_secret_name: PRIVATE_TCP_ACTIVE_ACTIVE_TFC_TOKEN + bastion_ssh_private_key_secret_name: PRIVATE_TCP_ACTIVE_ACTIVE_BASTION_SSH_KEY_BASE64 + + standalone_external_replicated: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/azure-tests.yml@main + secrets: inherit + name: Standalone External + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'standalone-external-replicated' }} + with: + test_name: Standalone External + is_replicated_deployment: true + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + work_dir: ./tests/standalone-external + k6_work_dir: ./tests/tfe-load-test + utility_test: false + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + TFC_token_secret_name: STANDALONE_EXTERNAL_REPLICATED_TFC_TOKEN + TFC_workspace_substitution_pattern: 's/terraform {/terraform {\n\ + backend "remote" {\n\ + organization = "terraform-enterprise-modules-test"\n\ + workspaces {\n\ + name = "azure-standalone-external-replicated"\n\ + }\n\ + }\n/' + + standalone_mounted_disk_replicated: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/azure-tests.yml@main + secrets: inherit + name: Standalone Mounted Disk + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'standalone-mounted-disk-replicated' }} + with: + test_name: Standalone Mounted Disk + is_replicated_deployment: true + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + work_dir: ./tests/standalone-mounted-disk + k6_work_dir: ./tests/tfe-load-test + utility_test: false + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + TFC_token_secret_name: STANDALONE_MOUNTED_DISK_REPLICATED_TFC_TOKEN + TFC_workspace_substitution_pattern: 's/terraform {/terraform {\n\ + backend "remote" {\n\ + organization = "terraform-enterprise-modules-test"\n\ + workspaces {\n\ + name = "azure-standalone-mounted-disk-replicated"\n\ + }\n\ + }\n/' + + public_active_active_replicated: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/azure-tests.yml@main + secrets: inherit + name: Public Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'public-active-active-replicated' }} + with: + test_name: Public Active/Active + is_replicated_deployment: true + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + work_dir: ./tests/public-active-active + k6_work_dir: ./tests/tfe-load-test + utility_test: false + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + TFC_token_secret_name: PUBLIC_ACTIVE_ACTIVE_REPLICATED_TFC_TOKEN + TFC_workspace_substitution_pattern: s/azure-public-active-active/azure-public-active-active-replicated/ + + private_active_active_replicated: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/azure-tests.yml@main + secrets: inherit + name: Private Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'private-active-active-replicated' }} + with: + test_name: Private Active/Active + is_replicated_deployment: true + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + work_dir: ./tests/private-active-active + k6_work_dir: ./tests/tfe-load-test + utility_test: false + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + TFC_token_secret_name: PRIVATE_ACTIVE_ACTIVE_REPLICATED_TFC_TOKEN + TFC_workspace_substitution_pattern: s/azure-private-active-active/azure-private-active-active-replicated/ + bastion_ssh_private_key_secret_name: PRIVATE_ACTIVE_ACTIVE_BASTION_SSH_KEY_BASE64 + + private_tcp_active_active_replicated: + uses: hashicorp/terraform-random-tfe-utility/.github/workflows/azure-tests.yml@main + secrets: inherit + name: Private TCP Active/Active + if: ${{ github.event.client_payload.slash_command.args.unnamed.all == 'all' || github.event.client_payload.slash_command.args.unnamed.all == 'private-tcp-active-active-replicated' }} + with: + test_name: Private TCP Active/Active + is_replicated_deployment: true + module_repository_id: hashicorp/terraform-azurerm-terraform-enterprise + work_dir: ./tests/private-tcp-active-active + k6_work_dir: ./tests/tfe-load-test + utility_test: false + pull_request_repo_name: ${{ github.event.client_payload.github.payload.repository.full_name }} + pull_request_ref: ${{ github.event.client_payload.pull_request.head.sha }} + pull_request_comment_id: ${{ github.event.client_payload.github.payload.comment.id }} + TFC_token_secret_name: PRIVATE_TCP_ACTIVE_ACTIVE_REPLICATED_TFC_TOKEN + TFC_workspace_substitution_pattern: s/azure-private-tcp-active-active/azure-private-tcp-active-active-replicated/ + bastion_ssh_private_key_secret_name: PRIVATE_TCP_ACTIVE_ACTIVE_BASTION_SSH_KEY_BASE64 diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..c8421a02 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,63 @@ +# Terraform Test + +The directories in here are considered Terraform Test Modules (TTM). These TTM +directories are used in our continuous integration processes. The README of each +TTM will document for which CI process the TTM is used. + +These commands will be run on Pull Requests automatically: + +- `terraform fmt` +- `tflint` + +## TFE Module CI Testing with GitHub Actions + +[GitHub Actions](../.github/workflows/handler-test.yml) is used to create a build +that will ensure that the module creates the desired Terraform Enterprise (TFE) +environment. These tests also leverage Terraform Cloud workspaces to allow +maintainers to run and audit contributions to this repository. + +### Commands + +These commands will be run by Maintainers manually after initial review: + +- `terraform init` +- `terraform validate` +- `terraform plan` +- `terraform apply` +- `k6` +- `terraform destroy` + +## TFE Integration Testing with CircleCI + +TFE integration testing is perfomed via CircleCI inside the [`ptfe-replicated`](https://github.com/hashicorp/ptfe-replicated/blob/master/.circleci/config.yml) +repository. Various environment scenarios are created via this module's TTMs as well as that +of [AWS's](https://github.com/hashicorp/terraform-aws-terraform-enterprise/tree/main/tests) and [GCP's](https://github.com/hashicorp/terraform-aws-terraform-enterprise/tree/main/tests). The TFE +release under test is used to install TFE onto said environment, and integration tests are performed. + +## Local Testing with k6 and tfe-load-test + +Github Actions and CircleCI test the modules present in the test directory using k6 and configuration located in the +[tfe-load-test](https://github.com/hashicorp/tfe-load-test) repository. Each module has a run-tests.sh script present +that automates the same actions taken by the aforementioned CI systems when validating a running TFE instance. These +scripts assume: + +1. You have k6 installed on your system on a known path +1. The tfe-load-test repository is cloned on your local filesystem +1. For instances requiring an SSH proxy you must have a local copy of the bastion + SSH private key. + +Usage: + +``` +./run-tests.sh -h +This script bootstraps the k6 / tfe-load-test environment and executes a smoke-test against an active TFE instance deployed with the terraform-azure-terraform-enterprise module. + +Syntax: run-tests.sh [-h|k|t|b|s|l] +options: +h Print this Help. +k (required) The path to the k6 binary. +t (required) The path to the tfe-load-test repository. +b (required) The path to the bastion server ssh private key. +s (optional) Skip the admin user initialization and tfe token retrieval (This is useful for secondary / repeated test runs). +l (optional) Bind the test proxy to localhost instead of the detected ip address (This is useful when testing from within a docker container). +``` diff --git a/tests/private-active-active/README.md b/tests/private-active-active/README.md new file mode 100644 index 00000000..57eaf51c --- /dev/null +++ b/tests/private-active-active/README.md @@ -0,0 +1,40 @@ +# TEST: Private Active/Active Terraform Enterprise + +## About this test + +This test for Terraform Enterprise creates a TFE +installation with the following traits. + +- Active/Active mode +- Large instance size (16 vCPUs) +- RHEL as the operating system +- An internally exposed network +- A proxy without TLS termination +- An Application Gateway +- End to end TLS +- External PostgreSQL +- External Redis +- Redis authentication enabled +- No Redis encryption in transit +- No Redis encryption at rest + +## Pre-requisites + +This test assumes the following resources exist. + +- a DNS zone +- an Azure Key Vault in which the following are stored: + - TFE CA certificate (certificate) + - proxy CA certificate (secret) + - proxy CA certificate private key (secret) + - proxy SSH public key (secret) + - proxy SSH private key (secret) + - bastion SSH public key (secret) + - bastion SSH private key (secret) + - Base64 encoded TFE license (secret) + +## How this test is used + +This test is leveraged by this repository's continuous integration setup which +leverages workspaces in a Terraform Cloud workspaces as a remote backend so that +Terraform state is preserved. diff --git a/tests/private-active-active/data.tf b/tests/private-active-active/data.tf new file mode 100644 index 00000000..9c6861dc --- /dev/null +++ b/tests/private-active-active/data.tf @@ -0,0 +1,34 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +data "azurerm_key_vault_certificate" "load_balancer" { + name = var.load_balancer_certificate_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "vm_certificate" { + name = var.vm_certificate_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "vm_key" { + name = var.vm_key_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "tfe_license" { + count = var.tfe_license_secret_name == null ? 0 : 1 + + name = var.tfe_license_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "bastion_public_ssh_key" { + name = var.bastion_public_ssh_key_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "proxy_public_ssh_key" { + name = var.proxy_public_ssh_key_secret_name + key_vault_id = var.key_vault_id +} diff --git a/tests/private-active-active/locals.tf b/tests/private-active-active/locals.tf new file mode 100644 index 00000000..3fd0dd2a --- /dev/null +++ b/tests/private-active-active/locals.tf @@ -0,0 +1,19 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +locals { + common_tags = { + Environment = "${local.friendly_name_prefix}-test-private-active-active" + Description = "Private Active/Active" + Repository = "hashicorp/terraform-azurerm-terraform-enterprise" + Team = "Terraform Enterprise" + OkToDelete = "True" + } + + friendly_name_prefix = random_string.friendly_name.id + network_proxy_subnet_cidr = "10.0.80.0/20" + proxy_user = "proxyuser" + proxy_port = "3128" + registry = "quay.io" + resource_group_name = module.private_active_active.resource_group_name +} diff --git a/tests/private-active-active/main.tf b/tests/private-active-active/main.tf new file mode 100644 index 00000000..95e0c14e --- /dev/null +++ b/tests/private-active-active/main.tf @@ -0,0 +1,92 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "random_string" "friendly_name" { + length = 4 + upper = false + numeric = false + special = false +} + +module "bastion_vm" { + source = "../../fixtures/bastion_vm" + friendly_name_prefix = local.friendly_name_prefix + + location = var.location + resource_group_name = local.resource_group_name + virtual_network_name = module.private_active_active.network.network.name + network_allow_range = var.network_allow_range + bastion_subnet_cidr = "10.0.16.0/20" + ssh_public_key = data.azurerm_key_vault_secret.bastion_public_ssh_key.value + bastion_user = "bastionuser" + + tags = local.common_tags +} + +module "test_proxy" { + source = "../../fixtures/test_proxy" + friendly_name_prefix = local.friendly_name_prefix + + location = var.location + resource_group_name = local.resource_group_name + key_vault_id = var.key_vault_id + virtual_network_name = module.private_active_active.network.network.name + proxy_subnet_cidr = local.network_proxy_subnet_cidr + proxy_user = local.proxy_user + proxy_public_ssh_key_secret_name = data.azurerm_key_vault_secret.proxy_public_ssh_key.value + + tags = local.common_tags + +} + +module "private_active_active" { + source = "../../" + + location = var.location + friendly_name_prefix = local.friendly_name_prefix + + resource_group_name_dns = var.resource_group_name_dns + domain_name = var.domain_name + iact_subnet_list = ["${module.bastion_vm.private_ip}/32"] + + # Bootstrapping resources + bypass_preflight_checks = true + load_balancer_certificate = data.azurerm_key_vault_certificate.load_balancer + tfe_license_secret_id = var.tfe_license_secret_name == null ? var.tfe_license_secret_name : data.azurerm_key_vault_secret.tfe_license[0].id + vm_certificate_secret = data.azurerm_key_vault_secret.vm_certificate + vm_key_secret = data.azurerm_key_vault_secret.vm_key + tls_bootstrap_cert_pathname = "/var/lib/terraform-enterprise/certificate.pem" + tls_bootstrap_key_pathname = "/var/lib/terraform-enterprise/key.pem" + + # Behind proxy information + proxy_ip = module.test_proxy.private_ip + proxy_port = local.proxy_port + + # Private Active / Active Scenario + distribution = "rhel" + load_balancer_public = false + load_balancer_type = "application_gateway" + load_balancer_sku_name = "WAF_v2" + load_balancer_sku_tier = "WAF_v2" + load_balancer_waf_rule_set_version = var.is_replicated_deployment ? "3.1" : "3.2" + redis_use_password_auth = true + redis_use_tls = false + operational_mode = "external" + vm_image_id = "rhel" + vm_node_count = 2 + vm_sku = "Standard_D16as_v4" + + create_bastion = false + tags = local.common_tags + + # FDO Specific Values + is_replicated_deployment = var.is_replicated_deployment + hc_license = var.hc_license + http_port = 8080 + https_port = 8443 + license_reporting_opt_out = true + registry = local.registry + registry_password = var.registry_password + registry_username = var.registry_username + tfe_image = "${local.registry}/hashicorp/terraform-enterprise:${var.tfe_image_tag}" +} diff --git a/tests/private-active-active/outputs.tf b/tests/private-active-active/outputs.tf new file mode 100644 index 00000000..46738788 --- /dev/null +++ b/tests/private-active-active/outputs.tf @@ -0,0 +1,35 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +output "private_active_active" { + value = module.private_active_active + description = "The outputs of the private_active_active module." + + # This output is marked as sensitive to work around a bug in Terraform 0.14 + sensitive = true +} + +output "tfe_url" { + value = module.private_active_active.tfe_application_url + description = "The URL to the TFE application." +} + +output "health_check_url" { + value = "${module.private_active_active.tfe_application_url}/_health_check" + description = "The URL with path to access the TFE instance health check." +} + +output "iact_url" { + value = "${module.private_active_active.tfe_application_url}/admin/retrieve-iact" + description = "The URL with path to access the TFE instance Retrieve IACT" +} + +output "initial_admin_user_url" { + value = "${module.private_active_active.tfe_application_url}/admin/initial-admin-user" + description = "The URL with path to access the TFE instance Initial Admin User" +} + +output "bastion_fqdn" { + value = module.bastion_vm.fqdn + description = "The fully qualified domain name of the basion host virtual machine" +} diff --git a/tests/private-active-active/run-tests.sh b/tests/private-active-active/run-tests.sh new file mode 100755 index 00000000..019a74bf --- /dev/null +++ b/tests/private-active-active/run-tests.sh @@ -0,0 +1,156 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + + +k6_path="" +k6_tests_dir="" +bastion_key_file="" +skip_init="" +bind_to_localhost="" + +Help() +{ + # Display Help + echo "This script bootstraps the k6 / tfe-load-test environment and executes a smoke-test against an active TFE instance deployed with the terraform-azure-terraform-enterprise module." + echo + echo "Syntax: run-tests.sh [-h|k|t|b|s|l]" + echo "options:" + echo "h Print this Help." + echo "k (required) The path to the k6 binary." + echo "t (required) The path to the tfe-load-test repository." + echo "b (required) The path to the bastion server ssh private key." + echo "s (optional) Skip the admin user initialization and tfe token retrieval (This is useful for secondary / repeated test runs)." + echo "l (optional) Bind the test proxy to localhost instead of the detected ip address (This is useful when testing from within a docker container)." + echo +} + +# Get the options +while getopts ":hk:t:b:sl" option; do + case $option in + h) # display Help + Help + exit;; + k) # Enter a path to the k6 binary + k6_path=$OPTARG;; + + t) # Enter a path to the tfe-load-test repo + k6_tests_dir=$OPTARG;; + b) # Enter a path to the bastion server ssh private key + bastion_key_file=$OPTARG;; + s) # Skip the admin user boostrapping process? + skip_init=1;; + l) # Bind test proxy to localhost + bind_to_localhost=1;; + \?) # Invalid option + echo "Error: Invalid option" + exit;; + esac +done + +if [[ -z "$k6_path" ]]; then + echo "k6 path missing. Please use the -k option." + Help + exit 1 +fi + +if [[ -z "$k6_tests_dir" ]]; then + echo "The tfe-load-test repository path missing. Please use the -t option." + Help + exit 1 +fi + +if [[ -z "$bastion_key_file" ]]; then + echo "The bastion key file path is missing. Please use the -b option." + Help + exit 1 +fi + +echo " +Executing tests with the following configuration: + + k6_path=$k6_path + k6_tests_dir=$k6_tests_dir + bastion_key_file=$bastion_key_file + skip_init=$skip_init + bind_to_localhost=$bind_to_localhost +" + +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"; + +cd $SCRIPT_DIR +health_check_url=$(terraform output -no-color -raw health_check_url) +echo "health check url: $health_check_url" +bastion_fqdn=$(terraform output -no-color -raw bastion_fqdn) + +# Start socks proxy +echo "bastion fqdn: $bastion_fqdn" + +host_ip="" +if [[ -z "$bind_to_localhost" ]]; then + host_ip=$(hostname -I | xargs) +else + host_ip="localhost" +fi +echo "host interface is: $host_ip" + +socks_port=8082 +proxy=socks5://$host_ip:$socks_port +echo "proxy will be: $proxy" +ssh \ + -o 'BatchMode yes' \ + -o 'StrictHostKeyChecking accept-new' \ + -i $bastion_key_file \ + -f -N -p 22 -D $host_ip:$socks_port \ + -S /tmp/.private-active-active \ + bastionuser@"$bastion_fqdn" + +ssh_pid=$(pgrep -f 'ssh.*-f') +trap "{ kill $ssh_pid ; }" EXIT + +if [[ -z "$skip_init" ]]; then + # Execute Tests + echo "Curling \`health_check_url\` for a return status of 200..." + while ! curl -sfS --max-time 5 --proxy $proxy $health_check_url; \ + do sleep 5; done + echo " : TFE is healthy and listening." + + tfe_url=$(terraform output -no-color -raw tfe_url) + echo "tfe url: $tfe_url" + iact_url=$(terraform output -no-color -raw iact_url) + echo "iact url: $iact_url" + echo "Fetching iact token.." + iact_token=$(curl --fail --proxy $proxy "$iact_url") + + echo "iact token: $iact_token" + admin_url=$(terraform output -no-color -raw initial_admin_user_url) + TFE_USERNAME="test$(date +%s)" + TFE_PASSWORD=$(openssl rand -base64 32) + echo "{\"username\": \"$TFE_USERNAME\", \"email\": \"$TFE_USERNAME@example.com\", \"password\": \"$TFE_PASSWORD\"}" \ + > ./payload.json + response=$( \ + curl \ + --fail \ + --retry 5 \ + --header 'Content-Type: application/json' \ + --data @./payload.json \ + --proxy $proxy \ + "$admin_url"?token="$iact_token") + tfe_token=$(echo "$response" | jq --raw-output '.token') + rm -f payload.json + echo "tfe_token: $tfe_token" + + echo "export K6_PATHNAME=$k6_path + export TFE_URL=$tfe_url + export TFE_API_TOKEN=$tfe_token + export TFE_EMAIL=$TFE_USERNAME@example.com + export http_proxy=$proxy + export https_proxy=$proxy" > .env.sh + + echo "Sleeping for 3 minutes to ensure that both instances are ready." + sleep 180 +fi + +source .env.sh +cd $k6_tests_dir +make smoke-test diff --git a/tests/private-active-active/variables.tf b/tests/private-active-active/variables.tf new file mode 100644 index 00000000..65867c36 --- /dev/null +++ b/tests/private-active-active/variables.tf @@ -0,0 +1,89 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +variable "bastion_public_ssh_key_secret_name" { + type = string + description = "The name of the public SSH key secret for the bastion." +} + +variable "domain_name" { + type = string + description = "Domain to create Terraform Enterprise subdomain within" +} + +variable "hc_license" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The raw TFE license that is validated on application startup." +} + +variable "is_replicated_deployment" { + type = bool + description = "TFE will be installed using a Replicated license and deployment method." + default = true +} + +variable "load_balancer_certificate_name" { + type = string + description = "The name of a Key Vault certificate which will be attached to the application gateway." +} + +variable "location" { + type = string + description = "Azure location name e.g. East US" +} + +variable "key_vault_id" { + type = string + description = "The identity of the Key Vault which contains secrets and certificates." +} + +variable "network_allow_range" { + default = null + type = string + description = "Network range to allow access to bastion vm" +} + +variable "proxy_public_ssh_key_secret_name" { + type = string + description = "The name of the public SSH key secret for the proxy." +} + +variable "registry_password" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The password for the docker registry from which to source the terraform_enterprise container images." +} + +variable "registry_username" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The username for the docker registry from which to source the terraform_enterprise container images." +} + +variable "resource_group_name_dns" { + type = string + description = "Name of resource group which contains desired DNS zone" +} + +variable "tfe_image_tag" { + default = "latest" + type = string + description = "(Not needed if is_replicated_deployment is true) The image version of the terraform-enterprise image (e.g. \"1234567\")" +} + +variable "tfe_license_secret_name" { + default = null + type = string + description = "Name of the secret under which the Base64 encoded TFE license is stored in the Azure Key Vault" +} + +variable "vm_certificate_secret_name" { + type = string + description = "The name of a Key Vault secret which contains the Base64 encoded version of a PEM encoded public certificate of a certificate authority (CA) to be trusted by the Virtual Machine Scale Set." +} + +variable "vm_key_secret_name" { + type = string + description = "The name of a Key Vault secret which contains the Base64 encoded version of a PEM encoded private key of a certificate authority (CA) to be trusted by the Virtual Machine Scale Set." +} diff --git a/tests/private-active-active/versions.tf b/tests/private-active-active/versions.tf new file mode 100644 index 00000000..c9af2d5f --- /dev/null +++ b/tests/private-active-active/versions.tf @@ -0,0 +1,29 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +terraform { + backend "remote" { + organization = "terraform-enterprise-modules-test" + + workspaces { + name = "azure-private-active-active" + } + } + + required_version = "~> 1.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.2" + } + random = { + source = "hashicorp/random" + version = "~> 3.1" + } + } +} + +provider "azurerm" { + features {} +} diff --git a/tests/private-tcp-active-active/README.md b/tests/private-tcp-active-active/README.md new file mode 100644 index 00000000..678756b4 --- /dev/null +++ b/tests/private-tcp-active-active/README.md @@ -0,0 +1,42 @@ +# TEST: Private TCP Active/Active Terraform Enterprise + +## About this test + +This test for Terraform Enterprise creates a TFE +installation with the following traits. + +- Active/Active mode +- Large instance size (32 vCPUs) +- RHEL as the operating system +- SELinux enabled +- An internally exposed network +- MITM proxy +- TCP load balancer +- End to end TLS +- External PostgreSQL +- External Redis +- Redis authentication enabled +- Redis encryption in transit +- Redis encryption at rest + +## Pre-requisites + +This test assumes the following resources exist. + +- a DNS zone +- an Azure Key Vault in which the following are stored: + - TFE CA certificate pem (secret) + - TFE CA certificate key (secret) + - proxy CA certificate key (secret) + - proxy CA certificate private key (secret) + - proxy SSH public key (secret) + - proxy SSH private key (secret) + - bastion SSH public key (secret) + - bastion SSH private key (secret) + - base64 encoded TFE license (secret) + +## How this test is used + +This test is leveraged by this repository's continuous integration setup which +leverages workspaces in a Terraform Cloud workspaces as a remote backend so that +Terraform state is preserved. \ No newline at end of file diff --git a/tests/private-tcp-active-active/data.tf b/tests/private-tcp-active-active/data.tf new file mode 100644 index 00000000..39f5a1f7 --- /dev/null +++ b/tests/private-tcp-active-active/data.tf @@ -0,0 +1,39 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +data "azurerm_key_vault_secret" "vm_certificate" { + name = var.vm_certificate_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "vm_key" { + name = var.vm_key_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "ca_certificate" { + name = var.ca_certificate_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "ca_key" { + name = var.ca_key_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "tfe_license" { + count = var.tfe_license_secret_name == null ? 0 : 1 + + name = var.tfe_license_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "bastion_public_ssh_key" { + name = var.bastion_public_ssh_key_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "proxy_public_ssh_key" { + name = var.proxy_public_ssh_key_secret_name + key_vault_id = var.key_vault_id +} diff --git a/tests/private-tcp-active-active/locals.tf b/tests/private-tcp-active-active/locals.tf new file mode 100644 index 00000000..1fac9c2f --- /dev/null +++ b/tests/private-tcp-active-active/locals.tf @@ -0,0 +1,19 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +locals { + common_tags = { + Environment = "${local.friendly_name_prefix}-test-private-tcp-active-active" + Description = "Private TCP Active/Active" + Repository = "hashicorp/terraform-azurerm-terraform-enterprise" + Team = "Terraform Enterprise" + OkToDelete = "True" + } + + friendly_name_prefix = random_string.friendly_name.id + network_proxy_subnet_cidr = "10.0.80.0/20" + proxy_user = "proxyuser" + proxy_port = "3128" + registry = "quay.io" + resource_group_name = module.private_tcp_active_active.resource_group_name +} diff --git a/tests/private-tcp-active-active/main.tf b/tests/private-tcp-active-active/main.tf new file mode 100644 index 00000000..8e509cb2 --- /dev/null +++ b/tests/private-tcp-active-active/main.tf @@ -0,0 +1,93 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "random_string" "friendly_name" { + length = 4 + upper = false + numeric = false + special = false +} + +module "bastion_vm" { + source = "../../fixtures/bastion_vm" + friendly_name_prefix = local.friendly_name_prefix + + location = var.location + resource_group_name = local.resource_group_name + virtual_network_name = module.private_tcp_active_active.network.network.name + network_allow_range = var.network_allow_range + bastion_subnet_cidr = "10.0.16.0/20" + ssh_public_key = data.azurerm_key_vault_secret.bastion_public_ssh_key.value + bastion_user = "bastionuser" + + tags = local.common_tags +} + +module "test_proxy" { + source = "../../fixtures/test_proxy" + friendly_name_prefix = local.friendly_name_prefix + + location = var.location + resource_group_name = local.resource_group_name + virtual_network_name = module.private_tcp_active_active.network.network.name + proxy_subnet_cidr = local.network_proxy_subnet_cidr + proxy_user = local.proxy_user + proxy_public_ssh_key_secret_name = data.azurerm_key_vault_secret.proxy_public_ssh_key.value + key_vault_id = var.key_vault_id + mitmproxy_ca_certificate_secret = data.azurerm_key_vault_secret.ca_certificate.id + mitmproxy_ca_private_key_secret = data.azurerm_key_vault_secret.ca_key.id + + tags = local.common_tags + +} + +module "private_tcp_active_active" { + source = "../../" + + location = var.location + friendly_name_prefix = local.friendly_name_prefix + + resource_group_name_dns = var.resource_group_name_dns + domain_name = var.domain_name + iact_subnet_list = ["${module.bastion_vm.private_ip}/32"] + + # Bootstrapping resources + bypass_preflight_checks = true + tfe_license_secret_id = var.tfe_license_secret_name == null ? var.tfe_license_secret_name : data.azurerm_key_vault_secret.tfe_license[0].id + vm_certificate_secret = data.azurerm_key_vault_secret.vm_certificate + vm_key_secret = data.azurerm_key_vault_secret.vm_key + tls_bootstrap_cert_pathname = "/var/lib/terraform-enterprise/certificate.pem" + tls_bootstrap_key_pathname = "/var/lib/terraform-enterprise/key.pem" + + # Behind proxy information + ca_certificate_secret = data.azurerm_key_vault_secret.ca_certificate + proxy_ip = module.test_proxy.private_ip + proxy_port = local.proxy_port + + # Private Active / Active Scenario + distribution = "rhel" + load_balancer_public = false + load_balancer_type = "load_balancer" + redis_use_password_auth = true + redis_use_tls = true + redis_rdb_backup_enabled = true + redis_rdb_backup_frequency = 60 + operational_mode = "external" + vm_node_count = 2 + vm_sku = "Standard_D32a_v4" + vm_image_id = "rhel" + + create_bastion = false + tags = local.common_tags + + # FDO Specific Values + is_replicated_deployment = var.is_replicated_deployment + hc_license = var.hc_license + http_port = 8080 + https_port = 8443 + license_reporting_opt_out = true + registry = local.registry + registry_password = var.registry_password + registry_username = var.registry_username + tfe_image = "${local.registry}/hashicorp/terraform-enterprise:${var.tfe_image_tag}" +} diff --git a/tests/private-tcp-active-active/outputs.tf b/tests/private-tcp-active-active/outputs.tf new file mode 100644 index 00000000..ff3376c7 --- /dev/null +++ b/tests/private-tcp-active-active/outputs.tf @@ -0,0 +1,35 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +output "private_tcp_active_active" { + value = module.private_tcp_active_active + description = "The outputs of the private_tcp_active_active module" + + # This output is marked as sensitive to work around a bug in Terraform 0.14 + sensitive = true +} + +output "tfe_url" { + value = module.private_tcp_active_active.tfe_application_url + description = "The URL to the TFE application" +} + +output "health_check_url" { + value = "${module.private_tcp_active_active.tfe_application_url}/_health_check" + description = "The URL with path to access the TFE instance health check" +} + +output "iact_url" { + value = "${module.private_tcp_active_active.tfe_application_url}/admin/retrieve-iact" + description = "The URL with path to access the TFE instance Retrieve IACT" +} + +output "initial_admin_user_url" { + value = "${module.private_tcp_active_active.tfe_application_url}/admin/initial-admin-user" + description = "The URL with path to access the TFE instance Initial Admin User" +} + +output "bastion_fqdn" { + value = module.bastion_vm.fqdn + description = "The fully qualified domain name of the basion host virtual machine" +} diff --git a/tests/private-tcp-active-active/run-tests.sh b/tests/private-tcp-active-active/run-tests.sh new file mode 100755 index 00000000..ce925305 --- /dev/null +++ b/tests/private-tcp-active-active/run-tests.sh @@ -0,0 +1,156 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + + +k6_path="" +k6_tests_dir="" +bastion_key_file="" +skip_init="" +bind_to_localhost="" + +Help() +{ + # Display Help + echo "This script bootstraps the k6 / tfe-load-test environment and executes a smoke-test against an active TFE instance deployed with the terraform-azure-terraform-enterprise module." + echo + echo "Syntax: run-tests.sh [-h|k|t|b|s|l]" + echo "options:" + echo "h Print this Help." + echo "k (required) The path to the k6 binary." + echo "t (required) The path to the tfe-load-test repository." + echo "b (required) The path to the bastion server ssh private key." + echo "s (optional) Skip the admin user initialization and tfe token retrieval (This is useful for secondary / repeated test runs)." + echo "l (optional) Bind the test proxy to localhost instead of the detected ip address (This is useful when testing from within a docker container)." + echo +} + +# Get the options +while getopts ":hk:t:b:sl" option; do + case $option in + h) # display Help + Help + exit;; + k) # Enter a path to the k6 binary + k6_path=$OPTARG;; + + t) # Enter a path to the tfe-load-test repo + k6_tests_dir=$OPTARG;; + b) # Enter a path to the bastion server ssh private key + bastion_key_file=$OPTARG;; + s) # Skip the admin user boostrapping process? + skip_init=1;; + l) # Bind test proxy to localhost + bind_to_localhost=1;; + \?) # Invalid option + echo "Error: Invalid option" + exit;; + esac +done + +if [[ -z "$k6_path" ]]; then + echo "k6 path missing. Please use the -k option." + Help + exit 1 +fi + +if [[ -z "$k6_tests_dir" ]]; then + echo "The tfe-load-test repository path missing. Please use the -t option." + Help + exit 1 +fi + +if [[ -z "$bastion_key_file" ]]; then + echo "The bastion key file path is missing. Please use the -b option." + Help + exit 1 +fi + +echo " +Executing tests with the following configuration: + + k6_path=$k6_path + k6_tests_dir=$k6_tests_dir + bastion_key_file=$bastion_key_file + skip_init=$skip_init + bind_to_localhost=$bind_to_localhost +" + +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"; + +cd $SCRIPT_DIR +health_check_url=$(terraform output -no-color -raw health_check_url) +echo "health check url: $health_check_url" +bastion_fqdn=$(terraform output -no-color -raw bastion_fqdn) + +# Start socks proxy +echo "bastion fqdn: $bastion_fqdn" + +host_ip="" +if [[ -z "$bind_to_localhost" ]]; then + host_ip=$(hostname -I | xargs) +else + host_ip="localhost" +fi +echo "host interface is: $host_ip" + +socks_port=8083 +proxy=socks5://$host_ip:$socks_port +echo "proxy will be: $proxy" +ssh \ + -o 'BatchMode yes' \ + -o 'StrictHostKeyChecking accept-new' \ + -i $bastion_key_file \ + -f -N -p 22 -D $host_ip:$socks_port \ + -S /tmp/.private-tcp-active-active \ + bastionuser@"$bastion_fqdn" + +ssh_pid=$(pgrep -f 'ssh.*-f') +trap "{ kill $ssh_pid ; }" EXIT + +if [[ -z "$skip_init" ]]; then + # Execute Tests + echo "Curling \`health_check_url\` for a return status of 200..." + while ! curl -sfS --max-time 5 --proxy $proxy $health_check_url; \ + do sleep 5; done + echo " : TFE is healthy and listening." + + tfe_url=$(terraform output -no-color -raw tfe_url) + echo "tfe url: $tfe_url" + iact_url=$(terraform output -no-color -raw iact_url) + echo "iact url: $iact_url" + echo "Fetching iact token.." + iact_token=$(curl --fail --proxy $proxy "$iact_url") + + echo "iact token: $iact_token" + admin_url=$(terraform output -no-color -raw initial_admin_user_url) + TFE_USERNAME="test$(date +%s)" + TFE_PASSWORD=$(openssl rand -base64 32) + echo "{\"username\": \"$TFE_USERNAME\", \"email\": \"$TFE_USERNAME@example.com\", \"password\": \"$TFE_PASSWORD\"}" \ + > ./payload.json + response=$( \ + curl \ + --fail \ + --retry 5 \ + --header 'Content-Type: application/json' \ + --data @./payload.json \ + --proxy $proxy \ + "$admin_url"?token="$iact_token") + tfe_token=$(echo "$response" | jq --raw-output '.token') + rm -f payload.json + echo "tfe_token: $tfe_token" + + echo "export K6_PATHNAME=$k6_path + export TFE_URL=$tfe_url + export TFE_API_TOKEN=$tfe_token + export TFE_EMAIL=$TFE_USERNAME@example.com + export http_proxy=$proxy + export https_proxy=$proxy" > .env.sh + + echo "Sleeping for 3 minutes to ensure that both instances are ready." + sleep 180 +fi + +source .env.sh +cd $k6_tests_dir +make smoke-test diff --git a/tests/private-tcp-active-active/variables.tf b/tests/private-tcp-active-active/variables.tf new file mode 100644 index 00000000..4f2acc57 --- /dev/null +++ b/tests/private-tcp-active-active/variables.tf @@ -0,0 +1,94 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +variable "bastion_public_ssh_key_secret_name" { + type = string + description = "The name of the public SSH key secret for the bastion." +} + +variable "ca_certificate_secret_name" { + type = string + description = "The name of a Key Vault secret which contains the Base64 encoded version of a PEM encoded public certificate of a certificate authority (CA) to be trusted by the Virtual Machine Scale Set." +} + +variable "ca_key_secret_name" { + type = string + description = "The name of a Key Vault secret which contains the Base64 encoded version of a PEM encoded private key of a certificate authority (CA)." +} + +variable "domain_name" { + type = string + description = "Domain to create Terraform Enterprise subdomain within" +} + +variable "hc_license" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The raw TFE license that is validated on application startup." +} + +variable "is_replicated_deployment" { + type = bool + description = "TFE will be installed using a Replicated license and deployment method." + default = true +} + +variable "location" { + type = string + description = "Azure location name e.g. East US" +} + +variable "key_vault_id" { + type = string + description = "The identity of the Key Vault which contains secrets and certificates." +} + +variable "network_allow_range" { + default = null + type = string + description = "Network range to allow access to bastion vm" +} + +variable "proxy_public_ssh_key_secret_name" { + type = string + description = "The name of the public SSH key secret for the proxy." +} + +variable "registry_password" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The password for the docker registry from which to source the terraform_enterprise container images." +} + +variable "registry_username" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The username for the docker registry from which to source the terraform_enterprise container images." +} + +variable "resource_group_name_dns" { + type = string + description = "Name of resource group which contains desired DNS zone" +} + +variable "tfe_image_tag" { + default = "latest" + type = string + description = "(Not needed if is_replicated_deployment is true) The image version of the terraform-enterprise image (e.g. \"1234567\")" +} + +variable "tfe_license_secret_name" { + default = null + type = string + description = "Name of the secret under which the Base64 encoded TFE license is stored in the Azure Key Vault" +} + +variable "vm_certificate_secret_name" { + type = string + description = "The name of a Key Vault secret which contains the Base64 encoded version of a PEM encoded public certificate of a certificate authority (CA) to be trusted by the Virtual Machine Scale Set." +} + +variable "vm_key_secret_name" { + type = string + description = "The name of a Key Vault secret which contains the Base64 encoded version of a PEM encoded private key of a certificate authority (CA) to be trusted by the Virtual Machine Scale Set." +} diff --git a/tests/private-tcp-active-active/versions.tf b/tests/private-tcp-active-active/versions.tf new file mode 100644 index 00000000..a0d61ab3 --- /dev/null +++ b/tests/private-tcp-active-active/versions.tf @@ -0,0 +1,27 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +terraform { + backend "remote" { + organization = "terraform-enterprise-modules-test" + + workspaces { + name = "azure-private-tcp-active-active" + } + } + + required_version = "~> 1.0" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.2" + } + random = { + source = "hashicorp/random" + version = "~> 3.1" + } + } +} +provider "azurerm" { + features {} +} diff --git a/tests/public-active-active/README.md b/tests/public-active-active/README.md new file mode 100644 index 00000000..61fcbf2b --- /dev/null +++ b/tests/public-active-active/README.md @@ -0,0 +1,29 @@ +# TEST: Public Active/Active Terraform Enterprise + +## About this test + +This test for Terraform Enterprise creates a TFE +installation with the following traits. + +- Active/Active mode +- a small VM machine type (Standard_D4_v3) +- Ubuntu 20.04 as the VM image +- a publicly accessible HTTP load balancer with TLS termination +- no proxy server +- no Redis authentication +- no Redis encryption in transit + +## Pre-requisites + +This test assumes the following resources exist. + +- a DNS zone +- an Azure Key Vault in which the following are stored: + - Base64 encoded TFE license (secret) + - TFE CA certificate (certificate) + +## How this test is used + +This test is leveraged by this repository's continuous integration setup which +leverages workspaces in a Terraform Cloud workspaces as a remote backend so that +Terraform state is preserved. diff --git a/tests/public-active-active/data.tf b/tests/public-active-active/data.tf new file mode 100644 index 00000000..0b366133 --- /dev/null +++ b/tests/public-active-active/data.tf @@ -0,0 +1,24 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +data "azurerm_key_vault_certificate" "load_balancer" { + name = var.load_balancer_certificate_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "vm_certificate" { + name = var.vm_certificate_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "vm_key" { + name = var.vm_key_secret_name + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "tfe_license" { + count = var.tfe_license_secret_name == null ? 0 : 1 + + name = var.tfe_license_secret_name + key_vault_id = var.key_vault_id +} diff --git a/tests/public-active-active/locals.tf b/tests/public-active-active/locals.tf new file mode 100644 index 00000000..adf37d27 --- /dev/null +++ b/tests/public-active-active/locals.tf @@ -0,0 +1,15 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +locals { + common_tags = { + Environment = "${local.friendly_name_prefix}-test-public-active-active" + Description = "Public Active/Active" + Repository = "hashicorp/terraform-azurerm-terraform-enterprise" + Team = "Terraform Enterprise" + OkToDelete = "True" + } + + friendly_name_prefix = random_string.friendly_name.id + registry = "quay.io" +} diff --git a/tests/public-active-active/main.tf b/tests/public-active-active/main.tf new file mode 100644 index 00000000..69f3c2a6 --- /dev/null +++ b/tests/public-active-active/main.tf @@ -0,0 +1,51 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "random_string" "friendly_name" { + length = 4 + upper = false + numeric = false + special = false +} + +module "public_active_active" { + source = "../../" + + domain_name = var.domain_name + friendly_name_prefix = local.friendly_name_prefix + location = var.location + resource_group_name_dns = var.resource_group_name_dns + + # Bootstrapping resources + load_balancer_certificate = data.azurerm_key_vault_certificate.load_balancer + tfe_license_secret_id = var.tfe_license_secret_name == null ? var.tfe_license_secret_name : data.azurerm_key_vault_secret.tfe_license[0].id + vm_certificate_secret = data.azurerm_key_vault_secret.vm_certificate + vm_key_secret = data.azurerm_key_vault_secret.vm_key + tls_bootstrap_cert_pathname = "/var/lib/terraform-enterprise/certificate.pem" + tls_bootstrap_key_pathname = "/var/lib/terraform-enterprise/key.pem" + + # Public Active / Active Scenario + distribution = "ubuntu" + iact_subnet_list = var.iact_subnet_list + load_balancer_public = true + load_balancer_type = "application_gateway" + operational_mode = "external" + redis_use_password_auth = false + redis_use_tls = false + vm_node_count = 2 + vm_sku = "Standard_D4_v3" + vm_image_id = "ubuntu" + + tags = local.common_tags + + # FDO Specific Values + is_replicated_deployment = var.is_replicated_deployment + hc_license = var.hc_license + http_port = 8080 + https_port = 8443 + license_reporting_opt_out = true + registry = local.registry + registry_password = var.registry_password + registry_username = var.registry_username + tfe_image = "${local.registry}/hashicorp/terraform-enterprise:${var.tfe_image_tag}" +} diff --git a/tests/public-active-active/outputs.tf b/tests/public-active-active/outputs.tf new file mode 100644 index 00000000..2cb34943 --- /dev/null +++ b/tests/public-active-active/outputs.tf @@ -0,0 +1,30 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +output "public_active_active" { + value = module.public_active_active + description = "The outputs of the public_active_active module" + + # This output is marked as sensitive to work around a bug in Terraform 0.14 + sensitive = true +} + +output "tfe_url" { + value = module.public_active_active.tfe_application_url + description = "The URL to the TFE application" +} + +output "health_check_url" { + value = "${module.public_active_active.tfe_application_url}/_health_check" + description = "The URL with path to access the TFE instance health check" +} + +output "iact_url" { + value = "${module.public_active_active.tfe_application_url}/admin/retrieve-iact" + description = "The URL with path to access the TFE instance Retrieve IACT" +} + +output "initial_admin_user_url" { + value = "${module.public_active_active.tfe_application_url}/admin/initial-admin-user" + description = "The URL with path to access the TFE instance Initial Admin User" +} diff --git a/tests/public-active-active/run-tests.sh b/tests/public-active-active/run-tests.sh new file mode 100755 index 00000000..7518f2a4 --- /dev/null +++ b/tests/public-active-active/run-tests.sh @@ -0,0 +1,115 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + + +k6_path="" +k6_tests_dir="" +bastion_key_file="" +skip_init="" +bind_to_localhost="" + +Help() +{ + # Display Help + echo "This script bootstraps the k6 / tfe-load-test environment and executes a smoke-test against an active TFE instance deployed with the terraform-azure-terraform-enterprise module." + echo + echo "Syntax: run-tests.sh [-h|k|t|s]" + echo "options:" + echo "h Print this Help." + echo "k (required) The path to the k6 binary." + echo "t (required) The path to the tfe-load-test repository." + echo "s (optional) Skip the admin user initialization and tfe token retrieval (This is useful for secondary / repeated test runs)." + echo +} + +# Get the options +while getopts ":hk:t:b:sl" option; do + case $option in + h) # display Help + Help + exit;; + k) # Enter a path to the k6 binary + k6_path=$OPTARG;; + t) # Enter a path to the tfe-load-test repo + k6_tests_dir=$OPTARG;; + s) # Skip the admin user boostrapping process? + skip_init=1;; + \?) # Invalid option + echo "Error: Invalid option" + exit;; + esac +done + +if [[ -z "$k6_path" ]]; then + echo "k6 path missing. Please use the -k option." + Help + exit 1 +fi + +if [[ -z "$k6_tests_dir" ]]; then + echo "The tfe-load-test repository path missing. Please use the -t option." + Help + exit 1 +fi + +echo " +Executing tests with the following configuration: + + k6_path=$k6_path + k6_tests_dir=$k6_tests_dir + skip_init=$skip_init +" + +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"; + +cd $SCRIPT_DIR + +if [[ -z "$skip_init" ]]; then + health_check_url=$(terraform output -no-color -raw health_check_url) + echo "health check url: $health_check_url" + + echo "Curling \`health_check_url\` for a return status of 200..." + while ! curl -sfS --max-time 5 $health_check_url; \ + do sleep 5; done + echo " : TFE is healthy and listening." + + tfe_url=$(terraform output -no-color -raw tfe_url) + echo "tfe url: $tfe_url" + + iact_url=$(terraform output -no-color -raw iact_url) + echo "iact url: $iact_url" + + echo "Fetching iact token.." + iact_token=$(curl --fail "$iact_url") + + echo "iact token: $iact_token" + admin_url=$(terraform output -no-color -raw initial_admin_user_url) + TFE_USERNAME="test$(date +%s)" + TFE_PASSWORD=$(openssl rand -base64 32) + echo "{\"username\": \"$TFE_USERNAME\", \"email\": \"$TFE_USERNAME@example.com\", \"password\": \"$TFE_PASSWORD\"}" \ + > ./payload.json + + response=$( \ + curl \ + --fail \ + --retry 5 \ + --header 'Content-Type: application/json' \ + --data @./payload.json \ + "$admin_url"?token="$iact_token") + tfe_token=$(echo "$response" | jq --raw-output '.token') + rm -f payload.json + echo "tfe_token: $tfe_token" + + echo "export K6_PATHNAME=$k6_path + export TFE_URL=$tfe_url + export TFE_API_TOKEN=$tfe_token + export TFE_EMAIL=$TFE_USERNAME@example.com" > .env.sh + + echo "Sleeping for 3 minutes to ensure that both instances are ready." + sleep 180 +fi + +source .env.sh +cd $k6_tests_dir +make smoke-test diff --git a/tests/public-active-active/variables.tf b/tests/public-active-active/variables.tf new file mode 100644 index 00000000..112709ea --- /dev/null +++ b/tests/public-active-active/variables.tf @@ -0,0 +1,79 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +variable "domain_name" { + type = string + description = "Domain to create Terraform Enterprise subdomain within" +} + +variable "hc_license" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The raw TFE license that is validated on application startup." +} + +variable "iact_subnet_list" { + default = [] + description = "A list of IP address ranges which will be authorized to access the IACT. The ranges must be expressed in CIDR notation." + type = list(string) +} + +variable "is_replicated_deployment" { + type = bool + description = "TFE will be installed using a Replicated license and deployment method." + default = true +} + +variable "location" { + type = string + description = "Azure location name e.g. East US" +} + +variable "load_balancer_certificate_name" { + type = string + description = "The name of a Key Vault certificate which will be attached to the application gateway." +} + +variable "key_vault_id" { + type = string + description = "The identity of the Key Vault which contains secrets and certificates." +} + +variable "registry_password" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The password for the docker registry from which to source the terraform_enterprise container images." +} + +variable "registry_username" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The username for the docker registry from which to source the terraform_enterprise container images." +} + +variable "resource_group_name_dns" { + type = string + description = "Name of resource group which contains desired DNS zone" +} + +variable "tfe_image_tag" { + default = "latest" + type = string + description = "(Not needed if is_replicated_deployment is true) The image version of the terraform-enterprise image (e.g. \"1234567\")" +} + +variable "tfe_license_secret_name" { + default = null + type = string + description = "Name of the secret under which the Base64 encoded TFE license is stored in the Azure Key Vault" +} + +variable "vm_certificate_secret_name" { + type = string + description = "The name of a Key Vault secret which contains the Base64 encoded version of a PEM encoded public certificate of a certificate authority (CA) to be trusted by the Virtual Machine Scale Set." +} + +variable "vm_key_secret_name" { + type = string + description = "The name of a Key Vault secret which contains the Base64 encoded version of a PEM encoded private key of a certificate authority (CA) to be trusted by the Virtual Machine Scale Set." +} diff --git a/tests/public-active-active/versions.tf b/tests/public-active-active/versions.tf new file mode 100644 index 00000000..c6b9401e --- /dev/null +++ b/tests/public-active-active/versions.tf @@ -0,0 +1,27 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +terraform { + backend "remote" { + organization = "terraform-enterprise-modules-test" + + workspaces { + name = "azure-public-active-active" + } + } + + required_version = "~> 1.0" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.2" + } + random = { + source = "hashicorp/random" + version = "~> 3.1" + } + } +} +provider "azurerm" { + features {} +} diff --git a/tests/standalone-external/README.md b/tests/standalone-external/README.md new file mode 100644 index 00000000..3093e5fe --- /dev/null +++ b/tests/standalone-external/README.md @@ -0,0 +1,33 @@ +# TEST: Standalone External Services Terraform Enterprise + +## About this test + +This test for Terraform Enterprise creates a TFE +installation with the following traits. + +- Standalone +- Production mode +- a small VM machine type (Standard_D4_v3) +- Ubuntu 20.04 as the VM image +- a publicly accessible HTTP load balancer with TLS termination +- no proxy server +- External PostgreSQL +- External Redis + - no Redis authentication + - no Redis encryption in transit +- Storage account + +## Pre-requisites + +This test assumes the following resources exist. + +- a DNS zone +- an Azure Key Vault in which the following are stored: + - Base64 encoded TFE license (secret) + - TFE CA certificate (certificate) +- TFE license on a filepath accessible by tests + +## How this test is used + +This test is leveraged by the integration tests in the [`ptfe-replicated`](https://github.com/hashicorp/ptfe-replicated/blob/master/.circleci/config.yml) +repository. diff --git a/tests/standalone-external/data.tf b/tests/standalone-external/data.tf new file mode 100644 index 00000000..f6e3b347 --- /dev/null +++ b/tests/standalone-external/data.tf @@ -0,0 +1,17 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +data "azurerm_key_vault_certificate" "load_balancer" { + name = "wildcard" + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "vm_certificate" { + name = "wildcard-chained-certificate-pem" + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "vm_key" { + name = "wildcard-private-key-pem" + key_vault_id = var.key_vault_id +} diff --git a/tests/standalone-external/locals.tf b/tests/standalone-external/locals.tf new file mode 100644 index 00000000..7a92e3ad --- /dev/null +++ b/tests/standalone-external/locals.tf @@ -0,0 +1,16 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +locals { + common_tags = { + Environment = "${local.friendly_name_prefix}-test-standalone-external" + Description = "Standalone, External Services scenario" + Repository = "hashicorp/terraform-azurerm-terraform-enterprise" + Team = "Terraform Enterprise" + OkToDelete = "True" + } + + friendly_name_prefix = random_string.friendly_name.id + registry = "quay.io" + utility_module_test = var.license_file == null +} diff --git a/tests/standalone-external/main.tf b/tests/standalone-external/main.tf new file mode 100644 index 00000000..09c352b2 --- /dev/null +++ b/tests/standalone-external/main.tf @@ -0,0 +1,65 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "random_string" "friendly_name" { + length = 4 + upper = false + numeric = false + special = false +} + +module "secrets" { + count = local.utility_module_test || !var.is_replicated_deployment ? 0 : 1 + source = "../../fixtures/secrets" + key_vault_id = var.key_vault_id + + tfe_license = { + name = "tfe-license-${local.friendly_name_prefix}" + path = var.license_file + } +} + +module "standalone_external" { + source = "../../" + + domain_name = var.domain_name + friendly_name_prefix = local.friendly_name_prefix + location = "Central US" + resource_group_name_dns = var.resource_group_name_dns + + # Bootstrapping resources + load_balancer_certificate = data.azurerm_key_vault_certificate.load_balancer + tfe_license_secret_id = try(module.secrets[0].tfe_license_secret_id, var.tfe_license_secret_id) + vm_certificate_secret = data.azurerm_key_vault_secret.vm_certificate + vm_key_secret = data.azurerm_key_vault_secret.vm_key + tls_bootstrap_cert_pathname = "/var/lib/terraform-enterprise/certificate.pem" + tls_bootstrap_key_pathname = "/var/lib/terraform-enterprise/key.pem" + bypass_preflight_checks = var.bypass_preflight_checks + custom_agent_image_tag = "hashicorp/tfc-agent:latest" + + # Standalone External Scenario + distribution = "ubuntu" + database_version = var.database_version + iact_subnet_list = ["0.0.0.0/0"] + load_balancer_public = true + load_balancer_type = "load_balancer" + operational_mode = "external" + vm_node_count = 1 + vm_sku = "Standard_D4_v3" + vm_image_id = "ubuntu" + + enable_ssh = true + create_bastion = false + tags = local.common_tags + + # FDO Specific Values + is_replicated_deployment = var.is_replicated_deployment + hc_license = var.hc_license + http_port = 8080 + https_port = 8443 + license_reporting_opt_out = true + registry = local.registry + registry_password = var.registry_password + registry_username = var.registry_username + tfe_image = "${local.registry}/hashicorp/terraform-enterprise:${var.tfe_image_tag}" +} diff --git a/tests/standalone-external/outputs.tf b/tests/standalone-external/outputs.tf new file mode 100644 index 00000000..e31df0a6 --- /dev/null +++ b/tests/standalone-external/outputs.tf @@ -0,0 +1,34 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +output "replicated_console_password" { + value = module.standalone_external.tfe_console_password + description = "The password for the TFE console" +} + +output "replicated_console_url" { + value = module.standalone_external.tfe_console_url + description = "Terraform Enterprise Console URL" +} + +output "ptfe_endpoint" { + value = module.standalone_external.tfe_application_url + description = "Terraform Enterprise Application URL" +} + +output "ptfe_health_check" { + value = "${module.standalone_external.tfe_application_url}/_health_check" + description = "Terraform Enterprise Health Check URL" +} + +output "ssh_config_file" { + value = local_file.ssh_config.filename + + description = "The pathname of the SSH configuration file that grants access to the compute instance." +} + +output "ssh_private_key" { + value = local_file.private_key_pem.filename + + description = "The pathname of the private SSH key." +} diff --git a/tests/standalone-external/run-tests.sh b/tests/standalone-external/run-tests.sh new file mode 100755 index 00000000..81f8eaa0 --- /dev/null +++ b/tests/standalone-external/run-tests.sh @@ -0,0 +1,106 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + + +k6_path="" +k6_tests_dir="" +skip_init="" + +Help() +{ + # Display Help + echo "This script bootstraps the k6 / tfe-load-test environment and executes a smoke-test against an active TFE instance deployed with the terraform-azure-terraform-enterprise module." + echo + echo "Syntax: run-tests.sh [-h|k|t|s]" + echo "options:" + echo "h Print this Help." + echo "k (required) The path to the k6 binary." + echo "t (required) The path to the tfe-load-test repository." + echo "s (optional) Skip the admin user initialization and tfe token retrieval (This is useful for secondary / repeated test runs)." + echo +} + +# Get the options +while getopts ":hk:t:b:sl" option; do + case $option in + h) # display Help + Help + exit;; + k) # Enter a path to the k6 binary + k6_path=$OPTARG;; + + t) # Enter a path to the tfe-load-test repo + k6_tests_dir=$OPTARG;; + s) # Skip the admin user boostrapping process? + skip_init=1;; + \?) # Invalid option + echo "Error: Invalid option" + exit;; + esac +done + +if [[ -z "$k6_path" ]]; then + echo "k6 path missing. Please use the -k option." + Help + exit 1 +fi + +if [[ -z "$k6_tests_dir" ]]; then + echo "The tfe-load-test repository path missing. Please use the -t option." + Help + exit 1 +fi + + +echo " +Executing tests with the following configuration: + + k6_path=$k6_path + k6_tests_dir=$k6_tests_dir + skip_init=$skip_init +" + +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"; +if [[ -z "$skip_init" ]]; then + cd $SCRIPT_DIR + health_check_url=$(terraform output -no-color -raw ptfe_health_check) + echo "health check url: $health_check_url" + + # Execute Tests + echo "Curling \`health_check_url\` for a return status of 200..." + while ! curl -sfS --max-time 5 $health_check_url; \ + do sleep 5; done + echo " : TFE is healthy and listening." + + tfe_url=$(terraform output -no-color -raw ptfe_endpoint) + echo "tfe url: $tfe_url" + iact_url=$tfe_url/admin/retrieve-iact + echo "iact url: $iact_url" + echo "Fetching iact token.." + iact_token=$(curl --fail "$iact_url") + echo "iact token: $iact_token" + admin_url=$tfe_url/admin/initial-admin-user + TFE_USERNAME="test$(date +%s)" + TFE_PASSWORD=$(openssl rand -base64 32) + echo "{\"username\": \"$TFE_USERNAME\", \"email\": \"$TFE_USERNAME@example.com\", \"password\": \"$TFE_PASSWORD\"}" > ./payload.json + response=$( \ + curl \ + --fail \ + --retry 5 \ + --header 'Content-Type: application/json' \ + --data @./payload.json \ + "$admin_url"?token="$iact_token") + tfe_token=$(echo "$response" | jq --raw-output '.token') + rm -f ./payload.json + echo "tfe_token: $tfe_token" + + echo "export K6_PATHNAME=$k6_path + export TFE_URL=$tfe_url + export TFE_API_TOKEN=$tfe_token + export TFE_EMAIL=$TFE_USERNAME@example.com" > .env.sh +fi + +source .env.sh +cd $k6_tests_dir +make smoke-test diff --git a/tests/standalone-external/ssh.tf b/tests/standalone-external/ssh.tf new file mode 100644 index 00000000..d4332397 --- /dev/null +++ b/tests/standalone-external/ssh.tf @@ -0,0 +1,28 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +# Create files for SSH config. +resource "local_file" "private_key_pem" { + filename = "${path.module}/work/private-key.pem" + + content = module.standalone_external.instance_private_key + file_permission = "0600" +} + +resource "local_file" "ssh_config" { + filename = "${path.module}/work/ssh-config" + + content = <<__eof +Host default + Hostname ${module.standalone_external.fqdn} + User ${module.standalone_external.instance_user_name} + Port 22 + UserKnownHostsFile /dev/null + StrictHostKeyChecking no + PasswordAuthentication no + IdentityFile ${local_file.private_key_pem.filename} + IdentitiesOnly yes + LogLevel FATAL +__eof + +} \ No newline at end of file diff --git a/tests/standalone-external/variables.tf b/tests/standalone-external/variables.tf new file mode 100644 index 00000000..9912ca5a --- /dev/null +++ b/tests/standalone-external/variables.tf @@ -0,0 +1,73 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +variable "bypass_preflight_checks" { + default = true + type = bool + description = "Allow the TFE application to start without preflight checks." +} + +variable "database_version" { + default = 12 + type = number + description = "Postgres version" +} + +variable "domain_name" { + type = string + default = "team-private-terraform-enterprise.azure.ptfedev.com" + description = "Domain to create Terraform Enterprise subdomain within" +} + +variable "hc_license" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The raw TFE license that is validated on application startup." +} + +variable "is_replicated_deployment" { + type = bool + description = "TFE will be installed using a Replicated license and deployment method." + default = true +} + +variable "key_vault_id" { + type = string + description = "The identity of the Key Vault which contains secrets and certificates." +} + +variable "license_file" { + type = string + default = null + description = "The local path to the Terraform Enterprise license to be provided by CI." +} + +variable "registry_password" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The password for the docker registry from which to source the terraform_enterprise container images." +} + +variable "registry_username" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The username for the docker registry from which to source the terraform_enterprise container images." +} + +variable "resource_group_name_dns" { + type = string + default = "ptfedev-com-dns-tls" + description = "Name of resource group which contains desired DNS zone" +} + +variable "tfe_image_tag" { + default = "latest" + type = string + description = "(Not needed if is_replicated_deployment is true) The image version of the terraform-enterprise image (e.g. \"1234567\")" +} + +variable "tfe_license_secret_id" { + default = null + type = string + description = "The Key Vault secret id under which the Base64 encoded Terraform Enterprise license is stored." +} diff --git a/tests/standalone-external/versions.tf b/tests/standalone-external/versions.tf new file mode 100644 index 00000000..0f0286db --- /dev/null +++ b/tests/standalone-external/versions.tf @@ -0,0 +1,23 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +terraform { + required_version = "~> 1.0" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.2" + } + random = { + source = "hashicorp/random" + version = "~> 3.1" + } + local = { + source = "hashicorp/local" + version = "~> 2.2" + } + } +} +provider "azurerm" { + features {} +} diff --git a/tests/standalone-mounted-disk/README.md b/tests/standalone-mounted-disk/README.md new file mode 100644 index 00000000..1ce1a8d9 --- /dev/null +++ b/tests/standalone-mounted-disk/README.md @@ -0,0 +1,31 @@ +# TEST: Standalone Mounted Disk Mode Terraform Enterprise + +## About this test + +This test for Terraform Enterprise creates a TFE +installation with the following traits. + +- Standalone +- Mounted Disk mode +- a small VM machine type (Standard_D4_v3) +- Ubuntu 20.04 as the VM image +- a publicly accessible HTTP load balancer with TLS termination + +## Pre-requisites + +This test assumes the following resources exist. + +- a DNS zone +- an Azure Key Vault in which the following are stored: + - TFE CA certificate (certificate) + - Key Vault secret which contains the Base64 encoded version of a PEM encoded public + certificate for the Virtual Machine Scale Set + - Key Vault secret which contains the Base64 encoded version of a PEM encoded private + key for the Virtual Machine Scale Set. +- TFE license on a filepath accessible by tests + +These are the certificate and key for the VM, not for a CA, as the application gateway requires its backend to also have a trusted TLS certificate. +## How this test is used + +This test is leveraged by the integration tests in the [`ptfe-replicated`](https://github.com/hashicorp/ptfe-replicated/blob/master/.circleci/config.yml) +repository. diff --git a/tests/standalone-mounted-disk/data.tf b/tests/standalone-mounted-disk/data.tf new file mode 100644 index 00000000..f6e3b347 --- /dev/null +++ b/tests/standalone-mounted-disk/data.tf @@ -0,0 +1,17 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +data "azurerm_key_vault_certificate" "load_balancer" { + name = "wildcard" + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "vm_certificate" { + name = "wildcard-chained-certificate-pem" + key_vault_id = var.key_vault_id +} + +data "azurerm_key_vault_secret" "vm_key" { + name = "wildcard-private-key-pem" + key_vault_id = var.key_vault_id +} diff --git a/tests/standalone-mounted-disk/locals.tf b/tests/standalone-mounted-disk/locals.tf new file mode 100644 index 00000000..d6e7db6f --- /dev/null +++ b/tests/standalone-mounted-disk/locals.tf @@ -0,0 +1,46 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +locals { + common_tags = { + Environment = "${local.friendly_name_prefix}-test-standalone-mounted-disk" + Description = "Standalone, Mounted Disk scenario" + Repository = "hashicorp/terraform-azurerm-terraform-enterprise" + Team = "Terraform Enterprise" + OkToDelete = "True" + } + vm_image_id = ( + var.vm_image_publisher != null && + var.vm_image_offer != null && + var.vm_image_sku != null && + var.vm_image_version != null + ) ? "manual" : "ubuntu" + vm_image_publisher = ( + var.vm_image_publisher != null && + var.vm_image_offer != null && + var.vm_image_sku != null && + var.vm_image_version != null + ) ? var.vm_image_publisher : null + vm_image_offer = ( + var.vm_image_publisher != null && + var.vm_image_offer != null && + var.vm_image_sku != null && + var.vm_image_version != null + ) ? var.vm_image_offer : null + vm_image_sku = ( + var.vm_image_publisher != null && + var.vm_image_offer != null && + var.vm_image_sku != null && + var.vm_image_version != null + ) ? var.vm_image_sku : null + vm_image_version = ( + var.vm_image_publisher != null && + var.vm_image_offer != null && + var.vm_image_sku != null && + var.vm_image_version != null + ) ? var.vm_image_version : null + + friendly_name_prefix = random_string.friendly_name.id + registry = "quay.io" + utility_module_test = var.license_file == null +} diff --git a/tests/standalone-mounted-disk/main.tf b/tests/standalone-mounted-disk/main.tf new file mode 100644 index 00000000..ad1c84e0 --- /dev/null +++ b/tests/standalone-mounted-disk/main.tf @@ -0,0 +1,75 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "random_string" "friendly_name" { + length = 4 + upper = false + numeric = false + special = false +} + +module "secrets" { + source = "../../fixtures/secrets" + count = local.utility_module_test || !var.is_replicated_deployment ? 0 : 1 + key_vault_id = var.key_vault_id + + tfe_license = { + name = "tfe-license-${local.friendly_name_prefix}" + path = var.license_file + } +} + +module "standalone_mounted_disk" { + source = "../../" + + domain_name = var.domain_name + friendly_name_prefix = local.friendly_name_prefix + location = "Central US" + resource_group_name_dns = var.resource_group_name_dns + iact_subnet_list = ["0.0.0.0/0"] + + # Bootstrapping resources + load_balancer_certificate = data.azurerm_key_vault_certificate.load_balancer + tfe_license_secret_id = try(module.secrets[0].tfe_license_secret_id, var.tfe_license_secret_id) + vm_certificate_secret = data.azurerm_key_vault_secret.vm_certificate + vm_key_secret = data.azurerm_key_vault_secret.vm_key + tls_bootstrap_cert_pathname = "/var/lib/terraform-enterprise/certificate.pem" + tls_bootstrap_key_pathname = "/var/lib/terraform-enterprise/key.pem" + bypass_preflight_checks = var.bypass_preflight_checks + + # Standalone Mounted Disk Mode Scenario + distribution = var.distribution + operational_mode = "disk" + disk_path = "/opt/hashicorp/data" + load_balancer_public = true + load_balancer_type = "load_balancer" + vm_image_id = local.vm_image_id + vm_image_publisher = local.vm_image_publisher + vm_image_offer = local.vm_image_offer + vm_image_sku = local.vm_image_sku + vm_image_version = local.vm_image_version + vm_node_count = 1 + vm_sku = "Standard_D4_v3" + + # VM Data Disk + vm_data_disk_caching = "ReadWrite" + vm_data_disk_create_option = "Empty" + vm_data_disk_storage_account_type = "StandardSSD_LRS" + vm_data_disk_lun = 0 + vm_data_disk_disk_size_gb = 100 + + enable_ssh = true + create_bastion = false + tags = local.common_tags + + # FDO Specific Values + is_replicated_deployment = var.is_replicated_deployment + hc_license = var.hc_license + http_port = 8080 + https_port = 8443 + license_reporting_opt_out = true + registry = local.registry + registry_password = var.registry_password + registry_username = var.registry_username + tfe_image = "${local.registry}/hashicorp/terraform-enterprise:${var.tfe_image_tag}" +} diff --git a/tests/standalone-mounted-disk/outputs.tf b/tests/standalone-mounted-disk/outputs.tf new file mode 100644 index 00000000..359a15fe --- /dev/null +++ b/tests/standalone-mounted-disk/outputs.tf @@ -0,0 +1,35 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +output "replicated_console_password" { + value = module.standalone_mounted_disk.tfe_console_password + description = "The password for the TFE console" +} + +output "replicated_console_url" { + value = module.standalone_mounted_disk.tfe_console_url + description = "Terraform Enterprise Console URL" +} + +output "ptfe_endpoint" { + value = module.standalone_mounted_disk.tfe_application_url + description = "Terraform Enterprise Application URL" +} + +output "ptfe_health_check" { + value = "${module.standalone_mounted_disk.tfe_application_url}/_health_check" + description = "Terraform Enterprise Health Check URL" +} + +output "ssh_config_file" { + value = local_file.ssh_config.filename + + description = "The pathname of the SSH configuration file that grants access to the compute instance." +} + +output "ssh_private_key" { + value = local_file.private_key_pem.filename + + description = "The pathname of the private SSH key." +} + diff --git a/tests/standalone-mounted-disk/run-tests.sh b/tests/standalone-mounted-disk/run-tests.sh new file mode 100755 index 00000000..384d3671 --- /dev/null +++ b/tests/standalone-mounted-disk/run-tests.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + + +k6_path="" +k6_tests_dir="" +skip_init="" + +Help() +{ + # Display Help + echo "This script bootstraps the k6 / tfe-load-test environment and executes a smoke-test against an active TFE instance deployed with the terraform-azure-terraform-enterprise module." + echo + echo "Syntax: run-tests.sh [-h|k|t|s]" + echo "options:" + echo "h Print this Help." + echo "k (required) The path to the k6 binary." + echo "t (required) The path to the tfe-load-test repository." + echo "s (optional) Skip the admin user initialization and tfe token retrieval (This is useful for secondary / repeated test runs)." + echo +} + +# Get the options +while getopts ":hk:t:b:sl" option; do + case $option in + h) # display Help + Help + exit;; + k) # Enter a path to the k6 binary + k6_path=$OPTARG;; + + t) # Enter a path to the tfe-load-test repo + k6_tests_dir=$OPTARG;; + s) # Skip the admin user boostrapping process? + skip_init=1;; + \?) # Invalid option + echo "Error: Invalid option" + exit;; + esac +done + +if [[ -z "$k6_path" ]]; then + echo "k6 path missing. Please use the -k option." + Help + exit 1 +fi + +if [[ -z "$k6_tests_dir" ]]; then + echo "The tfe-load-test repository path missing. Please use the -t option." + Help + exit 1 +fi + + +echo " +Executing tests with the following configuration: + + k6_path=$k6_path + k6_tests_dir=$k6_tests_dir + skip_init=$skip_init +" + +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"; +if [[ -z "$skip_init" ]]; then + cd $SCRIPT_DIR + health_check_url=$(terraform output -no-color -raw ptfe_health_check) + echo "health check url: $health_check_url" + + # Execute Tests + echo "Curling \`health_check_url\` for a return status of 200..." + while ! curl -sfS --max-time 5 $health_check_url; \ + do sleep 5; done + echo " : TFE is healthy and listening." + + tfe_url=$(terraform output -no-color -raw ptfe_endpoint) + echo "tfe url: $tfe_url" + iact_url=$tfe_url/admin/retrieve-iact + echo "iact url: $iact_url" + echo "Fetching iact token.." + iact_token=$(curl --fail "$iact_url") + echo "iact token: $iact_token" + admin_url=$tfe_url/admin/initial-admin-user + TFE_USERNAME="test$(date +%s)" + TFE_PASSWORD=$(openssl rand -base64 32) + echo "{\"username\": \"$TFE_USERNAME\", \"email\": \"$TFE_USERNAME@example.com\", \"password\": \"$TFE_PASSWORD\"}" \ + > ./payload.json + response=$( \ + curl \ + --fail \ + --retry 5 \ + --header 'Content-Type: application/json' \ + --data @./payload.json \ + "$admin_url"?token="$iact_token") + tfe_token=$(echo "$response" | jq --raw-output '.token') + rm -f ./payload.json + echo "tfe_token: $tfe_token" + + echo "export K6_PATHNAME=$k6_path + export TFE_URL=$tfe_url + export TFE_API_TOKEN=$tfe_token + export TFE_EMAIL=$TFE_USERNAME@example.com" > .env.sh +fi + +source .env.sh +cd $k6_tests_dir +make smoke-test diff --git a/tests/standalone-mounted-disk/ssh.tf b/tests/standalone-mounted-disk/ssh.tf new file mode 100644 index 00000000..6cb1680c --- /dev/null +++ b/tests/standalone-mounted-disk/ssh.tf @@ -0,0 +1,29 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +# Create files for SSH config. +resource "local_file" "private_key_pem" { + filename = "${path.module}/work/private-key.pem" + + content = module.standalone_mounted_disk.instance_private_key + file_permission = "0600" +} + +resource "local_file" "ssh_config" { + filename = "${path.module}/work/ssh-config" + + content = <<__eof +Host default + Hostname ${module.standalone_mounted_disk.fqdn} + User ${module.standalone_mounted_disk.instance_user_name} + Port 22 + UserKnownHostsFile /dev/null + StrictHostKeyChecking no + PasswordAuthentication no + IdentityFile ${local_file.private_key_pem.filename} + IdentitiesOnly yes + LogLevel FATAL +__eof + +} + diff --git a/tests/standalone-mounted-disk/variables.tf b/tests/standalone-mounted-disk/variables.tf new file mode 100644 index 00000000..b160a658 --- /dev/null +++ b/tests/standalone-mounted-disk/variables.tf @@ -0,0 +1,102 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + + +variable "bypass_preflight_checks" { + default = true + type = bool + description = "Allow the TFE application to start without preflight checks." +} + +variable "distribution" { + type = string + description = "(Required) What is the OS distribution of the instance on which Terraoform Enterprise will be deployed?" + validation { + condition = contains(["rhel", "ubuntu"], var.distribution) + error_message = "Supported values for distribution are 'rhel' or 'ubuntu'." + } + default = "ubuntu" +} + +variable "domain_name" { + type = string + default = "team-private-terraform-enterprise.azure.ptfedev.com" + description = "Domain to create Terraform Enterprise subdomain within" +} + +variable "hc_license" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The raw TFE license that is validated on application startup." +} + +variable "is_replicated_deployment" { + type = bool + description = "TFE will be installed using a Replicated license and deployment method." + default = true +} + +variable "key_vault_id" { + type = string + description = "The identity of the Key Vault which contains secrets and certificates." +} + +variable "license_file" { + type = string + default = null + description = "The local path to the Terraform Enterprise license to be provided by CI." +} + +variable "registry_password" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The password for the docker registry from which to source the terraform_enterprise container images." +} + +variable "registry_username" { + default = null + type = string + description = "(Not needed if is_replicated_deployment is true) The username for the docker registry from which to source the terraform_enterprise container images." +} + +variable "resource_group_name_dns" { + type = string + default = "ptfedev-com-dns-tls" + description = "Name of resource group which contains desired DNS zone" +} + +variable "tfe_image_tag" { + default = "latest" + type = string + description = "(Not needed if is_replicated_deployment is true) The image version of the terraform-enterprise image (e.g. \"1234567\")" +} + +variable "tfe_license_secret_id" { + default = null + type = string + description = "The Key Vault secret id under which the Base64 encoded Terraform Enterprise license is stored." +} + +variable "vm_image_publisher" { + type = string + description = "The image publisher of the base image to install Terraform Enterprise on. This is used in conjunction with vm_image_offer, vm_image_sku, and vm_image_version to determine the image to install from the public markeplace when vm_image_id is not provided." + default = null +} + +variable "vm_image_offer" { + type = string + description = "The image offer of the base image to install Terraform Enterprise on. This is used in conjunction with vm_image_publisher, vm_image_sku, and vm_image_version to determine the image to install from the public markeplace when vm_image_id is not provided." + default = null +} + +variable "vm_image_sku" { + type = string + description = "The image sku of the base image to install Terraform Enterprise on. This is used in conjunction with vm_image_publisher, vm_image_offer, and vm_image_version to determine the image to install from the public markeplace when vm_image_id is not provided." + default = null +} + +variable "vm_image_version" { + type = string + description = "The image version of the base image to install Terraform Enterprise on. This is used in conjunction with vm_image_publisher, vm_image_offer, and vm_image_sku to determine the image to install from the public markeplace when vm_image_id is not provided." + default = null +} diff --git a/tests/standalone-mounted-disk/versions.tf b/tests/standalone-mounted-disk/versions.tf new file mode 100644 index 00000000..0f0286db --- /dev/null +++ b/tests/standalone-mounted-disk/versions.tf @@ -0,0 +1,23 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +terraform { + required_version = "~> 1.0" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.2" + } + random = { + source = "hashicorp/random" + version = "~> 3.1" + } + local = { + source = "hashicorp/local" + version = "~> 2.2" + } + } +} +provider "azurerm" { + features {} +}