Files
scylladb/tools/toolchain/dbuild
Pekka Enberg d6354cb507 dbuild: Use host $USER and $HOME in Podman container
The "user.home" system property in JVM does not use the "HOME"
environment variable. This breaks Ant and Maven builds with Podman,
which attempts to look up the local Maven repository in "/root/.m2" when
building tools, for example:

  build.xml:757: /root/.m2/repository does not exist.

To fix the issue, let's bind-mount an /etc/passwd file, which contains
host username for UID 0, which ensures that Podman container $USER and $HOME
are the same as on the host.

Message-Id: <20200817085720.1756807-1-penberg@scylladb.com>
2020-08-17 13:46:28 +03:00

232 lines
5.3 KiB
Bash
Executable File

#!/bin/bash
if [[ -f ~/.config/scylladb/dbuild ]]; then
. ~/.config/scylladb/dbuild
fi
if which docker >/dev/null 2>&1 ; then
tool=${DBUILD_TOOL-docker}
elif which podman >/dev/null 2>&1 ; then
tool=${DBUILD_TOOL-podman}
else
die "Please make sure you install either podman or docker on this machine to run dbuild"
fi
here="$(realpath $(dirname "$0"))"
toplevel="$(realpath "$here/../..")"
group_args=()
docker_args=()
image="$(<"$here/image")"
for gid in $(id -G); do
group_args+=(--group-add "$gid")
done
interactive=
function help () {
cat <<EOF 1>&2
NAME
$(basename $0) - Run a command in scylla's frozen toolchain docker build image.
SYNOPSIS
$0 [OPTIONS --] [command [arg ...]]
DESCRIPTION
$(basename $0) is used mainly to build scylla in a docker image containing
a frozen version of the toolchain.
When no command is provided, $(basename $0) runs an interactive shell in
the docker instance. The image to use is taken by default from "$(dirname $0)/image".
It may be overriden using the --image option.
When providing docker options, the options list must be terminated with \`--'.
OPTIONS
-h | --help
Print this help message.
--image [IMAGE]
Use the specified docker IMAGE.
If omitted, list the available images using \`docker image ls'
-i | --interactive
Run an interactive session.
See \`docker help run' for available options.
ENVIRONMENT
SCYLLADB_DBUILD this variable, which can be a string or a bash
array, is prepended to the parmeters passed to
docker. This can be used to mount the ccache
directory (~/.ccache) and set up environment
variables (e.g. CCACHE_PREFIX)
If the file ~/.config/scylladb/dbuild exists, it is sourced. This can
be used to set up the SCYLLADB_DBUILD environment variable.
EOF
exit 0
}
function die () {
msg="$1"
if [[ -n "$msg" ]]; then
echo "$(basename $0): $msg." 1>&2
fi
cat <<EOF 1>&2
Run \`$0 --help' to print the full help message.
EOF
exit 1
}
if [[ $# -eq 0 ]]; then
interactive=y
docker_args=(-it)
elif [[ "$1" = -* ]]; then
while [[ "$1" != "--" && $# != 0 ]]; do
case "$1" in
-h|--help)
help
;;
--image)
image="$2"
shift 2
if [[ -z "$image" ]]; then
die "Expected docker image identifier to follow the --image option"
fi
if ! $tool image inspect "$image" >/dev/null && ! $tool image pull "$image"; then
die
fi
continue
;;
--*)
if [[ "$1" = --interactive || "$1" = --interactive=true ]]; then
interactive=y
fi
;;
-*)
if [[ "$1" = -*i* ]]; then
interactive=y
fi
;;
*)
;;
esac
docker_args+=("$1")
shift
done
if [[ "$1" != "--" ]]; then
die "Expected '--' to terminate docker flag list"
fi
shift
fi
if [[ $# != 0 ]]; then
args=("$@")
else
args=(/bin/bash -i)
fi
MAVEN_LOCAL_REPO="$HOME/.m2"
mkdir -p "$MAVEN_LOCAL_REPO"
is_podman="$($tool --help | grep -o podman)"
docker_common_args=()
docker_common_args+=("${SCYLLADB_DBUILD[@]}")
if [ -z "$is_podman" ]; then
unset TMP_PASSWD
docker_common_args+=(
-u "$(id -u):$(id -g)"
"${group_args[@]}"
-v /etc/passwd:/etc/passwd:ro
-v /etc/group:/etc/group:ro
)
else
TMP_PASSWD=$(mktemp --tmpdir passwd.XXXXXX)
FULLNAME=$(getent passwd $USER | cut -d ':' -f 5)
echo "$USER:x:0:0:$FULLNAME:$HOME:/bin/bash" > "$TMP_PASSWD"
docker_common_args+=(-v "$TMP_PASSWD:/etc/passwd:ro")
fi
if [ "$PWD" != "$toplevel" ]; then
docker_common_args+=(-v "$toplevel:$toplevel:z")
fi
# podman cannot relabel system directories like /tmp, but it can
# relable directories we own, so we map a temporary directory to /tmp
tmpdir=$(mktemp -d)
docker_common_args+=(
--pids-limit -1 \
--network host \
--cap-add SYS_PTRACE \
-v "$PWD:$PWD:z" \
-v "$tmpdir:/tmp:z" \
-v "$MAVEN_LOCAL_REPO:$MAVEN_LOCAL_REPO:z" \
-v /etc/localtime:/etc/localtime:ro \
-w "$PWD" \
-e HOME \
"${docker_args[@]}" \
"$image" \
"${args[@]}"
)
cleanup() {
rm -rf "$tmpdir"
if [ -v TMP_PASSWD ]; then
rm -f "$TMP_PASSWD"
fi
}
if [[ -n "$interactive" || -n "$is_podman" ]]; then
# If --interactive was given on the command line, we can't run in detached mode
# as it will be impossible to interact with the container.
# We also avoid detached mode with podman, which doesn't need it
# (it does not proxy SIGTERM) and doesn't work well with it.
$tool run --rm "${docker_common_args[@]}"
ret=$?
cleanup
exit $ret
fi
container=$(
$tool run \
"--detach=true" \
"${docker_common_args[@]}"
)
kill_it() {
if [[ -n "$container" ]]; then
docker rm -f "$container" > /dev/null
container=
fi
cleanup
}
trap kill_it SIGTERM SIGINT SIGHUP EXIT
$tool logs --follow "$container"
if [[ -n "$container" ]]; then
exitcode="$($tool wait "$container")"
else
exitcode=99
fi
kill_it
trap - SIGTERM SIGINT SIGHUP EXIT
# after "docker kill", docker wait will not print anything
[[ -z "$exitcode" ]] && exitcode=1
exit "$exitcode"