183 lines
5.7 KiB
Bash
Executable file
183 lines
5.7 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# This script is used to build the OpenShift Docker images.
|
|
#
|
|
# OS - Specifies distribution - "rhel7", "centos7" or "fedora"
|
|
# VERSION - Specifies the image version - (must match with subdirectory in repo)
|
|
# VERSIONS - Must be set to a list with possible versions (subdirectories)
|
|
|
|
set -e
|
|
|
|
script_name=$(readlink -f "$0")
|
|
script_dir=$(dirname "$script_name")
|
|
|
|
OS=${1-$OS}
|
|
VERSION=${2-$VERSION}
|
|
|
|
error() { echo "ERROR: $*" ; false ; }
|
|
|
|
|
|
# _parse_output_inner
|
|
# -------------------
|
|
# Helper function for 'parse_output'.
|
|
# We need to avoid case statements in $() for older Bash versions (per issue
|
|
# postgresql-container#35, mac ships with 3.2).
|
|
# Example of problematic statement: echo $(case i in i) echo i;; esac)
|
|
_parse_output_inner ()
|
|
{
|
|
set -o pipefail
|
|
{
|
|
case $stream in
|
|
stdout|1|"")
|
|
eval "$command" | tee >(cat - >&"$stdout_fd")
|
|
;;
|
|
stderr|2)
|
|
set +x # avoid stderr pollution
|
|
eval "$command" {free_fd}>&1 1>&"$stdout_fd" 2>&"$free_fd" | tee >(cat - >&"$stderr_fd")
|
|
;;
|
|
esac
|
|
# Inherit correct exit status.
|
|
(exit "${PIPESTATUS[0]}")
|
|
} | eval "$filter"
|
|
}
|
|
|
|
|
|
# parse_output COMMAND FILTER_COMMAND OUTVAR [STREAM={stderr|stdout}]
|
|
# -------------------------------------------------------------------
|
|
# Parse standard (error) output of COMMAND with FILTER_COMMAND and store the
|
|
# output into variable named OUTVAR. STREAM might be 'stdout' or 'stderr',
|
|
# defaults to 'stdout'. The filtered output stays (live) printed to terminal.
|
|
# This method doesn't create any explicit temporary files.
|
|
# Defines:
|
|
# ${$OUTVAR}: Set to FILTER_COMMAND output.
|
|
parse_output ()
|
|
{
|
|
local command=$1 filter=$2 var=$3 stream=$4
|
|
local raw_output='' rc=0
|
|
{
|
|
# shellcheck disable=SC2034
|
|
raw_output=$(_parse_output_inner)
|
|
} {stdout_fd}>&1 {stderr_fd}>&2
|
|
rc=$?
|
|
eval "$var=\$raw_output"
|
|
(exit $rc)
|
|
}
|
|
|
|
# "best-effort" cleanup of previous image
|
|
function clean_image {
|
|
if test -f .image-id.raw; then
|
|
local previous_id
|
|
previous_id=$(cat .image-id.raw)
|
|
if test "$IMAGE_ID" != "$previous_id"; then
|
|
# Also remove squashed image since it will change anyway
|
|
docker rmi "$previous_id" "$(cat .image-id)" || :
|
|
rm -f ".image-id.raw" ".image-id" || :
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Perform docker build but append the LABEL with GIT commit id at the end
|
|
function docker_build_with_version {
|
|
local dockerfile="$1"
|
|
local exclude=.exclude-${OS}
|
|
if [ -e "$exclude" ]; then
|
|
echo "-> $exclude file exists for version $dir, skipping build."
|
|
clean_image
|
|
return
|
|
fi
|
|
if [ ! -e "$dockerfile" ]; then
|
|
echo "-> $dockerfile for version $dir does not exist, skipping build."
|
|
clean_image
|
|
return
|
|
fi
|
|
echo "-> Version ${dir}: building image from '${dockerfile}' ..."
|
|
|
|
git_version=$(git rev-parse --short HEAD)
|
|
BUILD_OPTIONS+=" --label io.openshift.builder-version=\"${git_version}\""
|
|
if [[ "${UPDATE_BASE}" == "1" ]]; then
|
|
BUILD_OPTIONS+=" --pull=true"
|
|
fi
|
|
if [ -n "$CUSTOM_REPO" ]; then
|
|
if [ -f "$CUSTOM_REPO" ]; then
|
|
BUILD_OPTIONS+=" -v $CUSTOM_REPO:/etc/yum.repos.d/sclorg_custom.repo:Z"
|
|
elif [ -d "$CUSTOM_REPO" ]; then
|
|
BUILD_OPTIONS+=" -v $CUSTOM_REPO:/etc/yum.repos.d/:Z"
|
|
else
|
|
echo "ERROR: file type not known: $CUSTOM_REPO" >&2
|
|
fi
|
|
fi
|
|
|
|
# shellcheck disable=SC2016
|
|
parse_output 'docker build '"$BUILD_OPTIONS"' -f "$dockerfile" "${DOCKER_BUILD_CONTEXT}"' \
|
|
"tail -n 1 | awk '/Successfully built|(^--> )?(Using cache )?[a-fA-F0-9]+$/{print \$NF}'" \
|
|
IMAGE_ID
|
|
clean_image
|
|
echo "$IMAGE_ID" > .image-id.raw
|
|
|
|
squash "${dockerfile}"
|
|
echo "$IMAGE_ID" > .image-id
|
|
}
|
|
|
|
# squash DOCKERFILE
|
|
# -----------------
|
|
# Use python library docker_squash[1] and squash the result image
|
|
# when necessary.
|
|
# [1] https://github.com/goldmann/docker-squash
|
|
# Reads:
|
|
# $IMAGE_ID
|
|
# Sets:
|
|
# $IMAGE_ID
|
|
squash ()
|
|
{
|
|
local base squashed_from squashed='' unsquashed=$IMAGE_ID
|
|
test "$SKIP_SQUASH" = 1 && return 0
|
|
|
|
if test -f .image-id.squashed; then
|
|
squashed=$(cat .image-id.squashed)
|
|
# We (maybe) already have squashed file.
|
|
if test -f .image-id.squashed_from; then
|
|
squashed_from=$(cat .image-id.squashed_from)
|
|
if test "$squashed_from" = "$IMAGE_ID"; then
|
|
# $squashed is up2date
|
|
IMAGE_ID=$squashed
|
|
echo "Image '$unsquashed' already squashed as '$squashed'"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# We are going to squash now, so if there's existing squashed image, try
|
|
# to do the best-effort 'rmi' to not waste memory unnecessarily.
|
|
docker rmi "$squashed" || :
|
|
fi
|
|
|
|
base=$(awk '/^FROM/{print $2}' "$1")
|
|
|
|
echo "Squashing the image '$unsquashed' from '$base' layer."
|
|
IMAGE_ID=$("${PYTHON-python3}" "$script_dir"/squash.py "$unsquashed" "$base")
|
|
|
|
echo "Squashed as '$IMAGE_ID'."
|
|
|
|
echo "$unsquashed" > .image-id.squashed_from
|
|
echo "$IMAGE_ID" > .image-id.squashed
|
|
}
|
|
|
|
# Versions are stored in subdirectories. You can specify VERSION variable
|
|
# to build just one single version. By default we build all versions
|
|
dirs=${VERSION:-$VERSIONS}
|
|
|
|
for dir in ${dirs}; do
|
|
pushd "${dir}" > /dev/null
|
|
if [ "$OS" == "rhel8" ] || [ "$OS" == "rhel8-candidate" ]; then
|
|
docker_build_with_version Dockerfile.rhel8
|
|
elif [ "$OS" == "rhel7" ] || [ "$OS" == "rhel7-candidate" ]; then
|
|
docker_build_with_version Dockerfile.rhel7
|
|
elif [ "$OS" == "fedora" ] || [ "$OS" == "fedora-candidate" ]; then
|
|
docker_build_with_version Dockerfile.fedora
|
|
elif [ "$OS" == "centos6" ] || [ "$OS" == "centos6-candidate" ]; then
|
|
docker_build_with_version Dockerfile.centos6
|
|
else
|
|
docker_build_with_version Dockerfile
|
|
fi
|
|
|
|
popd > /dev/null
|
|
done
|