kolla-ansible/tools/build-all-docker-images
Steven Dake cebbd9fb7b Quote array index with -n so -n works properly
For some reason -n doesn't work with arrays, probably becuase
the array has an entry by the array's indexed value is empty.

By quoting it we get it as one unit, which behaves as expected.

Change-Id: Ic3243d13d3f8fc9978c460f816e33ad348302d8e
2015-02-23 12:46:18 -07:00

176 lines
4.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Depends on bash 4 and gawk
TOPDIR=$(git rev-parse --show-toplevel)
DOCKERDIR="$TOPDIR/docker"
declare -A dependency
declare -A img_dirs
declare -A status
function info {
[[ -n $1 ]] && printf "%s\n" "$1"
}
function success {
[[ -n $1 ]] && printf "\033[00;32m%s\033[00m\n" "$1"
}
function warn {
[[ -n $1 ]] && printf "\033[00;31m%s\033[00m\n" "$1"
}
function set_defaults {
PREFIX=fedora-rdo-
NAMESPACE=kollaglue
}
function has_changed {
local image=$1
# Rebuild everything unless given git revision
# We don't really care about the order of the $FROM and $TO parameters, all
# we need is the list of changed files between the revisions, or HEAD if
# only one of them is specified
[[ -z $FROM && -z $TO ]] || git diff --name-only $FROM $TO | grep -q "${img_dirs[$image]#$TOPDIR/}"
}
function requires_build {
local image=$1
local dep=${dependency[$image]}
# An image requires a built if it meets the following conditions:
# - it has instructions to build the image
# - it hasn't been processed yet
# - its dependency was rebuilt or its build instruction was modified
[[ ${img_dirs[$image]} && -z ${status[$image]} ]] && \
([[ ${status[$dep]} == "rebuilt" ]] || has_changed $image)
}
function build_image {
local dir=$1
if [ -x "$dir/build" ]; then
printf "\n"
info "Building image in $dir"
if $dir/build $ARGS; then
success "Successfully built image in $dir"
status[$image]="rebuilt"
else
warn "Failed to build image in $dir"
status[$image]="fail"
fi
fi
}
function init_image {
local img_dir=$1
set_defaults
[ -f $TOPDIR/.buildconf ] && . $TOPDIR/.buildconf
[ -f $img_dir/.buildconf ] && . $img_dir/.buildconf
[ -n $FORCE_NAMESPACE ] && NAMESPACE=$FORCE_NAMESPACE
local image="${NAMESPACE:+${NAMESPACE}/}${PREFIX}${img_dir##*/}"
local base_image=$(cat $img_dir/Dockerfile | gawk 'match($0, /^\s*FROM\s+(\S+)/, matches) {print matches[1]}' )
img_dirs[$image]=$img_dir
dependency[$image]=$base_image
# Restore defaults to minimize risk of side effects
set_defaults
}
function process_image {
local image=$1
if [ -n "${dependency[$image]}" ]; then
process_image ${dependency[$image]}
fi
if requires_build $image; then
build_image ${img_dirs[$image]}
fi
if [ -z "${status[$image]}" ]; then
status[$image]="up-to-date"
fi
}
function print_summary {
printf "\nSummary\n=======\n"
for image in "${!status[@]}"; do
case "${status[$image]}" in
("fail") warn "Failed to process $image" ;;
("rebuilt") success "Rebuilt $image" ;;
(*) info "$image: ${status[$image]}" ;;
esac
done
}
function interrupted {
info "Interrupted..."
print_summary
exit 1
}
function usage () {
read -r -d '' HELP <<EOF
A wrapper to build-docker-image that build all images in order.
Options:
--from <git-revision>
--to <git-revision>
$($TOPDIR/tools/build-docker-image --help)
EOF
printf "%s\n" "${HELP/$TOPDIR\/tools\/build-docker-image/$0}"
}
trap 'interrupted' INT
ARGS=$@
PARSED_ARGS=$(getopt -q -o hn: -l help,namespace:,from:,to: -- "$@")
eval set -- "$PARSED_ARGS"
while :; do
case "$1" in
(--help|-h) usage
exit 0
;;
(--namespace|-n)
shift
FORCE_NAMESPACE="$1"
;;
(--from)
shift
FROM="$1"
ARGS=${ARGS/\-\-from*$FROM/}
;;
(--to)
shift
TO="$1"
ARGS=${ARGS/\-\-to*$TO/}
;;
(--) break
;;
esac
shift
done
# Do a first pass to find images to build and their dependencies
for dockerfile in $(find $DOCKERDIR -name Dockerfile); do
init_image $(dirname $dockerfile)
done
# Process all images
for image in "${!img_dirs[@]}"; do
process_image $image
done
print_summary