Skip to content

Commit

Permalink
Merge pull request #1130 from CDCgov/story/1121/dockerize-load-tests
Browse files Browse the repository at this point in the history
Add Containerization To Load Test
  • Loading branch information
saquino0827 authored Jun 17, 2024
2 parents 3d6b742 + 093963d commit 9ea1a90
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 73 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,15 @@ The `test` directory contains the tests. The `main` directory contains our cust

#### Load Testing

Load tests are completed with [Locust.io](https://docs.locust.io/en/stable/installation.html). Run the load tests by
running...
Load tests are completed with [Locust.io](https://docs.locust.io/en/stable/installation.html).
Run the load tests by running...

```shell
./load-execute.sh
./gradle-load-execute.sh

./docker-load-execute.sh
```
Currently, we are migrating to using Azure. Local load testing is using gradle, however a docker load test is available to mimic the Azure environment settings until the azure migration is complete.

This will run the API for you, so no need to run it manually.
**If you are already running the API, stop it before running the load tests or the cleanup steps won't work.**
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.postgres-test.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: "3.7"

services:
postgresql-test:
postgresql:
image: postgres:16
restart: unless-stopped
environment:
Expand Down
112 changes: 112 additions & 0 deletions docker-load-execute.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/usr/bin/env bash
set -e

local_port=5434

start_api() {
echo 'Starting API'
export DB_URL=postgresql
export DB_PORT=${local_port}
export DB_NAME=intermediary-test
export DB_USER=intermediary
export DB_PASS=changeIT!
export DB_SSL=require
export REPORT_STREAM_URL_PREFIX=
./gradlew shadowJar
docker compose up --build -d
export API_PID="${!}"
echo "API starting at PID ${API_PID}"
}

start_database() {
echo 'Starting database'
docker compose -f docker-compose.postgres-test.yml up -d
sleep 2
echo "Database started"
}
migrate_database() {
echo 'Migrating database'
liquibase update --changelog-file ./etor/databaseMigrations/root.yml --url jdbc:postgresql://localhost:${local_port}/intermediary-test --username intermediary --password 'changeIT!' --label-filter '!azure'
echo "Database migrated"
}

wait_for_api() {
attempt_counter=0
max_attempts=36

until curl --output /dev/null --silent --head --fail http://localhost:8080/health; do
if [ "${attempt_counter}" -eq "${max_attempts}" ];then
echo 'Done waiting for API to respond'
exit 1
fi
attempt_counter=$(($attempt_counter+1))
echo 'Waiting for API to respond'
sleep 5
done

echo 'API is responding'
}

warm_up_api() {
echo 'Warming up API...'
sleep 5
tokenPath=$(pwd)/mock_credentials/trusted-intermediary-valid-token.jwt
token=$(cat "${tokenPath}")

echo ${token}

echo 'Warming up auth...'
tiAuthResponse=$(curl --request POST "http://localhost:8080/v1/auth/token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "scope=trusted-intermediary" \
--data-urlencode "client_assertion=${token}")

echo "$tiAuthResponse"
echo 'Retrieving access token...'

accessToken=$(echo "$tiAuthResponse" | grep -o '"access_token":"[^"]*' | grep -o '[^"]*$')

echo "$accessToken"

echo 'Warming up results...'
resultFile=$(pwd)/examples/Test/e2e/results/001_ORU_R01_short.fhir
curl --silent --request POST "http://localhost:8080/v1/etor/results" \
--header "recordId: 6789" \
--header "Authorization: Bearer ${accessToken}" \
--data-binary "@${resultFile}"

echo 'Warming up orders...'
orderFile=$(pwd)/examples/Test/e2e/orders/002_ORM_O01_short.fhir
curl --silent --request POST "http://localhost:8080/v1/etor/orders" \
--header "recordId: 1234" \
--header "Authorization: Bearer ${accessToken}" \
--data-binary "@${orderFile}"

echo 'Warm up nap time...'
sleep 5

echo 'API is cozy'
}

run_tests() {
echo 'Running the load test'
locust --headless -f ./operations/locustfile.py -H http://localhost:8080 -u 1000 -r 15 -t 5m
}

cleanup() {
echo "Stopping API docker container"
docker compose down
echo "API Docker container stopped"
echo "Stopping and deleting database"
docker compose -f docker-compose.postgres-test.yml down -v
echo "Database stopped and deleted"
}

trap cleanup EXIT # Run the cleanup function on exit
start_database
migrate_database
start_api
wait_for_api
warm_up_api
warm_up_api
run_tests
111 changes: 111 additions & 0 deletions gradle-load-execute.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env bash
set -e

local_port=5434

start_api() {
echo 'Starting API'
export DB_URL=localhost
export DB_PORT=${local_port}
export DB_NAME=intermediary-test
export DB_USER=intermediary
export DB_PASS=changeIT!
export DB_SSL=require
export REPORT_STREAM_URL_PREFIX=
./gradlew --no-daemon app:clean app:run > /dev/null 2>&1 &
export API_PID="${!}"
echo "API starting at PID ${API_PID}"
}

start_database() {
echo 'Starting database'
docker compose -f docker-compose.postgres-test.yml up -d
sleep 2
echo "Database started"
}

migrate_database() {
echo 'Migrating database'
liquibase update --changelog-file ./etor/databaseMigrations/root.yml --url jdbc:postgresql://localhost:${local_port}/intermediary-test --username intermediary --password 'changeIT!' --label-filter '!azure'
echo "Database migrated"
}

wait_for_api() {
attempt_counter=0
max_attempts=36

until curl --output /dev/null --silent --head --fail http://localhost:8080/health; do
if [ "${attempt_counter}" -eq "${max_attempts}" ];then
echo 'Done waiting for API to respond'
exit 1
fi
attempt_counter=$(($attempt_counter+1))
echo 'Waiting for API to respond'
sleep 5
done

echo 'API is responding'
}

warm_up_api() {
echo 'Warming up API...'
sleep 5
tokenPath=$(pwd)/mock_credentials/trusted-intermediary-valid-token.jwt
token=$(cat "${tokenPath}")

echo ${token}

echo 'Warming up auth...'
tiAuthResponse=$(curl --request POST "http://localhost:8080/v1/auth/token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "scope=trusted-intermediary" \
--data-urlencode "client_assertion=${token}")

echo "$tiAuthResponse"
echo 'Retrieving access token...'

accessToken=$(echo "$tiAuthResponse" | grep -o '"access_token":"[^"]*' | grep -o '[^"]*$')

echo "$accessToken"

echo 'Warming up results...'
resultFile=$(pwd)/examples/Test/e2e/results/001_ORU_R01_short.fhir
curl --silent --request POST "http://localhost:8080/v1/etor/results" \
--header "recordId: 6789" \
--header "Authorization: Bearer ${accessToken}" \
--data-binary "@${resultFile}"

echo 'Warming up orders...'
orderFile=$(pwd)/examples/Test/e2e/orders/002_ORM_O01_short.fhir
curl --silent --request POST "http://localhost:8080/v1/etor/orders" \
--header "recordId: 1234" \
--header "Authorization: Bearer ${accessToken}" \
--data-binary "@${orderFile}"

echo 'Warm up nap time...'
sleep 5

echo 'API is cozy'
}

run_tests() {
echo 'Running the load test'
locust --headless -f ./operations/locustfile.py -H http://localhost:8080 -u 1000 -r 17 -t 5m
}

cleanup() {
echo "Killing API at PID ${API_PID}"
kill "${API_PID}"
echo "PID ${API_PID} killed"
echo "Stopping and deleting database"
docker compose -f docker-compose.postgres-test.yml down -v
echo "Database stopped and deleted"
}

trap cleanup EXIT # Run the cleanup function on exit
start_database
migrate_database
start_api
wait_for_api
warm_up_api
run_tests
68 changes: 0 additions & 68 deletions load-execute.sh

This file was deleted.

2 changes: 1 addition & 1 deletion operations/locustfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def authenticate(self):
else:
logging.error(f"Authentication failed: {response.error}")

@task
@task(1)
def get_health(self):
self.client.get(HEALTH_ENDPOINT)

Expand Down

0 comments on commit 9ea1a90

Please sign in to comment.