Skip to content

Commit

Permalink
Ah/tf 5370 (hashicorp#118)
Browse files Browse the repository at this point in the history
* add docker config module and fdo deployment
* add common destroy workflow
* add reusable aws test workflow
  • Loading branch information
anniehedgpeth authored Sep 21, 2023
1 parent 9b16042 commit a529d5c
Show file tree
Hide file tree
Showing 36 changed files with 2,281 additions and 1,986 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/auto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
with:
terraform_version: 0.14.7
terraform_version: 1.1.5

- name: Format all .tf files recursively
run: |
Expand Down
360 changes: 360 additions & 0 deletions .github/workflows/aws-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,360 @@
name: AWS Test Harness

on:
workflow_call:
inputs:
# Configuration Flags #
test_name:
description: |-
The name for this test run. eg: 'Public Active/Active'
required: true
type: string
utility_test:
description: "Is this test run being executed from the utility repo?"
type: boolean
required: false
default: false
is_replicated_deployment:
description: "Is this test scenario using Replicated to deploy TFE?"
type: boolean
required: true
default: false
first_apply_args:
description: "Terraform arguments for the first apply operation."
required: false
type: string
default: ''

# Pull Request / Repo Identifiers #
module_repository_id:
description: |-
For utility module tests, what is the source module repo for this test?
eg: hashicorp/terraform-aws-terraform-enterprise
required: true
type: string
pull_request_repo_name:
description: |-
The name of the initiating pull request repo.
required: true
type: string
pull_request_ref:
description: |-
The ref of the pull request initiating this action. This is relevent
to both utility module changes and non-utility module changes.
required: true
type: string
pull_request_comment_id:
description: |-
The ref of the pull request comment initiating this action. This is
relevent to both utility module changes and non-utility module changes.
required: true
type: string

# General Job Configuration #
work_dir:
description: "The directory in which tests are executed"
required: true
type: string
k6_work_dir:
description: "The directory in which k6 is installed"
required: true
type: string

# TFC Workspace Configuration #
TFC_token_secret_name:
description: |-
The id of the github secret that contains the TFC token for the tfc
workspace for this test.
required: true
type: string

TFC_workspace_substitution_pattern:
description: |-
The sed supstitution pattern used to retarget this test to another TFC
workspace. This is used primarily in testing the utility modules.
eg: s/aws-public-active-active/utility-aws-public-active-active/
required: false
type: string
default: ""

# Target system SSH configuration #
ssh_private_key_secret_name:
description: |-
The github secret name for a Base64 encoded private certificate used
to authenticate into and proxy tests from the TFE instance.
required: false
default: ""
type: string

jobs:
execute_aws_tests:
name: Run tf-test on AWS infrastructure
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
env:
WORK_DIR_PATH: ${{ inputs.work_dir }}
K6_WORK_DIR_PATH: ${{ inputs.k6_work_dir }}
steps:
- name: Create URL to the run output
id: vars
run: echo ::set-output name=run-url::https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID

# Module Checkout
# If this is not a utility module test, check out the pull request under
# test in the module repo.
- name: Checkout
if: ${{ ! inputs.utility_test }}
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
repository: ${{ github.event.client_payload.pull_request.head.repo.full_name }}
ref: ${{ github.event.client_payload.pull_request.head.sha }}
token: ${{ secrets.GITHUB_TOKEN }}
persist-credentials: false

# If this is a utility test then checkout out the module source and patch
# the configuration to target the appropriate TFC workspace.
- name: Checkout
if: ${{ inputs.utility_test }}
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
repository: ${{inputs.module_repository_id}}

- name: Update Terraform Backend to TFC Workspace for Utility Module
working-directory: ${{ env.WORK_DIR_PATH }}
run: |
sed --in-place '${{ inputs.TFC_workspace_substitution_pattern }}' versions.tf
- name: Set Terraform Utility Module Sources
if: ${{ inputs.utility_test }}
working-directory: ${{ env.WORK_DIR_PATH }}
env:
SHA: ${{ inputs.pull_request_ref }}
run: |
sed --in-place "s/?ref=main/?ref=$SHA/" ../../main.tf
sed --in-place "s/?ref=main/?ref=$SHA/" ../../fixtures/test_proxy/main.tf
- name: Checkout TFE Load Test
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
path: ${{ env.K6_WORK_DIR_PATH }}
repository: hashicorp/tfe-load-test
token: ${{ secrets.GH_TFE_LOAD_TEST_TOKEN }}
persist-credentials: false

- name: Install required tools
working-directory: ${{ env.K6_WORK_DIR_PATH }}
env:
K6_URL: https://github.com/loadimpact/k6/releases/download/v0.31.1/k6-v0.31.1-linux64.tar.gz
run: |
sudo apt-get install jq
curl -L $K6_URL | tar -xz --strip-components=1
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
with:
cli_config_credentials_hostname: 'app.terraform.io'
cli_config_credentials_token: ${{ secrets[inputs.TFC_token_secret_name] }}
terraform_version: 1.1.5
terraform_wrapper: false

- name: Write Private SSH Key
if: ${{ inputs.ssh_private_key_secret_name != '' }}
working-directory: ${{ env.WORK_DIR_PATH }}
env:
SSH_KEY_BASE64: ${{ secrets[inputs.ssh_private_key_secret_name] }}
run: |
echo "$SSH_KEY_BASE64" | base64 --decode > ./ssh-key.pem
chmod 0400 ./ssh-key.pem
- name: Terraform Init
id: init
working-directory: ${{ env.WORK_DIR_PATH }}
run: terraform init -input=false -no-color

- name: Terraform Validate
id: validate
working-directory: ${{ env.WORK_DIR_PATH }}
run: terraform validate -no-color

- name: Write GitHub Actions runner CIDR to Terraform Variables
working-directory: ${{ env.WORK_DIR_PATH }}
run: |
echo "iact_subnet_list = [\"$( dig +short @resolver1.opendns.com myip.opendns.com )/32\"]" >> github.auto.tfvars
echo "is_replicated_deployment = ${{ inputs.is_replicated_deployment }} >> github.auto.tfvars
- name: Terraform Targeted Pre-Apply
if: ${{ inputs.first_apply_args != '' }}
id: pre-apply
working-directory: ${{ env.WORK_DIR_PATH}}
run: |
tfrun apply ${{ inputs.first_apply_args }}} --auto-approve
sleep 180
- name: Terraform Apply
id: apply
working-directory: ${{ env.WORK_DIR_PATH }}
run: terraform apply -auto-approve -input=false -no-color

