3 # Copyright (c) 2020 Cisco and/or its affiliates.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
19 # Log all output to stdout & stderr to a log file
20 logname="/tmp/$(basename $0).$(date +%Y_%m_%d_%H%M%S).log"
21 echo -e "\n*** Logging output to $logname ***\n"
22 exec > >(tee -a $logname) 2>&1
24 export CIMAN_DOCKER_SCRIPTS=${CIMAN_DOCKER_SCRIPTS:-"$(dirname $BASH_SOURCE)"}
25 . $CIMAN_DOCKER_SCRIPTS/lib_common.sh
28 long_bar="################################################################"
39 image_realname_prod=""
40 image_realname_prev=""
54 local script="$(basename $0)"
56 echo "Usage: $script r[evert] <prod image>"
57 echo " $script p[romote] <new image> [<new image>]"
58 echo " $script i[nspect] <prod image>"
60 echo " revert: swaps 'prod-<arch>' and 'prod-prev-<arch>' images"
61 echo " <prod image>: e.g. fdiotools/builder-ubuntu1804:prod-x86_64"
63 echo " promote: moves 'prod-<arch>' image to 'prod-prev-<arch>' tag and"
64 echo " tags <new image> with 'prod-<arch>'"
65 echo " <new image>: e.g. fdiotools/builder-ubuntu1804:2020_09_23_151655-x86_64"
66 echo " inspect: prints out all tags for prod-<arch> and prod-prev-<arch>"
72 echo -e "\n$long_bar\n"
73 echo "To restore tags to original state, issue the following command:"
74 echo -e "\n$restore_cmd\n\n$long_bar\n"
79 for image in "$@" ; do
81 echo "Pushing '$image' to docker hub..."
82 if ! docker push $image ; then
83 echo "ERROR: 'docker push $image' failed!"
90 image_user="$(echo $1 | cut -d'/' -f1)"
91 image_repo="$(echo $1 | cut -d'/' -f2 | cut -d':' -f1)"
92 local tag="$(echo $1 | cut -d':' -f2)"
93 image_version="$(echo $tag | cut -d'-' -f1)"
94 image_arch="$(echo $tag | sed -e s/$image_version-//)"
95 image_name_new="${image_user}/${image_repo}:${image_version}-${image_arch}"
96 if [ "$1" != "$image_name_new" ] ; then
97 echo "ERROR: Image name parsing failed: $1 != '$image_name_new'"
100 if [[ "$image_version" =~ "prod" ]] ; then
103 image_name_prod="${image_user}/${image_repo}:prod-${image_arch}"
104 image_name_prev="${image_user}/${image_repo}:prod-prev-${image_arch}"
107 format_image_tags() {
108 # Note: 'grep $image_arch' & grep -v 'prod-curr' is required due to a
109 # bug in docker hub which returns old tags which were deleted via
110 # the webUI, but are still retrieved by 'docker pull -a'
111 image_tags="$(docker images | grep $1 | grep $image_arch | grep -v prod-curr | sort -r | mawk '{print $1":"$2}' | tr '\n' ' ')"
112 image_realname="$(docker images | grep $1 | grep $image_arch | sort -r | grep -v prod | mawk '{print $1":"$2}')"
115 get_image_id_tags() {
116 for image in "$image_name_new" "$image_name_prod" "$image_name_prev" ; do
117 if [ -z "$image" ] ; then
120 # ensure image exists
122 local image_found="$(docker images | mawk '{print $1":"$2}' | grep $image)"
124 if [ -z "$image_found" ] ; then
125 if [ "$image" = "$image_name_prev" ] ; then
126 if [ "$action" = "revert" ] ; then
127 echo "ERROR: Image '$image' not found!"
128 echo "Unable to revert production image '$image_name_prod'!"
134 echo "ERROR: Image '$image' not found!"
139 local id="$(docker image inspect $image | mawk -F':' '/Id/{print $3}')"
140 local digest="$(docker image inspect $image | grep -A1 RepoDigests | grep -v RepoDigests | mawk -F':' '{print $2}')"
143 if [ "$retval" -ne "0" ] ; then
144 echo "ERROR: Docker ID not found for '$image'!"
147 if [ "$image" = "$image_name_prod" ] ; then
148 docker_id_prod="${id::12}"
149 digest_prod="${digest::12}"
150 format_image_tags "$docker_id_prod"
151 image_tags_prod="$image_tags"
152 if [ -z "$image_realname_prod" ] ; then
153 image_realname_prod="$image_realname"
155 elif [ "$image" = "$image_name_prev" ] ; then
156 docker_id_prev="${id::12}"
157 digest_prev="${digest::12}"
158 format_image_tags "$docker_id_prev"
159 image_tags_prev="$image_tags"
160 if [ -z "$image_realname_prev" ] ; then
161 image_realname_prev="$image_realname"
164 docker_id_new="${id::12}"
165 digest_new="${digest::12}"
166 format_image_tags "$docker_id_new" "NEW"
167 image_tags_new="$image_tags"
170 if [ -z "$restore_cmd" ] ; then
171 restore_cmd="sudo $0 p $image_realname_prev $image_realname_prod"
175 get_all_tags_from_dockerhub() {
176 local dh_repo="$image_user/$image_repo"
177 echo -e "Pulling all tags from docker hub repo '$dh_repo':\n$long_bar"
178 if ! docker pull -a "$dh_repo" ; then
179 echo "ERROR: Repository '$dh_repo' not found on docker hub!"
185 verify_image_name() {
188 if [ "$image_user" != "fdiotools" ] ; then
189 image_not_found="true"
190 echo "ERROR: invalid user '$image_user' in '$image_name_new'!"
193 if [ -z "$image_not_found" ] \
194 && [ "$image_version" != "prod" ] \
195 && ! [[ "$image_version" =~ \
196 ^[0-9]{4}_[0-1][0-9]_[0-3][0-9]_[0-2][0-9][0-5][0-9][0-5][0-9]$ ]]
198 image_not_found="true"
199 echo "ERROR: invalid version '$image_version' in '$image_name_new'!"
202 if [ -z "$image_not_found" ] \
203 && ! [[ "$EXECUTOR_ARCHS" =~ .*"$image_arch".* ]] ; then
204 image_not_found="true"
205 echo "ERROR: invalid arch '$image_arch' in '$image_name_new'!"
207 if [ -n "$image_not_found" ] ; then
208 echo "ERROR: Invalid image '$image_name_new'!"
214 echo ">>> docker tag $1 $2"
219 if [ "$retval" -ne "0" ] ; then
220 echo "WARNING: 'docker tag $1 $2' failed!"
226 echo ">>> docker rmi $1"
230 if [ "$retval" -ne "0" ] ; then
231 echo "WARNING: 'docker rmi $1' failed!"
236 if [ -z "$2" ] ; then
237 echo "$1 Image Not Found"
240 echo "$1 (Id $2, Digest $3):"
247 echo -e "\n${1}Production Docker Images:"
249 if [ -n "$image_tags_new" ] ; then
250 print_image_list "NEW" "$docker_id_new" "$digest_new" "$image_tags_new"
253 print_image_list "prod-$image_arch" "$docker_id_prod" "$digest_prod" \
256 print_image_list "prod-prev-$image_arch" "$docker_id_prev" "$digest_prev" \
258 echo -e "$short_bar\n"
261 revert_prod_image() {
262 inspect_images "EXISTING "
263 docker_tag_image $docker_id_prod $image_name_prev
264 docker_tag_image $docker_id_prev $image_name_prod
266 inspect_images "REVERTED "
270 read -p "Push Reverted tags to '$image_user/$image_repo' (yes/no)? " yn
275 echo -e "\nABORTING REVERT!\n"
276 docker_tag_image $docker_id_prev $image_name_prod
277 docker_tag_image $docker_id_prod $image_name_prev
279 inspect_images "RESTORED LOCAL "
282 echo "Please answer yes or no." ;;
286 push_to_dockerhub $image_name_prev $image_name_prod
291 promote_new_image() {
292 inspect_images "EXISTING "
293 docker_tag_image $docker_id_prod $image_name_prev
294 docker_tag_image $docker_id_new $image_name_prod
296 inspect_images "PROMOTED "
300 read -p "Push promoted tags to '$image_user/$image_repo' (yes/no)? " yn
305 echo -e "\nABORTING PROMOTION!\n"
306 docker_tag_image $docker_id_prev $image_name_prod
307 local restore_both="$(echo $restore_cmd | mawk '{print $5}')"
308 if [[ -n "$restore_both" ]] ; then
309 docker_tag_image $image_realname_prev $image_name_prev
311 docker_rmi_tag $image_name_prev
316 inspect_images "RESTORED "
319 echo "Please answer yes or no." ;;
323 push_to_dockerhub $image_name_new $image_name_prev $image_name_prod
332 if [ "$num_args" -lt "1" ] ; then
339 if [ "$num_args" -ne "2" ] ; then
340 echo "ERROR: Invalid number of arguments: $#"
344 if [ "$num_args" -eq "2" ] || [ "$num_args" -eq "3" ] ; then
347 echo "ERROR: Invalid number of arguments: $#"
352 if [ "$num_args" -ne "2" ] ; then
353 echo "ERROR: Invalid number of arguments: $#"
357 echo "ERROR: Invalid option '$1'!"
361 docker login >& /dev/null
365 for image in "$@" ; do
366 parse_image_name "$image"
367 verify_image_name "$image"
368 get_all_tags_from_dockerhub
370 if [ "$action" = "promote" ] ; then
371 if [ -n "$image_name_new" ] ; then
374 echo "ERROR: No new image specified to promote!"
377 elif [ "$action" = "revert" ] ; then
378 if [ "$image_version" = "prod" ] ; then
381 echo "ERROR: Non-production image '$image' specified!"
385 if [ "$image_version" = "prod" ] ; then
388 echo "ERROR: Non-production image '$image' specified!"