#!/usr/bin/env bash # # Copyright (C) 2014, 2015 Red Hat # # Author: Loic Dachary # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Library Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library Public License for more details. # function get_image_name() { local os_type=$1 local os_version=$2 echo ceph-$os_type-$os_version-$USER } function setup_container() { local os_type=$1 local os_version=$2 local dockercmd=$3 local opts="$4" # rm not valid here opts=${opts//' --rm'}; local image=$(get_image_name $os_type $os_version) local build=true if $dockercmd images $image | grep --quiet "^$image " ; then eval touch --date=$($dockercmd inspect $image | jq '.[0].Created') $image found=$(find -L test/$os_type-$os_version/* -newer $image) rm $image if test -n "$found" ; then $dockercmd rmi $image else build=false fi fi if $build ; then # # In the dockerfile, # replace environment variables %%FOO%% with their content # rm -fr dockerfile cp --dereference --recursive test/$os_type-$os_version dockerfile os_version=$os_version user_id=$(id -u) \ perl -p -e 's/%%(\w+)%%/$ENV{$1}/g' \ dockerfile/Dockerfile.in > dockerfile/Dockerfile $dockercmd $opts build --tag=$image dockerfile rm -fr dockerfile fi } function get_upstream() { git rev-parse --show-toplevel } function get_downstream() { local os_type=$1 local os_version=$2 local image=$(get_image_name $os_type $os_version) local upstream=$(get_upstream) local dir=$(dirname $upstream) echo "$dir/$image" } function setup_downstream() { local os_type=$1 local os_version=$2 local ref=$3 local image=$(get_image_name $os_type $os_version) local upstream=$(get_upstream) local dir=$(dirname $upstream) local downstream=$(get_downstream $os_type $os_version) ( cd $dir if ! test -d $downstream ; then # Inspired by https://github.com/git/git/blob/master/contrib/workdir/git-new-workdir mkdir -p $downstream/.git || return 1 for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache do case $x in */*) mkdir -p "$downstream/.git/$x" ;; esac ln -s "$upstream/.git/$x" "$downstream/.git/$x" done cp "$upstream/.git/HEAD" "$downstream/.git/HEAD" fi cd $downstream git reset --hard $ref || return 1 git submodule sync --recursive || return 1 git submodule update --force --init --recursive || return 1 ) } function run_in_docker() { local os_type=$1 shift local os_version=$1 shift local ref=$1 shift local dockercmd=$1 shift local opts="$1" shift local script=$1 setup_downstream $os_type $os_version $ref || return 1 setup_container $os_type $os_version $dockercmd "$opts" || return 1 local downstream=$(get_downstream $os_type $os_version) local image=$(get_image_name $os_type $os_version) local upstream=$(get_upstream) local ccache mkdir -p $HOME/.ccache ccache="--volume $HOME/.ccache:$HOME/.ccache" user="--user $USER" local cmd="$dockercmd run $opts --name $image --privileged $ccache" cmd+=" --volume $downstream:$downstream" cmd+=" --volume $upstream:$upstream" if test "$dockercmd" = "podman" ; then cmd+=" --userns=keep-id" fi local status=0 if test "$script" = "SHELL" ; then echo Running: $cmd --tty --interactive --workdir $downstream $user $image bash $cmd --tty --interactive --workdir $downstream $user $image bash else echo Running: $cmd --workdir $downstream $user $image "$@" if ! $cmd --workdir $downstream $user $image "$@" ; then status=1 fi fi return $status } function remove_all() { local os_type=$1 local os_version=$2 local dockercmd=$3 local image=$(get_image_name $os_type $os_version) $dockercmd rm $image $dockercmd rmi $image } function usage() { cat < /dev/null; then dockercmd="podman" fi if ! $dockercmd ps > /dev/null 2>&1 ; then echo "docker not available: $0" return 0 fi local temp temp=$(getopt -o scht:v:o:a:r: --long remove-all,verbose,shell,no-rm,help,os-type:,os-version:,opts:,all:,ref: -n $0 -- "$@") || return 1 eval set -- "$temp" local os_type=ubuntu local os_version=16.04 local all local remove=false local shell=false local opts local ref=$(git rev-parse HEAD) local no-rm=false while true ; do case "$1" in --remove-all) remove=true shift ;; --verbose) set -xe PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: ' shift ;; -s|--shell) shell=true shift ;; -h|--help) usage return 0 ;; -t|--os-type) os_type=$2 shift 2 ;; -v|--os-version) os_version=$2 shift 2 ;; -o|--opts) opts="$2" shift 2 ;; -a|--all) all="$2" shift 2 ;; -r|--ref) ref="$2" shift 2 ;; --no-rm) no-rm=true shift ;; --) shift break ;; *) echo "unexpected argument $1" return 1 ;; esac done if test -z "$all" ; then all="([$os_type]=\"$os_version\")" fi declare -A os_type2versions eval os_type2versions="$all" if ! $no-rm ; then opts+=" --rm" fi for os_type in ${!os_type2versions[@]} ; do for os_version in ${os_type2versions[$os_type]} ; do if $remove ; then remove_all $os_type $os_version $dockercmd || return 1 elif $shell ; then run_in_docker $os_type $os_version $ref $dockercmd "$opts" SHELL || return 1 else run_in_docker $os_type $os_version $ref $dockercmd "$opts" "$@" || return 1 fi done done }