blob: 35a5e96266911ad71d59cb2b3a63e3e9f9bb82e0 (
plain)
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
#!/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 print_parseable_summary {
printf "{"
for image in "${!status[@]}"; do
printf "'$image':'${status[$image]}',"
done
printf "}"
}
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:,testmode -- "$@")
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/}
;;
(--testmode)
TESTMODE=1
ARGS=${ARGS/\-\-testmode/}
;;
(--) 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
[ -n "$TESTMODE" ] && print_parseable_summary
rm -rf $WORKDIR
|