Skip to content

Commit

Permalink
test the current branch by building ziti and the quickstart container
Browse files Browse the repository at this point in the history
image and running in compose and running quickstart_test.go
  • Loading branch information
qrkourier committed Aug 31, 2023
1 parent 271d9da commit aa58722
Show file tree
Hide file tree
Showing 6 changed files with 1,254 additions and 14 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/test-quickstart.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Test Quickstart
on:
workflow_dispatch:
# test quickstart changes after merge
push:
branches:
- release-next
- main
paths:
- 'quickstart/**'
# test quickstart changes before merge
pull_request:
paths:
- 'quickstart/**'

# cancel older, redundant runs of same workflow on same branch
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

jobs:
compose-test:
name: Test Compose Quickstart
runs-on: ubuntu-latest
steps:
- name: Shallow checkout
uses: actions/checkout@v3
- name: Install zsh
run: sudo apt-get update && sudo apt-get install --yes zsh
- name: Build and run a quickstart container image
run: ./quickstart/test/compose-test.zsh
33 changes: 28 additions & 5 deletions quickstart/docker/image/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,43 @@ FROM ubuntu:rolling as fetch-ziti-bins

# optional arg to specify which version to fetch when local "ziti-bin" directory is not present
ARG ZITI_VERSION_OVERRIDE
ARG DEBIAN_FRONTEND=noninteractive

COPY . /docker.build.context
RUN apt update && apt install jq curl -y && \
RUN apt-get update \
&& apt-get --yes install \
jq \
curl \
&& apt-get --yes autoremove \
&& apt-get clean autoclean \
&& rm -fr /var/lib/apt/lists/{apt,dpkg,cache,log} /tmp/* /var/tmp/*
# to use a locally built `ziti` cli \
# create a ./ziti-bin directory adjacent to this Dockerfile \
# and include any desired binaries to include in the image
# to use the latest released version of ziti \
# just build the Dockerfile \
# to use a specific version of ziti, specify ZITI_VERSION_OVERRIDE then \
# build the Dockerfile
/bin/bash /docker.build.context/fetch-ziti-bins.sh /ziti-bin
RUN bash /docker.build.context/fetch-ziti-bins.sh /ziti-bin

FROM ubuntu:rolling
ARG RUNUSER=ziti
ARG RUNGROUP=ziti
ARG RUNUSERID=2171

RUN apt update && \
apt install jq curl netcat-openbsd vim inetutils-ping net-tools lsof -y
RUN apt-get update \
&& apt-get --yes install \
jq \
curl \
netcat-openbsd \
vim \
inetutils-ping \
net-tools \
lsof \
zsh \
&& apt-get --yes autoremove \
&& apt-get clean autoclean \
&& rm -fr /var/lib/apt/lists/{apt,dpkg,cache,log} /tmp/* /var/tmp/*

RUN useradd -u $RUNUSERID -ms /bin/bash $RUNUSER && \
mkdir /persistent && chown $RUNUSER:$RUNGROUP /persistent && \
Expand Down Expand Up @@ -48,4 +66,9 @@ COPY --chown=ziti run-with-ziti-cli.sh "${ZITI_SCRIPTS}/"
COPY --chown=ziti access-control.sh "${ZITI_SCRIPTS}/"
COPY --chown=ziti run-router-external.sh "${ZITI_SCRIPTS}/"

RUN /bin/bash -c "source ${ZITI_SCRIPTS}/ziti-cli-functions.sh; persistEnvironmentValues; echo source ${ZITI_HOME}/ziti.env >> ~/.bashrc"
RUN /bin/bash -c " \
source ${ZITI_SCRIPTS}/ziti-cli-functions.sh; \
persistEnvironmentValues; \
echo source ${ZITI_HOME}/ziti.env \
>> ~/.bashrc \
"
42 changes: 33 additions & 9 deletions quickstart/docker/image/ziti-cli-functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,28 @@ function _wait_for_controller {
done
}

function _wait_for_public_router {
local advertised_host_port="${ZITI_ROUTER_NAME}:${ZITI_ROUTER_PORT}"
local COUNTDOWN=30
until [[ -s "${ZITI_HOME}/${ZITI_ROUTER_NAME}.cert" ]] \
&& openssl s_client \
-connect "${advertised_host_port}" \
-servername "${ZITI_ROUTER_NAME}" \
-alpn "ziti-edge,h2,http/1.1" \
-cert "${ZITI_HOME}/${ZITI_ROUTER_NAME}.cert" \
-key "${ZITI_HOME}/${ZITI_ROUTER_NAME}.key" \
<>/dev/null 2>&1 # client cert needed for a zero exit code
do
if (( COUNTDOWN-- )); then
echo "INFO: waiting for https://${advertised_host_port}"
sleep 3
else
echo "ERROR: timed out waiting for https://${advertised_host_port}" >&2
return 1
fi
done
}

function _setup_ziti_home {
_setup_ziti_network
if [[ "${ZITI_HOME-}" == "" ]]; then export ZITI_HOME="${HOME}/.ziti/quickstart/${ZITI_NETWORK-}"; else echo "ZITI_HOME overridden: ${ZITI_HOME}"; fi
Expand Down Expand Up @@ -366,7 +388,7 @@ function setupEnvironment {

# Stores environment variables prefixed with ZITI_ to a .env file
function persistEnvironmentValues {
local filepath retVal envval envvar zEnvVar
local filepath tmpfilepath retVal envval envvar zEnvVar
# Get the file path
filepath="${1-}"
if [[ "" == "${filepath}" ]]; then
Expand All @@ -381,23 +403,24 @@ function persistEnvironmentValues {
fi

# Store all ZITI_ variables in the environment file, creating the directory if necessary
mkdir -p "$(dirname "${filepath}")" && echo "" > "${filepath}"
tmpfilepath="$(mktemp)"
mkdir -p "$(dirname "${filepath}")" && echo "" > "${tmpfilepath}"
for zEnvVar in $(set | grep -e "^ZITI_" | sort); do
envvar="$(echo "${zEnvVar}" | cut -d '=' -f1)"
envval="$(echo "${zEnvVar}" | cut -d '=' -f2-1000)"
echo 'if [[ "$'${envvar}'" == "" ]]; then export '${envvar}'="'${envval}'"; else echo "NOT OVERRIDING: env var '${envvar}' already set. using existing value"; fi' >> "${filepath}"
echo 'if [[ "$'${envvar}'" == "" ]]; then export '${envvar}'="'${envval}'"; else echo "NOT OVERRIDING: env var '${envvar}' already set. using existing value"; fi' >> "${tmpfilepath}"
done

export PFXLOG_NO_JSON=true
# shellcheck disable=SC2129
echo "export PFXLOG_NO_JSON=true" >> "${filepath}"
echo "export PFXLOG_NO_JSON=true" >> "${tmpfilepath}"

echo "alias zec='ziti edge'" >> "${filepath}"
echo "alias zitiLogin='ziti edge login \"\${ZITI_CTRL_EDGE_ADVERTISED_ADDRESS}:\${ZITI_CTRL_EDGE_ADVERTISED_PORT}\" -u \"\${ZITI_USER-}\" -p \"\${ZITI_PWD}\" -y'" >> "${filepath}"
echo "alias psz='ps -ef | grep ziti'" >> "${filepath}"
echo "alias zec='ziti edge'" >> "${tmpfilepath}"
echo "alias zitiLogin='ziti edge login \"\${ZITI_CTRL_EDGE_ADVERTISED_ADDRESS}:\${ZITI_CTRL_EDGE_ADVERTISED_PORT}\" -u \"\${ZITI_USER-}\" -p \"\${ZITI_PWD}\" -y'" >> "${tmpfilepath}"
echo "alias psz='ps -ef | grep ziti'" >> "${tmpfilepath}"

#when sourcing the emitted file add the bin folder to the path
tee -a "${filepath}" > /dev/null <<'heredoc'
cat >> "${tmpfilepath}" <<'HEREDOC'
echo " "
if [[ ! "$(echo "$PATH"|grep -q "${ZITI_BIN_DIR}" && echo "yes")" == "yes" ]]; then
echo "adding ${ZITI_BIN_DIR} to the path"
Expand All @@ -407,8 +430,9 @@ echo " ziti binaries are located at: ${ZITI_BIN_DIR}"
echo -e 'add this to your path if you want by executing: export PATH=$PATH:'"${ZITI_BIN_DIR}"
echo " "
fi
heredoc
HEREDOC

mv "${tmpfilepath}" "${filepath}"
echo -e "A file with all pertinent environment values was created here: $(BLUE "${filepath}")"
echo ""
}
Expand Down
154 changes: 154 additions & 0 deletions quickstart/test/compose-test.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/usr/bin/env zsh
#
# this script tests the quickstart's ziti-cli-functions.sh, container image creation process, and Compose project by
# gathering files from a particular GitHub repo ref or a filesystem path and running the quickstart's Go test suite
# against the running Compose project
#

set -euo pipefail

function down_project() {
# don't destroy volumes or temp dir so we can inspect when running locally
docker compose kill
# rm -rf "${TESTDIR}"
echo "INFO: Stopped Compose project: ${TESTDIR}"
}

DATESTAMP=$(date +%Y%m%d%H%M%S)
# generate a random password for the controller's admin user to ensure we're testing the expected instance
ZITI_PWD="$(set +o pipefail; LC_ALL=C tr -dc -- -A-Z-a-z-0-9 < /dev/urandom 2>/dev/null | head -c5)"
BASENAME="$(basename "$0")"
DIRNAME="$(dirname "$0")"
if [[ -n "${ZITI_QUICK_DIR:-}" ]]; then
if [[ -d "${ZITI_QUICK_DIR}" ]]; then
ZITI_QUICK_DIR="$(realpath "${ZITI_QUICK_DIR}")"
else
if [[ -d "${DIRNAME}/${ZITI_QUICK_DIR}" ]]; then
ZITI_QUICK_DIR="$(realpath "${DIRNAME}/${ZITI_QUICK_DIR}")"
else
echo "ERROR: ZITI_QUICK_DIR is set but is not a directory: ${ZITI_QUICK_DIR}" >&2
exit 1
fi
fi
fi
# avoid re-using directories from previous runs to keep this one-shot (non-idempotent) script simple because we needn't
# consider the state of the test dir
TESTDIR="$(mktemp -d -t "${BASENAME%.*}.${DATESTAMP}.XXX")"

# if unset, set ZITI_QUICK_DIR to this script's parent dir which is always the quickstart root in the git repo
if [[ -z "${ZITI_QUICK_DIR:-}" ]]; then
ZITI_QUICK_DIR="$(realpath "${DIRNAME}/..")"
fi
# if unset, set ZITI_QUICK_IMAGE_TAG to this run's dirname
if [[ -z "${ZITI_QUICK_IMAGE_TAG:-}" ]]; then
ZITI_QUICK_IMAGE_TAG=$(basename "${TESTDIR}")
fi

# case "${1:-}" in
# shift
# ;;
# --help|-h)
# echo "Usage: $BASENAME [--local|--help]"
# exit 0
# ;;
# esac

cd "${TESTDIR}"
echo "INFO: Testing Compose project $PWD"

declare -a QUICK_FILES=(
../go.{mod,sum}
test/{quickstart_test.go,compose.override.yml}
docker/{simplified-docker-compose.yml,.env}
)
# TODO: re-add cert checks files after https://github.com/openziti/ziti/pull/1278
# test/{quickstart_test.go,compose.override.yml,check-cert-chains.zsh}
# download the quickstart Go test suite files from GitHub unless a local dir is specified
if [[ -n "${ZITI_QUICK_DIR:-}" ]]; then
for FILE in "${QUICK_FILES[@]}"; do
cp "${ZITI_QUICK_DIR}/${FILE}" .
done
if [[ -n "${ZITI_QUICK_IMAGE_TAG:-}" ]]; then
if [[ -x "${ZITI_QUICK_DIR:-}/docker/createLocalImage.sh" ]]; then
(
cd "${ZITI_QUICK_DIR}/docker"
unset ZITI_VERSION ZITI_OVERRIDE_VERSION # always build the local source
./createLocalImage.sh --build "${ZITI_QUICK_IMAGE_TAG}"
)
else
echo "ERROR: ZITI_QUICK_IMAGE_TAG is set but ZITI_QUICK_DIR/docker/createLocalImage.sh is not executable" >&2
exit 1
fi
fi
elif [[ -n "${ZITI_QUICK_IMAGE_TAG:-}" ]]; then
echo "ERROR: ZITI_QUICK_IMAGE_TAG is set but ZITI_QUICK_DIR is not set" >&2
exit 1
else
echo "ERROR: ZITI_QUICK_IMAGE_TAG is not set, try running with --local" >&2
exit 1
fi

# rename the simplified Compose file to the default Compose project file name
mv ./simplified-docker-compose.yml ./compose.yml

# learn the expected Go version from the Go mod file so we can pull the correct container image
ZITI_GO_VERSION="$(grep -Po '^go\s+\K\d+\.\d+(\.\d+)?$' ./go.mod)"
# make this var available in the Compose project
sed -Ei "s/^(#\s+)?(ZITI_GO_VERSION)=.*/\2=${ZITI_GO_VERSION}/" ./.env
sed -Ei "s/^(#\s+)?(ZITI_PWD)=.*/\2=${ZITI_PWD}/" ./.env
sed -Ei "s/^(#\s+)?(ZITI_INTERFACE)=.*/\2=${ZITI_INTERFACE:-127.0.0.1}/" ./.env