- name: Retrieve Health Check URL
id: retrieve-health-check-url
working-directory: ${{ env.WORK_DIR_PATH }}
run: |
terraform output -no-color -raw health_check_url
- name: Retrieve Instance ID
if: ${{ inputs.ssh_private_key_secret_name != '' }}
id: retrieve-instance-id
working-directory: ${{ env.WORK_DIR_PATH }}
run: |
terraform output -no-color -raw proxy_instance_id
- name: Configure AWS Credentials
if: ${{ inputs.ssh_private_key_secret_name != '' }}
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
with:
aws-access-key-id: ${{ secrets.AWS_PRIVATE_TCP_ACTIVE_ACTIVE_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_PRIVATE_TCP_ACTIVE_ACTIVE_AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-2
role-to-assume: ${{ secrets.AWS_PRIVATE_TCP_ACTIVE_ACTIVE_AWS_ROLE_TO_ASSUME }}
role-duration-seconds: 2400
role-skip-session-tagging: true

- name: Start SOCKS5 Proxy
if: ${{ inputs.ssh_private_key_secret_name != '' }}
env:
INSTANCE_ID: ${{ steps.retrieve-instance-id.outputs.stdout }}
run: |
aws ec2 wait instance-status-ok --instance-ids "$INSTANCE_ID"
ssh \
-o 'BatchMode yes' \
-o 'StrictHostKeyChecking accept-new' \
-o 'ServerAliveInterval 5' \
-o 'ServerAliveCountMax 3' \
-o 'ProxyCommand sh -c \
"aws ssm start-session \
--target %h \
--document-name AWS-StartSSHSession \
--parameters \"portNumber=%p\""' \
-i ./ssh-key.pem \
-f -N -p 22 -D localhost:5000 \
ubuntu@"$INSTANCE_ID"
- name: Wait For TFE
id: wait-for-tfe
timeout-minutes: 20
env:
HEALTH_CHECK_URL: ${{ steps.retrieve-health-check-url.outputs.stdout }}
USE_PROXY: ${{ inputs.ssh_private_key_secret_name != '' && '--proxy socks5://localhost:5000' || '' }}
run: |
echo "Curling \`health_check_url\` for a return status of 200..."
while ! curl \
--connect-timeout 10 \
-sfS --max-time 5 \
$USE_PROXY \
--verbose \
$HEALTH_CHECK_URL; \
do sleep 5; done
- name: Retrieve TFE URL
id: retrieve-tfe-url
working-directory: ${{ env.WORK_DIR_PATH }}
run: |
terraform output -no-color -raw tfe_url
- name: Retrieve IACT URL
id: retrieve-iact-url
working-directory: ${{ env.WORK_DIR_PATH }}
run: |
terraform output -no-color -raw iact_url
- name: Retrieve IACT
id: retrieve-iact
env:
IACT_URL: ${{ steps.retrieve-iact-url.outputs.stdout }}
USE_PROXY: ${{ inputs.ssh_private_key_secret_name != '' && '--proxy socks5://localhost:5000' || '' }}
run: |
token=$( \
curl --fail --retry 5 --verbose \
--connect-timeout 10 \
$USE_PROXY "$IACT_URL")
echo "::set-output name=token::$token"
- name: Retrieve Initial Admin User URL
id: retrieve-initial-admin-user-url
working-directory: ${{ env.WORK_DIR_PATH }}
run: |
terraform output -no-color -raw initial_admin_user_url
- name: Create Admin in TFE
id: create-admin
env:
TFE_PASSWORD: ${{ secrets.TFE_PASSWORD }}
IAU_URL: ${{ steps.retrieve-initial-admin-user-url.outputs.stdout }}
IACT_TOKEN: ${{ steps.retrieve-iact.outputs.token }}
USE_PROXY: ${{ inputs.ssh_private_key_secret_name != '' && '--proxy socks5://localhost:5000' || '' }}
run: |
echo \
'{"username": "test", "email": "[email protected]", "password": "$TFE_PASSWORD"}' \
> ./payload.json
response=$( \
curl \
--connect-timeout 10 \
--fail \
--retry 5 \
--verbose \
--header 'Content-Type: application/json' \
--data @./payload.json \
$USE_PROXY \
"$IAU_URL"?token="$IACT_TOKEN")
echo "::set-output name=response::$response"
- name: Retrieve Admin Token
id: retrieve-admin-token
env:
RESPONSE: ${{ steps.create-admin.outputs.response }}
run: |
token=$(echo "$RESPONSE" | jq --raw-output '.token')
echo "::set-output name=token::$token"
- name: Run k6 Smoke Test
id: run-smoke-test
working-directory: ${{ env.K6_WORK_DIR_PATH }}
env:
K6_PATHNAME: "./k6"
TFE_URL: "${{ steps.retrieve-tfe-url.outputs.stdout }}"
TFE_API_TOKEN: "${{ steps.retrieve-admin-token.outputs.token }}"
TFE_EMAIL: [email protected]
http_proxy: ${{ inputs.ssh_private_key_secret_name != '' && 'socks5://localhost:5000/' || '' }}
https_proxy: ${{ inputs.ssh_private_key_secret_name != '' && 'socks5://localhost:5000/' || '' }}
run: |
make smoke-test
- name: Terraform Destroy
id: destroy
if: ${{ always() && github.event.client_payload.slash_command.args.named.destroy != 'false' }}
working-directory: ${{ env.WORK_DIR_PATH }}
run: terraform destroy -auto-approve -input=false -no-color

- name: Update comment
if: ${{ always() }}
uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ inputs.pull_request_repo_name }}
comment-id: ${{ inputs.pull_request_comment_id }}
body: |
${{ format('### {0} Terraform AWS {1} ({2}) - Test Report', job.status == 'success' && ':white_check_mark:' || ':x:', inputs.test_name, inputs.is_replicated_deployment && 'Replicated' || 'FDO') }}
${{ format(':link: [Action Summary Page]({0})', steps.vars.outputs.run-url) }}
${{ format('- {0} Terraform Init', steps.init.outcome == 'success' && ':white_check_mark:' || ':x:') }}
${{ format('- {0} Terraform Validate', steps.validate.outcome == 'success' && ':white_check_mark:' || ':x:') }}
${{ format('- {0} Terraform Apply', steps.apply.outcome == 'success' && ':white_check_mark:' || ':x:') }}
${{ format('- {0} Run k6 Smoke Test', steps.run-smoke-test.outcome == 'success' && ':white_check_mark:' || ':x:') }}
${{ github.event.client_payload.slash_command.args.named.destroy != 'false' && format('- {0} Terraform Destroy', steps.destroy.outcome == 'success' && ':white_check_mark:' || ':x:') || '' }}
Loading

0 comments on commit a529d5c

Please sign in to comment.