kolla-ansible/tools/build-all-docker-images
Martin André 047683d12c Initial support for taggable dependencies
Introduce a new --no-use-released-parent option to `build-docker-image`
that allows specifying whether the parent image uses the same tag as
the one that's currently build or the release tag.

Default is to use the release tag for parent image, however
`build-all-docker-images` script forces it to be the current tag.

Change to Dockerfile is coming next.

Change-Id: Ief11c9abb722c181ca85f38ee11800dbf4332a5f
2015-05-05 12:45:11 +09:00

187 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Depends on bash 4 and gawk
TOPDIR=$(git rev-parse --show-toplevel)
# Work in a temp dir so that developers can continue working while a build is
# in progress
WORKDIR=$(mktemp -d /tmp/kolla-workdir.XXXXXXXXXX)
# Remove $WORKDIR otherwise $TOPDIR is copied *inside* of it
rm -rf $WORKDIR
cp -aL "$TOPDIR" $WORKDIR
DOCKERDIR="$WORKDIR/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=centos-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]#$WORKDIR/}"
}
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 --no-use-released-parent; 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 $WORKDIR/.buildconf ] && . $WORKDIR/.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]}' )
base_image=${base_image//%%KOLLA_NAMESPACE%%/$NAMESPACE}
base_image=${base_image//%%KOLLA_PREFIX%%/$PREFIX}
base_image=${base_image//:%%KOLLA_TAG%%/}
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
rm -rf $WORKDIR
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>
$($WORKDIR/tools/build-docker-image --help)
EOF
printf "%s\n" "${HELP/$WORKDIR\/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
rm -rf $WORKDIR