Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run integration tests in docker #227

Merged
merged 7 commits into from Aug 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
@@ -1,4 +1,5 @@
*
!.env
!.yamllint
!*.yml
!docker/
Expand Down
2 changes: 0 additions & 2 deletions README.rst
Expand Up @@ -67,11 +67,9 @@ Development setup

First, install the system dependencies:

- `curl <https://curl.haxx.se>`_
- `docker <https://docs.docker.com>`_
- `docker-compose <https://docs.docker.com/compose/>`_
- `git <https://git-scm.com>`_
- `jq <https://stedolan.github.io/jq/>`_
- `make <https://www.gnu.org/software/make/>`_

Second, get the source code.
Expand Down
15 changes: 11 additions & 4 deletions docker-compose.yml
Expand Up @@ -95,7 +95,16 @@ services:
build:
context: .
dockerfile: docker/setup/Dockerfile
command: /app/setup.sh --help
command: echo skipped

integtest:
image: ${DOCKER_REPO}/opwenserver_integtest:${BUILD_TAG}
build:
context: .
dockerfile: docker/integtest/Dockerfile
command: echo skipped
volumes:
- /var/run/docker.sock:/var/run/docker.sock

rabbitmq:
image: rabbitmq:management-alpine
Expand All @@ -120,9 +129,7 @@ services:
- ${POSTGRES_PORT}:5432

azurite:
image: arafato/azurite:2.6.5
environment:
executable: blob
image: mcr.microsoft.com/azure-storage/azurite:latest
ports:
- ${AZURITE_PORT}:10000

Expand Down
@@ -1,33 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail

readonly polling_interval_seconds=2

log() {
echo "$@" >&2
}
scriptdir="$(dirname "$0")"
# shellcheck disable=SC1090
. "${scriptdir}/utils.sh"

get_dotenv() {
local key dotenv_file

key="$1"
dotenv_file="$(dirname "$0")/../../.env"

grep "^${key}=" "${dotenv_file}" | cut -d'=' -f2-
}
readonly polling_interval_seconds=2

