]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/docker-test-helper.sh
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / test / docker-test-helper.sh
CommitLineData
11fdf7f2 1#!/usr/bin/env bash
7c673cae
FG
2#
3# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
4#
5# Author: Loic Dachary <loic@dachary.org>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU Library Public License as published by
9# the Free Software Foundation; either version 2, or (at your option)
10# any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Library Public License for more details.
16#
17function get_image_name() {
18 local os_type=$1
19 local os_version=$2
20
21 echo ceph-$os_type-$os_version-$USER
22}
23
24function setup_container() {
25 local os_type=$1
26 local os_version=$2
f67539c2
TL
27 local dockercmd=$3
28 local opts="$4"
29
30 # rm not valid here
31 opts=${opts//' --rm'};
7c673cae
FG
32
33 local image=$(get_image_name $os_type $os_version)
34 local build=true
f67539c2
TL
35 if $dockercmd images $image | grep --quiet "^$image " ; then
36 eval touch --date=$($dockercmd inspect $image | jq '.[0].Created') $image
7c673cae
FG
37 found=$(find -L test/$os_type-$os_version/* -newer $image)
38 rm $image
39 if test -n "$found" ; then
f67539c2 40 $dockercmd rmi $image
7c673cae
FG
41 else
42 build=false
43 fi
44 fi
45 if $build ; then
46 #
47 # In the dockerfile,
48 # replace environment variables %%FOO%% with their content
49 #
50 rm -fr dockerfile
51 cp --dereference --recursive test/$os_type-$os_version dockerfile
52 os_version=$os_version user_id=$(id -u) \
53 perl -p -e 's/%%(\w+)%%/$ENV{$1}/g' \
54 dockerfile/Dockerfile.in > dockerfile/Dockerfile
f67539c2 55 $dockercmd $opts build --tag=$image dockerfile
7c673cae
FG
56 rm -fr dockerfile
57 fi
58}
59
60function get_upstream() {
61 git rev-parse --show-toplevel
62}
63
64function get_downstream() {
65 local os_type=$1
66 local os_version=$2
67
68 local image=$(get_image_name $os_type $os_version)
69 local upstream=$(get_upstream)
70 local dir=$(dirname $upstream)
71 echo "$dir/$image"
72}
73
74function setup_downstream() {
75 local os_type=$1
76 local os_version=$2
77 local ref=$3
78
79 local image=$(get_image_name $os_type $os_version)
80 local upstream=$(get_upstream)
81 local dir=$(dirname $upstream)
82 local downstream=$(get_downstream $os_type $os_version)
83
84 (
85 cd $dir
86 if ! test -d $downstream ; then
87 # Inspired by https://github.com/git/git/blob/master/contrib/workdir/git-new-workdir
88 mkdir -p $downstream/.git || return 1
89 for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache
90 do
91 case $x in
92 */*)
93 mkdir -p "$downstream/.git/$x"
94 ;;
95 esac
96 ln -s "$upstream/.git/$x" "$downstream/.git/$x"
7c673cae 97 done
11fdf7f2 98 cp "$upstream/.git/HEAD" "$downstream/.git/HEAD"
7c673cae
FG
99 fi
100 cd $downstream
101 git reset --hard $ref || return 1
102 git submodule sync --recursive || return 1
103 git submodule update --force --init --recursive || return 1
104 )
105}
106
107function run_in_docker() {
108 local os_type=$1
109 shift
110 local os_version=$1
111 shift
112 local ref=$1
113 shift
f67539c2
TL
114 local dockercmd=$1
115 shift
7c673cae
FG
116 local opts="$1"
117 shift
118 local script=$1
119
120 setup_downstream $os_type $os_version $ref || return 1
f67539c2 121 setup_container $os_type $os_version $dockercmd "$opts" || return 1
7c673cae
FG
122 local downstream=$(get_downstream $os_type $os_version)
123 local image=$(get_image_name $os_type $os_version)
124 local upstream=$(get_upstream)
125 local ccache
126 mkdir -p $HOME/.ccache
127 ccache="--volume $HOME/.ccache:$HOME/.ccache"
128 user="--user $USER"
f67539c2 129 local cmd="$dockercmd run $opts --name $image --privileged $ccache"
7c673cae
FG
130 cmd+=" --volume $downstream:$downstream"
131 cmd+=" --volume $upstream:$upstream"
f67539c2
TL
132 if test "$dockercmd" = "podman" ; then
133 cmd+=" --userns=keep-id"
134 fi
7c673cae
FG
135 local status=0
136 if test "$script" = "SHELL" ; then
f67539c2 137 echo Running: $cmd --tty --interactive --workdir $downstream $user $image bash
7c673cae
FG
138 $cmd --tty --interactive --workdir $downstream $user $image bash
139 else
f67539c2 140 echo Running: $cmd --workdir $downstream $user $image "$@"
7c673cae
FG
141 if ! $cmd --workdir $downstream $user $image "$@" ; then
142 status=1
143 fi
144 fi
145 return $status
146}
147
148function remove_all() {
149 local os_type=$1
150 local os_version=$2
f67539c2 151 local dockercmd=$3
7c673cae
FG
152 local image=$(get_image_name $os_type $os_version)
153
f67539c2
TL
154 $dockercmd rm $image
155 $dockercmd rmi $image
7c673cae
FG
156}
157
158function usage() {
159 cat <<EOF
f67539c2
TL
160Run commands within Ceph sources, in a container. Use podman if available,
161docker if not.
7c673cae
FG
162$0 [options] command args ...
163
164 [-h|--help] display usage
165 [--verbose] trace all shell lines
166
167 [--os-type type] docker image repository (centos, ubuntu, etc.)
168 (defaults to ubuntu)
11fdf7f2
TL
169 [--os-version version] docker image tag (7 for centos, 16.04 for ubuntu, etc.)
170 (defaults to 16.04)
7c673cae
FG
171 [--ref gitref] git reset --hard gitref before running the command
172 (defaults to git rev-parse HEAD)
173 [--all types+versions] list of docker image repositories and tags
174
175 [--shell] run an interactive shell in the container
176 [--remove-all] remove the container and the image for the specified types+versions
f67539c2 177 [--no-rm] don't remove the container when finished
7c673cae 178
f67539c2 179 [--opts options] run the container with 'options'
7c673cae
FG
180
181docker-test.sh must be run from a Ceph clone and it will run the
182command in a container, using a copy of the clone so that long running
183commands such as make check are not disturbed while development
184continues. Here is a sample use case including an interactive session
185and running a unit test:
186
187 $ lsb_release -d
11fdf7f2 188 Description: Ubuntu Xenial Xerus (development branch)
7c673cae
FG
189 $ test/docker-test.sh --os-type centos --os-version 7 --shell
190 HEAD is now at 1caee81 autotools: add --enable-docker
191 bash-4.2$ pwd
192 /srv/ceph/ceph-centos-7
193 bash-4.2$ lsb_release -d
194 Description: CentOS Linux release 7.0.1406 (Core)
195 bash-4.2$
196 $ time test/docker-test.sh --os-type centos --os-version 7 unittest_str_map
197 HEAD is now at 1caee81 autotools: add --enable-docker
198 Running main() from gtest_main.cc
199 [==========] Running 2 tests from 1 test case.
200 [----------] Global test environment set-up.
201 [----------] 2 tests from str_map
202 [ RUN ] str_map.json
203 [ OK ] str_map.json (1 ms)
204 [ RUN ] str_map.plaintext
205 [ OK ] str_map.plaintext (0 ms)
206 [----------] 2 tests from str_map (1 ms total)
207
208 [----------] Global test environment tear-down
209 [==========] 2 tests from 1 test case ran. (1 ms total)
210 [ PASSED ] 2 tests.
211
212 real 0m3.759s
213 user 0m0.074s
214 sys 0m0.051s
215
216The --all argument is a bash associative array literal listing the
217operating system version for each operating system type. For instance
218
11fdf7f2 219 docker-test.sh --all '([ubuntu]="16.04 17.04" [centos]="7")'
7c673cae
FG
220
221is strictly equivalent to
222
11fdf7f2
TL
223 docker-test.sh --os-type ubuntu --os-version 16.04
224 docker-test.sh --os-type ubuntu --os-version 17.04
7c673cae
FG
225 docker-test.sh --os-type centos --os-version 7
226
227The --os-type and --os-version must be exactly as displayed by docker images:
228
229 $ docker images
230 REPOSITORY TAG IMAGE ID ...
231 centos 7 87e5b6b3ccc1 ...
11fdf7f2 232 ubuntu 16.04 6b4e8a7373fe ...
7c673cae
FG
233
234The --os-type value can be any string in the REPOSITORY column, the --os-version
235can be any string in the TAG column.
236
237The --shell and --remove actions are mutually exclusive.
238
239Run make check in centos 7
240docker-test.sh --os-type centos --os-version 7 -- make check
241
242Run make check on a giant
243docker-test.sh --ref giant -- make check
244
245Run an interactive shell and set resolv.conf to use 172.17.42.1
246docker-test.sh --opts --dns=172.17.42.1 --shell
247
11fdf7f2
TL
248Run make check on centos 7, ubuntu 16.04 and ubuntu 17.04
249docker-test.sh --all '([ubuntu]="16.04 17.04" [centos]="7")' -- make check
7c673cae
FG
250EOF
251}
252
253function main_docker() {
f67539c2
TL
254 local dockercmd="docker"
255 if type podman > /dev/null; then
256 dockercmd="podman"
257 fi
258
259 if ! $dockercmd ps > /dev/null 2>&1 ; then
7c673cae
FG
260 echo "docker not available: $0"
261 return 0
262 fi
263
264 local temp
f67539c2 265 temp=$(getopt -o scht:v:o:a:r: --long remove-all,verbose,shell,no-rm,help,os-type:,os-version:,opts:,all:,ref: -n $0 -- "$@") || return 1
7c673cae
FG
266
267 eval set -- "$temp"
268
269 local os_type=ubuntu
11fdf7f2 270 local os_version=16.04
7c673cae
FG
271 local all
272 local remove=false
273 local shell=false
274 local opts
275 local ref=$(git rev-parse HEAD)
f67539c2 276 local no-rm=false
7c673cae
FG
277
278 while true ; do
279 case "$1" in
280 --remove-all)
281 remove=true
282 shift
283 ;;
284 --verbose)
285 set -xe
286 PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: '
287 shift
288 ;;
289 -s|--shell)
290 shell=true
291 shift
292 ;;
293 -h|--help)
294 usage
295 return 0
296 ;;
297 -t|--os-type)
298 os_type=$2
299 shift 2
300 ;;
301 -v|--os-version)
302 os_version=$2
303 shift 2
304 ;;
305 -o|--opts)
306 opts="$2"
307 shift 2
308 ;;
309 -a|--all)
310 all="$2"
311 shift 2
312 ;;
313 -r|--ref)
314 ref="$2"
315 shift 2
316 ;;
f67539c2
TL
317 --no-rm)
318 no-rm=true
319 shift
320 ;;
7c673cae
FG
321 --)
322 shift
323 break
324 ;;
325 *)
326 echo "unexpected argument $1"
327 return 1
328 ;;
329 esac
330 done
331
332 if test -z "$all" ; then
333 all="([$os_type]=\"$os_version\")"
334 fi
335
336 declare -A os_type2versions
337 eval os_type2versions="$all"
338
f67539c2
TL
339 if ! $no-rm ; then
340 opts+=" --rm"
341 fi
342
7c673cae
FG
343 for os_type in ${!os_type2versions[@]} ; do
344 for os_version in ${os_type2versions[$os_type]} ; do
345 if $remove ; then
f67539c2 346 remove_all $os_type $os_version $dockercmd || return 1
7c673cae 347 elif $shell ; then
f67539c2 348 run_in_docker $os_type $os_version $ref $dockercmd "$opts" SHELL || return 1
7c673cae 349 else
f67539c2 350 run_in_docker $os_type $os_version $ref $dockercmd "$opts" "$@" || return 1
7c673cae
FG
351 fi
352 done
353 done
354}