#!/bin/bash set -e USAGE="USAGE: $(basename "$0") [run|edit|dockerfile] " GOSS_FILES_PATH="${GOSS_FILES_PATH:-.}" info() { echo -e "INFO: $*" >&2; } error() { echo -e "ERROR: $*" >&2; exit 1; } cleanup() { set +e { kill "$log_pid" && wait "$log_pid"; } 2> /dev/null rm -rf "$tmp_dir" if [[ $id ]];then info "Deleting container" docker rm -vf "$id" > /dev/null fi } # Copy goss & any config into a folder which then gets mounted as a volume # Run the container and perform the checks setup_container(){ info "Setting up test dir" cp "${GOSS_PATH}" "$tmp_dir/goss" chmod 755 "$tmp_dir/goss" [[ -e "${GOSS_FILES_PATH}/goss.yaml" ]] && cp "${GOSS_FILES_PATH}/goss.yaml" "$tmp_dir" [[ -e "${GOSS_FILES_PATH}/goss_wait.yaml" ]] && cp "${GOSS_FILES_PATH}/goss_wait.yaml" "$tmp_dir" [[ ! -z "${GOSS_VARS}" ]] && [[ -e "${GOSS_FILES_PATH}/${GOSS_VARS}" ]] && cp "${GOSS_FILES_PATH}/${GOSS_VARS}" "$tmp_dir" # copy the Dockerfile if path has been provided [[ ! -z "${3}" ]] && [[ "${3}" == *"Dockerfile"* ]] && cp "${3}" "$tmp_dir" info "Setup complete" # Switch between mount or cp files strategy GOSS_FILES_STRATEGY=${GOSS_FILES_STRATEGY:="mount"} case "$GOSS_FILES_STRATEGY" in mount) info "Starting docker container" id=$(docker run -d -v "$tmp_dir:/goss:z" "${@:2}") docker logs -f "$id" > "$tmp_dir/docker_output.log" 2>&1 & ;; cp) info "Creating docker container" id=$(docker create ${@:2}) info "Copy goss files into container" docker cp $tmp_dir/. $id:/goss info "Starting docker container" docker start $id > /dev/null ;; *) error "Wrong goss files strategy used! Correct options are \"mount\" or \"cp\"." esac log_pid=$! info "Container ID: ${id:0:8}" } get_file_from_docker() { if docker exec "$id" sh -c "test -e $1" > /dev/null;then mkdir -p "${GOSS_FILES_PATH}" info "Copied '$1' from container to '${GOSS_FILES_PATH}'" docker cp "$id:$1" "${GOSS_FILES_PATH}" fi } # Main tmp_dir=$(mktemp -d /tmp/tmp.XXXXXXXXXX) chmod 777 "$tmp_dir" trap 'ret=$?;cleanup;exit $ret' EXIT GOSS_PATH="${GOSS_PATH:-$(which 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:-1.0} case "$1" in run) info "Run Docker tests" setup_container "$@" 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 "$id" sh -c "/goss/goss -g /goss/goss_wait.yaml validate $GOSS_WAIT_OPTS"; then error "goss_wait.yaml never passed" fi else if ! docker exec "$id" sh -c "/goss/goss -g /goss/goss_wait.yaml --vars='/goss/${GOSS_VARS}' validate $GOSS_WAIT_OPTS"; then error "goss_wait.yaml never passed" fi fi fi [[ $GOSS_SLEEP ]] && { info "Sleeping for $GOSS_SLEEP"; sleep "$GOSS_SLEEP"; } # info "Container health" # if ! docker top $id; then # docker logs $id # fi info "Running Tests" if [[ -z "${GOSS_VARS}" ]]; then docker exec "$id" sh -c "/goss/goss -g /goss/goss.yaml validate $GOSS_OPTS" else docker exec "$id" sh -c "/goss/goss -g /goss/goss.yaml --vars='/goss/${GOSS_VARS}' validate $GOSS_OPTS" fi ;; dockerfile) info "Run Dockerfile tests" setup_container "$@" docker exec "$id" sh -c "cat /goss/goss.yaml" docker exec "$id" sh -c "/goss/goss -g /goss/goss.yaml validate $GOSS_OPTS" ;; edit) setup_container "$@" info "Run goss add/autoadd to add resources" docker exec -it "$id" sh -c 'cd /goss; PATH="/goss:$PATH" exec sh' get_file_from_docker "/goss/goss.yaml" get_file_from_docker "/goss/goss_wait.yaml" [[ ! -z "${GOSS_VARS}" ]] && get_file_from_docker "/goss/${GOSS_VARS}" ;; *) error "$USAGE" esac