#!/bin/bash if [[ -f ~/.config/scylladb/dbuild ]]; then . ~/.config/scylladb/dbuild fi function die () { msg="$1" if [[ -n "$msg" ]]; then echo "$(basename $0): $msg." 1>&2 fi cat <&2 Run \`$0 --help' to print the full help message. EOF exit 1 } 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 <&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 } 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 --pids-limit -1 ) 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") # --pids-limit is not supported on podman with cgroupsv1 # detection code from # https://unix.stackexchange.com/questions/617764/how-do-i-check-if-system-is-using-cgroupv1 if grep -q 'cgroup2.*/sys/fs/cgroup ' /proc/mounts; then docker_common_args+=( --pids-limit -1 --annotation run.oci.keep_original_groups=1 ) fi # if --pids-limit is not supported, add # [containers] # pids_limit = 0 # # to /etc/containers/containers.conf 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+=( --security-opt seccomp=unconfined \ --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="$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 $tool 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"