Skip to content

Instantly share code, notes, and snippets.

@terabyte
Created September 12, 2019 18:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save terabyte/bc44d11efcbba8c7223192546ed1d36e to your computer and use it in GitHub Desktop.
Save terabyte/bc44d11efcbba8c7223192546ed1d36e to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Copyright (c) 2017 Cloudera, Inc. All rights reserved.
set -exo pipefail
# Usage: ./docker.sh
# Usage: ./docker.sh test/test.sh
# Usage: INTERACTIVE=1 ./docker.sh
# This script invokes the docker container, does the necessary contortions to
# ensure the external user matches the internal user, maps in the kitchen/tools
# repo, and then runs the given script (or test/test.sh by default).
KITCHEN_TOOLS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
DEFAULT_SCRIPT="test/test.sh"
SCRIPT_TO_RUN="$DEFAULT_SCRIPT"
if [[ -f "$KITCHEN_TOOLS_DIR/$1" ]]; then
if [[ -x "$KITCHEN_TOOLS_DIR/$1" ]]; then
# if the argument is a file and executable, run it, otherwise use default
# this enables testing a specific entrypoint
SCRIPT_TO_RUN="$1"
shift
fi
fi
echo "Invoking script $KITCHEN_TOOLS_DIR/$SCRIPT_TO_RUN in docker..."
# ensure docker exists on our path
DOCKER_BIN="$(command -v docker)"
MY_UID="$(id -u)"
MY_GID="$(id -g)"
if [[ -z "$MY_GID" ]]; then
# I've seen this happen on macos, and it may occur in other circumstances as well?
echo "WARNING: Couldn't determine GID, using UID as GID"
MY_GID=$MY_UID # probably?
fi
# allow developers to use the cache for local development, but default to not
# using it because it is more correct.
if [[ -z "$DOCKER_USE_CACHE" ]]; then
DOCKER_NO_CACHE="true"
else
DOCKER_NO_CACHE="false"
fi
"$DOCKER_BIN" build --no-cache=$DOCKER_NO_CACHE -f "$KITCHEN_TOOLS_DIR/test/Dockerfile" "$KITCHEN_TOOLS_DIR" | tee "$KITCHEN_TOOLS_DIR/test/docker.log"
IMAGE="$(grep "^Successfully built" "$KITCHEN_TOOLS_DIR/test/docker.log" | cut -d' ' -f3)"
# it is bad practice for a build to rely upon or alter the user's homedir, but
# many tools do write to or read from caches in the user's homedir, including
# maven. We avoid this by creating an empty home dir for the user and map it in.
#
# The second try in the line below is because mktemp has different args on mac os
TMP_USER_HOME="$(mktemp -d 2>/dev/null || mktemp -d -t 'kt_docker_tmp')"
function cleanup() {
rm -rf "$TMP_USER_HOME"
}
trap cleanup EXIT
# PRO TIP: Did you know that maven (and possibly other java things) IGNORE $HOME and instead read /etc/passwd?
# For this reason, we can't just leak the hosts's /etc/passwd into the container, we need to control it.
# The host's version of these files is probably not correct either, so we grab
# the version from the container, remove the current user/group, then add in a
# version which we know is correct. This is similar to what we do in Cauldron,
# we grab the container's /etc/passwd and /etc/group and modify them and
# overwrite them into the container.
NEWPW="$KITCHEN_TOOLS_DIR/test/.passwd"
NEWGRP="$KITCHEN_TOOLS_DIR/test/.group"
"$DOCKER_BIN" run "$IMAGE" /bin/bash -c "cat /etc/passwd" | grep -v "^$USER" > "$NEWPW"
"$DOCKER_BIN" run "$IMAGE" /bin/bash -c "cat /etc/group" | grep -v "^$USER" > "$NEWGRP"
echo "${USER}:x:${MY_UID}:${MY_GID}:Test User,,,:/home/${USER}:/bin/bash" >> "$NEWPW"
echo "${USER}:x:${MY_GID}:${USER}" >> "$NEWGRP"
# NOTE: docs encourage use of --mount over --volume, but the version of docker
# in our images is too old to support --mount.
# TODO: docker copies the files (passwd, group) out of the image, edits them,
# then maps them back in. We should do that, probably reusing the code from
# cdh/cdh, but for now, this suffices.
MOUNTS=(
-v "$TMP_USER_HOME:/home/$USER"
-v "$NEWPW:/etc/passwd:ro"
-v "$NEWGRP:/etc/group:ro"
-v /etc/localtime:/etc/localtime:ro
-v "$KITCHEN_TOOLS_DIR:/kitchen-tools"
)
THIS_UID="$(id -u)"
THIS_GID="$(id -g)"
if [[ -z "$THIS_GID" ]]; then
# needed on macos
THIS_GID="$THIS_UID"
fi
if [[ -n "$INTERACTIVE" ]]; then
echo "Running bash in interactive mode. The script that would have been run is: /kitchen-tools/$SCRIPT_TO_RUN"
"$DOCKER_BIN" run -i -t "${MOUNTS[@]}" -u "$MY_UID:$MY_GID" -e USER="$USER" -e HOME="/home/$USER" -e BUILD_URL="$BUILD_URL" "$IMAGE" /bin/bash
else
"$DOCKER_BIN" run "${MOUNTS[@]}" -u "$MY_UID:$MY_GID" -e USER="$USER" -e HOME="/home/$USER" -e BUILD_URL="$BUILD_URL" "$IMAGE" "/kitchen-tools/$SCRIPT_TO_RUN" "$@"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment