Created
September 12, 2019 18:23
-
-
Save terabyte/bc44d11efcbba8c7223192546ed1d36e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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