# pull images preemptively that we never build locally because pull=never when using a local quickstart image
for IMAGE in \
"golang:${ZITI_GO_VERSION}-alpine" \
"openziti/zac:latest"
do
docker pull --quiet "${IMAGE}" &>/dev/null
done

# any halt after this point should cause the Compose project to be torn down
trap down_project SIGTERM SIGINT EXIT

# if ZITI_QUICK_IMAGE_TAG is set then run the locally-built image
if [[ -n "${ZITI_QUICK_IMAGE_TAG:-}" ]]; then
sed -Ei "s/^(#\s+)?(ZITI_VERSION)=.*/\2=${ZITI_QUICK_IMAGE_TAG}/" ./.env
docker compose up --detach --pull=never &>/dev/null # no pull because local quickstart image
else
echo "ERROR: ZITI_QUICK_IMAGE_TAG is not set" >&2
exit 1
fi

# copy files that are not present in older quickstart container images to the persistent volume; this allows us to run
# the test suite against them and investigate if the test fails and the container is destroyed
for FILE in \
""
# check-cert-chains.zsh
# TODO: re-add cert checks to cp list after https://github.com/openziti/ziti/pull/1278
do
docker compose cp \
"./${FILE}" \
"ziti-controller:/persistent/${FILE}" &>/dev/null
done
# TODO: build these executables into the container image?

# wait for the controller and router to be ready and run the certificate check script; NOUNSET option is enabled after
# sourcing quickstart functions and env because there are some unset variables in those
docker compose exec ziti-controller \
bash -eo pipefail -c '
source "${ZITI_SCRIPTS}/ziti-cli-functions.sh" >/dev/null;
echo "INFO: waiting for controller";
sleep 3;
source /persistent/ziti.env >/dev/null;
set -u;
_wait_for_controller >/dev/null;
echo "INFO: waiting for public router";
sleep 3;
source /persistent/ziti.env >/dev/null;
_wait_for_public_router >/dev/null;
'
# TODO: re-add cert checks to above test suite after https://github.com/openziti/ziti/pull/1278
# zsh /persistent/check-cert-chains.zsh;
docker compose run quickstart-test

echo -e "\nINFO: Test completed successfully."

Loading

0 comments on commit aa58722

Please sign in to comment.