extras/dcgoss/dcgoss
#!/bin/bash
set -e
[ "$DEBUG" ] && set -x
USAGE="USAGE: $(basename "$0") [run|edit] <docker-compose-service>"
GOSS_FILES_PATH="${GOSS_FILES_PATH:-.}"
info() {
echo -e "INFO: $*" >&2;
}
error() {
echo -e "ERROR: $*" >&2;
[[ -e "$service" ]] && docker logs "$service"
exit 1;
}
cleanup() {
set +e
{ kill "$log_pid" && wait "$log_pid"; } 2> /dev/null
[ "$DEBUG" ] || rm -rf "$tmp_dir"
if [[ -n "$service" ]]; then
info "Stopping container"
echo "Deleting $(docker rm -f "$service")"
docker-compose stop > /dev/null
fi
}
run(){
# Copy in goss
cp "${GOSS_PATH}" "$tmp_dir/goss"
chmod 755 "$tmp_dir/goss"
[[ -e "${GOSS_FILES_PATH}/${GOSS_FILE:-goss.yaml}" ]] && install -m ugo+rw "${GOSS_FILES_PATH}/${GOSS_FILE:-goss.yaml}" "$tmp_dir"
[[ -e "${GOSS_FILES_PATH}/goss_wait.yaml" ]] && install -m ugo+rw "${GOSS_FILES_PATH}/goss_wait.yaml" "$tmp_dir"
[[ -n "${GOSS_VARS}" ]] && [[ -e "${GOSS_FILES_PATH}/${GOSS_VARS}" ]] && install -m ugo+rw "${GOSS_FILES_PATH}/${GOSS_VARS}" "$tmp_dir"
# Switch between mount or cp files strategy
GOSS_FILES_STRATEGY=${GOSS_FILES_STRATEGY:="mount"}
case "$GOSS_FILES_STRATEGY" in
mount)
info "Starting docker container"
docker-compose run -d -T --name "$service" -v "$tmp_dir:/goss" "$service"
;;
cp)
info "Creating docker container"
docker-compose run -d -T --name "$service" "$service"
info "Copy goss files into container"
docker cp "$tmp_dir/." "$service:/goss"
;;
*) error "Wrong goss files strategy used! Correct options are \"mount\" or \"cp\"."
esac
docker logs -f "$service" > "$tmp_dir/docker_output.log" 2>&1 &
log_pid="$!"
info "Container name: $service"
}
get_docker_file() {
set +e
if docker exec "$service" sh -c "test -e $1" > /dev/null; then
mkdir -p "${GOSS_FILES_PATH}"
info "Copied '$1' from container to '${GOSS_FILES_PATH}'"
docker cp "$service:$1" "${GOSS_FILES_PATH}"
fi
set -e
}
# Main
tmp_dir=$(mktemp -d /tmp/tmp.XXXXXXXXXX)
chmod 777 "$tmp_dir"
# shellcheck disable=SC2154
trap 'ret=$?; cleanup; info "Test ran for a total of $SECONDS seconds"; exit $ret' EXIT
service="$2"
if [[ ! -f docker-compose.yaml && ! -f docker-compose.yml ]]; then
echo "no docker-compose file found in ."
exit 1
fi
state=$(docker inspect --format '{{.State.Status}}' "$service" 2> /dev/null || true)
if [[ "$state" == running ]]; then
docker rm -f "$service" > /dev/null
elif [[ "$state" == exited ]]; then
docker rm "$service" > /dev/null
fi
GOSS_PATH="${GOSS_PATH:-$(command -v goss 2> /dev/null || true)}"
[[ "$GOSS_PATH" ]] || { error "Couldn't find goss installation, please set GOSS_PATH to it"; }
[[ "${GOSS_OPTS+x}" ]] || GOSS_OPTS="--color --format documentation"
[[ "${GOSS_WAIT_OPTS+x}" ]] || GOSS_WAIT_OPTS="-r 30s -s 1s > /dev/null"
GOSS_SLEEP="${GOSS_SLEEP:-0.2}"
case "$1" in
run)
run "$@"
[[ "$GOSS_SLEEP" ]] && { info "Sleeping for $GOSS_SLEEP"; sleep "$GOSS_SLEEP"; }
if [[ -e "${GOSS_FILES_PATH}/goss_wait.yaml" ]]; then
info "Found goss_wait.yaml, waiting for it to pass before running tests"
if [[ -z "${GOSS_VARS}" ]]; then
if ! docker exec "$service" sh -c "/goss/goss -g /goss/goss_wait.yaml render | /goss/goss -g - validate $GOSS_WAIT_OPTS"; then
error "goss_wait.yaml never passed"
fi
else
if ! docker exec "$service" sh -c "/goss/goss -g /goss/goss_wait.yaml --vars='/goss/${GOSS_VARS}' render | /goss/goss -g - validate $GOSS_WAIT_OPTS"; then
error "goss_wait.yaml never passed"
fi
fi
fi
info "Container health"
if ! docker top "$service"; then
error "The container failed to start"
fi
info "Running Tests"
if [[ -z "${GOSS_VARS}" ]]; then
docker exec "$service" sh -c "/goss/goss -g /goss/${GOSS_FILE:-goss.yaml} render | /goss/goss -g - validate $GOSS_OPTS"
else
docker exec "$service" sh -c "/goss/goss -g /goss/${GOSS_FILE:-goss.yaml} --vars='/goss/${GOSS_VARS}' render | /goss/goss -g - validate $GOSS_OPTS"
fi
;;
edit)
run "$@"
info "Run goss add/autoadd to add resources"
docker exec -it "$service" sh -c 'cd /goss; PATH="/goss:$PATH" exec sh'
[[ -n "${GOSS_FILE}" ]] && get_docker_file "/goss/${GOSS_FILE}"
get_docker_file "/goss/goss.yaml"
get_docker_file "/goss/goss_wait.yaml"
[[ -n "${GOSS_VARS}" ]] && get_docker_file "/goss/${GOSS_VARS}"
;;
*)
error "$USAGE"
esac