3 # Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
5 # Author: Loic Dachary <loic@dachary.org>
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)
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.
17 function get_image_name
() {
21 echo ceph-
$os_type-$os_version-$USER
24 function setup_container
() {
29 local image
=$
(get_image_name
$os_type $os_version)
31 if docker images
$image |
grep --quiet "^$image " ; then
32 eval touch --date=$
(docker inspect
$image | jq
'.[0].Created') $image
33 found
=$
(find -L test
/$os_type-$os_version/* -newer $image)
35 if test -n "$found" ; then
44 # replace environment variables %%FOO%% with their content
47 cp --dereference --recursive test
/$os_type-$os_version dockerfile
48 os_version
=$os_version user_id
=$
(id
-u) \
49 perl
-p -e 's/%%(\w+)%%/$ENV{$1}/g' \
50 dockerfile
/Dockerfile.
in > dockerfile
/Dockerfile
51 docker
$opts build
--tag=$image dockerfile
56 function get_upstream
() {
57 git rev-parse
--show-toplevel
60 function get_downstream
() {
64 local image
=$
(get_image_name
$os_type $os_version)
65 local upstream
=$
(get_upstream
)
66 local dir
=$
(dirname $upstream)
70 function setup_downstream
() {
75 local image
=$
(get_image_name
$os_type $os_version)
76 local upstream
=$
(get_upstream
)
77 local dir
=$
(dirname $upstream)
78 local downstream
=$
(get_downstream
$os_type $os_version)
82 if ! test -d $downstream ; then
83 # Inspired by https://github.com/git/git/blob/master/contrib/workdir/git-new-workdir
84 mkdir
-p $downstream/.git ||
return 1
85 for x
in config refs logs
/refs objects info hooks packed-refs remotes rr-cache
89 mkdir
-p "$downstream/.git/$x"
92 ln -s "$upstream/.git/$x" "$downstream/.git/$x"
94 cp "$upstream/.git/HEAD" "$downstream/.git/HEAD"
97 git
reset --hard $ref ||
return 1
98 git submodule sync
--recursive ||
return 1
99 git submodule update
--force --init --recursive ||
return 1
103 function run_in_docker
() {
114 setup_downstream
$os_type $os_version $ref ||
return 1
115 setup_container
$os_type $os_version "$opts" ||
return 1
116 local downstream
=$
(get_downstream
$os_type $os_version)
117 local image
=$
(get_image_name
$os_type $os_version)
118 local upstream
=$
(get_upstream
)
120 mkdir
-p $HOME/.ccache
121 ccache
="--volume $HOME/.ccache:$HOME/.ccache"
123 local cmd
="docker run $opts --rm --name $image --privileged $ccache"
124 cmd
+=" --volume $downstream:$downstream"
125 cmd
+=" --volume $upstream:$upstream"
127 if test "$script" = "SHELL" ; then
128 $cmd --tty --interactive --workdir $downstream $user $image bash
130 if ! $cmd --workdir $downstream $user $image "$@" ; then
137 function remove_all
() {
140 local image
=$
(get_image_name
$os_type $os_version)
148 Run commands within Ceph sources, in a docker container
149 $0 [options] command args ...
151 [-h|--help] display usage
152 [--verbose] trace all shell lines
154 [--os-type type] docker image repository (centos, ubuntu, etc.)
156 [--os-version version] docker image tag (7 for centos, 16.04 for ubuntu, etc.)
158 [--ref gitref] git reset --hard gitref before running the command
159 (defaults to git rev-parse HEAD)
160 [--all types+versions] list of docker image repositories and tags
162 [--shell] run an interactive shell in the container
163 [--remove-all] remove the container and the image for the specified types+versions
165 [--opts options] run the contain with 'options'
167 docker-test.sh must be run from a Ceph clone and it will run the
168 command in a container, using a copy of the clone so that long running
169 commands such as make check are not disturbed while development
170 continues. Here is a sample use case including an interactive session
171 and running a unit test:
174 Description: Ubuntu Xenial Xerus (development branch)
175 $ test/docker-test.sh --os-type centos --os-version 7 --shell
176 HEAD is now at 1caee81 autotools: add --enable-docker
178 /srv/ceph/ceph-centos-7
179 bash-4.2$ lsb_release -d
180 Description: CentOS Linux release 7.0.1406 (Core)
182 $ time test/docker-test.sh --os-type centos --os-version 7 unittest_str_map
183 HEAD is now at 1caee81 autotools: add --enable-docker
184 Running main() from gtest_main.cc
185 [==========] Running 2 tests from 1 test case.
186 [----------] Global test environment set-up.
187 [----------] 2 tests from str_map
189 [ OK ] str_map.json (1 ms)
190 [ RUN ] str_map.plaintext
191 [ OK ] str_map.plaintext (0 ms)
192 [----------] 2 tests from str_map (1 ms total)
194 [----------] Global test environment tear-down
195 [==========] 2 tests from 1 test case ran. (1 ms total)
202 The --all argument is a bash associative array literal listing the
203 operating system version for each operating system type. For instance
205 docker-test.sh --all '([ubuntu]="16.04 17.04" [centos]="7")'
207 is strictly equivalent to
209 docker-test.sh --os-type ubuntu --os-version 16.04
210 docker-test.sh --os-type ubuntu --os-version 17.04
211 docker-test.sh --os-type centos --os-version 7
213 The --os-type and --os-version must be exactly as displayed by docker images:
216 REPOSITORY TAG IMAGE ID ...
217 centos 7 87e5b6b3ccc1 ...
218 ubuntu 16.04 6b4e8a7373fe ...
220 The --os-type value can be any string in the REPOSITORY column, the --os-version
221 can be any string in the TAG column.
223 The --shell and --remove actions are mutually exclusive.
225 Run make check in centos 7
226 docker-test.sh --os-type centos --os-version 7 -- make check
228 Run make check on a giant
229 docker-test.sh --ref giant -- make check
231 Run an interactive shell and set resolv.conf to use 172.17.42.1
232 docker-test.sh --opts --dns=172.17.42.1 --shell
234 Run make check on centos 7, ubuntu 16.04 and ubuntu 17.04
235 docker-test.sh --all '([ubuntu]="16.04 17.04" [centos]="7")' -- make check
239 function main_docker
() {
240 if ! docker ps
> /dev
/null
2>&1 ; then
241 echo "docker not available: $0"
246 temp
=$
(getopt
-o scht
:v
:o
:a
:r
: --long remove-all
,verbose
,shell
,help,os-type
:,os-version
:,opts
:,all
:,ref
: -n $0 -- "$@") ||
return 1
251 local os_version
=16.04
256 local ref
=$
(git rev-parse HEAD
)
266 PS4
='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: '
302 echo "unexpected argument $1"
308 if test -z "$all" ; then
309 all
="([$os_type]=\"$os_version\")"
312 declare -A os_type2versions
313 eval os_type2versions
="$all"
315 for os_type
in ${!os_type2versions[@]} ; do
316 for os_version
in ${os_type2versions[$os_type]} ; do
318 remove_all
$os_type $os_version ||
return 1
320 run_in_docker
$os_type $os_version $ref "$opts" SHELL ||
return 1
322 run_in_docker
$os_type $os_version $ref "$opts" "$@" ||
return 1