forked from sclorg/container-common-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.sh
executable file
·183 lines (158 loc) · 5.58 KB
/
build.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/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}
DOCKERFILE_PATH=""
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
{
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 [ ! -z "$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
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" -o "$OS" == "rhel8-candidate" ]; then
docker_build_with_version Dockerfile.rhel8
elif [ "$OS" == "rhel7" -o "$OS" == "rhel7-candidate" ]; then
docker_build_with_version Dockerfile.rhel7
elif [ "$OS" == "fedora" -o "$OS" == "fedora-candidate" ]; then
docker_build_with_version Dockerfile.fedora
elif [ "$OS" == "centos6" -o "$OS" == "centos6-candidate" ]; then
docker_build_with_version Dockerfile.centos6
else
docker_build_with_version Dockerfile
fi
popd > /dev/null
done