sql() {
local user database query
wait_for_rabbitmq() {
local rabbitmq

user="$(get_dotenv "POSTGRES_USER")"
database="$(get_dotenv "POSTGRES_DB")"
query="$1"
rabbitmq="$(get_container rabbitmq)"

docker-compose exec postgres psql -U "${user}" -d "${database}" -c "${query}"
}

wait_for_rabbitmq() {
while ! docker-compose exec rabbitmq rabbitmqctl wait -q -P 1 -t "${polling_interval_seconds}"; do
while ! docker exec "${rabbitmq}" rabbitmqctl wait -q -P 1 -t "${polling_interval_seconds}"; do
log "Waiting for rabbitmq"
done

Expand Down
@@ -1,30 +1,33 @@
#!/usr/bin/env bash
set -euo pipefail

out_dir="$(dirname "$0")/../files/end_to_end/test.out"
scriptdir="$(dirname "$0")"
out_dir="${scriptdir}/files/test.out"
mkdir -p "${out_dir}"
# shellcheck disable=SC1090
. "${scriptdir}/utils.sh"

# workflow 3: register a new client called "developer"
# normally this endpoint would be called during a new lokole device setup
curl -fs \
-H "Content-Type: application/json" \
-u "admin:password" \
-d '{"domain":"developer1.lokole.ca"}' \
"http://localhost:8080/api/email/register/" \
"http://nginx:8888/api/email/register/" \
| tee "${out_dir}/register1.json"

# registering a client with bad credentials should fail
if curl -fs \
-H "Content-Type: application/json" \
-u "baduser:badpassword" \
-d '{"domain":"hacker.lokole.ca"}' \
"http://localhost:8080/api/email/register/" \
"http://nginx:8888/api/email/register/" \
; then echo "Was able to register a client with bad credentials" >&2; exit 4; fi

# also register another client to simulate multi-client emails
curl -fs \
-H "Content-Type: application/json" \
-u "admin:password" \
-d '{"domain":"developer2.lokole.ca"}' \
"http://localhost:8080/api/email/register/" \
"http://nginx:8888/api/email/register/" \
| tee "${out_dir}/register2.json"
@@ -1,9 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail

in_dir="$(dirname "$0")/../files/end_to_end"
out_dir="$(dirname "$0")/../files/end_to_end/test.out"
scriptdir="$(dirname "$0")"
in_dir="${scriptdir}/files"
out_dir="${scriptdir}/files/test.out"
mkdir -p "${out_dir}"
# shellcheck disable=SC1090
. "${scriptdir}/utils.sh"

emails_to_send="${in_dir}/client-emails.tar.gz"
client_id="$(jq -r '.client_id' < "${out_dir}/register1.json")"
Expand All @@ -12,14 +15,10 @@ resource_id="$(uuidgen).tar.gz"

# workflow 1: send emails written on the client to the world
# first we simulate the client uploading its emails to the shared blob storage
curl -fs \
-X PUT -T "${emails_to_send}" \
-H "x-ms-blob-type: BlockBlob" \
-H "Content-Length: $(wc -c "${emails_to_send}" | cut -d' ' -f1)" \
"http://localhost:10000/devstoreaccount1/${resource_container}/${resource_id}"
az_storage upload "${resource_container}" "${resource_id}" "${emails_to_send}"

# the client then calls the server to trigger the delivery of the emails
curl -fs \
-H "Content-Type: application/json" \
-d '{"resource_id":"'"${resource_id}"'"}' \
"http://localhost:8080/api/email/upload/${client_id}"
"http://nginx:8888/api/email/upload/${client_id}"
24 changes: 24 additions & 0 deletions docker/integtest/3-receive-email-for-client.sh
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail

scriptdir="$(dirname "$0")"
in_dir="${scriptdir}/files"
out_dir="${scriptdir}/files/test.out"
mkdir -p "${out_dir}"
# shellcheck disable=SC1090
. "${scriptdir}/utils.sh"

email_to_receive="${in_dir}/inbound-email.mime"

client_id="$(jq -r '.client_id' < "${out_dir}/register1.json")"

# workflow 2a: receive an email directed at one of the clients
# this simulates sendgrid delivering an email to the service
http --check-status -f POST \
"http://nginx:8888/api/email/sendgrid/${client_id}" \
"email=@${email_to_receive}"

# simulate delivery of the same email to the second mailbox
http --check-status -f POST \
"http://nginx:8888/api/email/sendgrid/${client_id}" \
"email=@${email_to_receive}"
@@ -1,8 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail

out_dir="$(dirname "$0")/../files/end_to_end/test.out"
scriptdir="$(dirname "$0")"
out_dir="${scriptdir}/files/test.out"
mkdir -p "${out_dir}"
# shellcheck disable=SC1090
. "${scriptdir}/utils.sh"

for i in 1 2; do

Expand All @@ -15,15 +18,13 @@ resource_container="$(jq -r '.resource_container' < "${out_dir}/register${i}.jso
# will package up the emails and store them on the shared blob storage
curl -fs \
-H "Accept: application/json" \
"http://localhost:8080/api/email/download/${client_id}" \
"http://nginx:8888/api/email/download/${client_id}" \
| tee "${out_dir}/download${i}.json"

resource_id="$(jq -r '.resource_id' < "${out_dir}/download${i}.json")"

# now we simulate the client downloading the package from the shared blob storage
curl -fs \
"http://localhost:10000/devstoreaccount1/${resource_container}/${resource_id}" \
> "${out_dir}/downloaded${i}.tar.gz"
az_storage download "${resource_container}" "${resource_id}" "${out_dir}/downloaded${i}.tar.gz"

tar xzf "${out_dir}/downloaded${i}.tar.gz" -C "${out_dir}"

Expand Down
@@ -1,13 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail

out_dir="$(dirname "$0")/../files/end_to_end/test.out"
scriptdir="$(dirname "$0")"
out_dir="${scriptdir}/files/test.out"
mkdir -p "${out_dir}"

sql_query() {
docker-compose exec postgres psql -Aqt -c "$1" -U ascoderu -d telemetry \
| tr -d -C '0-9'
}
# shellcheck disable=SC1090
. "${scriptdir}/utils.sh"

num_exceptions="$(sql_query 'select count(*) from exceptions;')"
num_exceptions_expected=0
Expand Down
17 changes: 17 additions & 0 deletions docker/integtest/Dockerfile
@@ -0,0 +1,17 @@
FROM microsoft/azure-cli:2.0.32

RUN apk add -q --no-cache \
curl=7.59.0-r0 \
docker=1.11.2-r1 \
jq=1.5-r2 \
util-linux=2.28-r3

RUN pip3 install --no-cache-dir --upgrade pip==19.2.3 && \
pip3 install --no-cache-dir httpie==1.0.2

WORKDIR /app

COPY .env .
COPY docker/integtest/ ./

CMD ["./tests.sh"]
File renamed without changes.
13 changes: 13 additions & 0 deletions docker/integtest/tests.sh
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail

scriptdir="$(dirname "$0")"

"${scriptdir}/0-wait-for-services.sh"
"${scriptdir}/1-register-client.sh"
"${scriptdir}/2-client-uploads-emails.sh" && sleep 10s
"${scriptdir}/3-receive-email-for-client.sh" && sleep 10s
"${scriptdir}/4-client-downloads-emails.sh"
"${scriptdir}/5-assert-on-results.sh"

rm -rf "${scriptdir}/files/test.out"
57 changes: 57 additions & 0 deletions docker/integtest/utils.sh
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
set -euo pipefail

sql() {
local postgres user database query

postgres="$(get_container postgres)"
user="$(get_dotenv "POSTGRES_USER")"
database="$(get_dotenv "POSTGRES_DB")"
query="$1"

docker exec "${postgres}" psql -U "${user}" -d "${database}" -c "${query}"
}

sql_query() {
local postgres

postgres="$(get_container postgres)"

docker exec "${postgres}" psql -Aqt -c "$1" -U ascoderu -d telemetry \
| tr -d -C '0-9'
}

get_container() {
docker ps --format '{{.Names}}' | grep "$1"
}

get_dotenv() {
local key dotenv_file

key="$1"
dotenv_file="$(dirname "$0")/.env"

grep "^${key}=" "${dotenv_file}" | cut -d'=' -f2-
}

log() {
echo "$@" >&2
}

az_storage() {
local mode="$1"
local container="$2"
local blob="$3"
local file="$4"
local storage_account storage_key

storage_account="$(get_dotenv AZURITE_ACCOUNT)"
storage_key="$(get_dotenv AZURITE_KEY)"

az storage blob "${mode}" --no-progress \
--file "${file}" \
--name "${blob}" \
--container-name "${container}" \
--connection-string "DefaultEndpointsProtocol=http;AccountName=${storage_account};AccountKey=${storage_key};BlobEndpoint=http://azurite:10000/${storage_account};" \
> /dev/null
}
11 changes: 3 additions & 8 deletions makefile
Expand Up @@ -53,13 +53,8 @@ lint: lint-python lint-shell lint-swagger lint-docker lint-yaml
ci: tests lint

integration-tests:
./tests/integration/wait.sh && \
./tests/integration/0-register-client.sh && \
./tests/integration/1-client-uploads-emails.sh && sleep 10s && \
./tests/integration/2-receive-email-for-client.sh && sleep 10s && \
./tests/integration/3-client-downloads-emails.sh && \
./tests/integration/assert.sh && \
rm -rf tests/files/end_to_end/test.out
docker-compose build integtest && \
docker-compose run --rm integtest ./tests.sh

clean:
find . -name '__pycache__' -type d -print0 | xargs -0 rm -rf
Expand All @@ -82,7 +77,7 @@ logs:
fi

stop:
docker-compose down --volumes
docker-compose down --volumes --timeout=5

verify-build:
docker pull wagoodman/dive
Expand Down
23 changes: 0 additions & 23 deletions tests/integration/2-receive-email-for-client.sh

This file was deleted.