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
() {
31 opts
=${opts//' --rm'};
33 local image
=$
(get_image_name
$os_type $os_version)
35 if $dockercmd images
$image |
grep --quiet "^$image " ; then
36 eval touch --date=$
($dockercmd inspect
$image | jq
'.[0].Created') $image
37 found
=$
(find -L test
/$os_type-$os_version/* -newer $image)
39 if test -n "$found" ; then
48 # replace environment variables %%FOO%% with their content
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
55 $dockercmd $opts build
--tag=$image dockerfile
60 function get_upstream
() {
61 git rev-parse
--show-toplevel
64 function get_downstream
() {
68 local image
=$
(get_image_name
$os_type $os_version)
69 local upstream
=$
(get_upstream
)
70 local dir
=$
(dirname $upstream)
74 function setup_downstream
() {
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)
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
93 mkdir
-p "$downstream/.git/$x"
96 ln -s "$upstream/.git/$x" "$downstream/.git/$x"
98 cp "$upstream/.git/HEAD" "$downstream/.git/HEAD"
101 git
reset --hard $ref ||
return 1
102 git submodule sync
--recursive ||
return 1
103 git submodule update
--force --init --recursive ||
return 1
107 function run_in_docker
() {
120 setup_downstream
$os_type $os_version $ref ||
return 1
121 setup_container
$os_type $os_version $dockercmd "$opts" ||
return 1
122 local downstream
=$
(get_downstream
$os_type $os_version)
123 local image
=$
(get_image_name
$os_type $os_version)
124 local upstream
=$
(get_upstream
)
126 mkdir
-p $HOME/.ccache
127 ccache
="--volume $HOME/.ccache:$HOME/.ccache"
129 local cmd
="$dockercmd run $opts --name $image --privileged $ccache"
130 cmd
+=" --volume $downstream:$downstream"
131 cmd
+=" --volume $upstream:$upstream"
132 if test "$dockercmd" = "podman" ; then
133 cmd
+=" --userns=keep-id"
136 if test "$script" = "SHELL" ; then
137 echo Running
: $cmd --tty --interactive --workdir $downstream $user $image bash
138 $cmd --tty --interactive --workdir $downstream $user $image bash
140 echo Running
: $cmd --workdir $downstream $user $image "$@"
141 if ! $cmd --workdir $downstream $user $image "$@" ; then
148 function remove_all
() {
152 local image
=$
(get_image_name
$os_type $os_version)
155 $dockercmd rmi
$image
160 Run commands within Ceph sources, in a container. Use podman if available,
162 $0 [options] command args ...
164 [-h|--help] display usage
165 [--verbose] trace all shell lines
167 [--os-type type] docker image repository (centos, ubuntu, etc.)
169 [--os-version version] docker image tag (7 for centos, 16.04 for ubuntu, etc.)
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
175 [--shell] run an interactive shell in the container
176 [--remove-all] remove the container and the image for the specified types+versions
177 [--no-rm] don't remove the container when finished
179 [--opts options] run the container with 'options'
181 docker-test.sh must be run from a Ceph clone and it will run the
182 command in a container, using a copy of the clone so that long running
183 commands such as make check are not disturbed while development
184 continues. Here is a sample use case including an interactive session
185 and running a unit test:
187 $ grep PRETTY_NAME /etc/os-release
188 PRETTY_NAME="Ubuntu 16.04.7 LTS"
189 $ test/docker-test.sh --os-type centos --os-version 7 --shell
190 HEAD is now at 1caee81 autotools: add --enable-docker
192 /srv/ceph/ceph-centos-7
193 bash-4.2$ cat /etc/redhat-release
194 CentOS Linux release 7.6.1810 (Core)
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
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)
208 [----------] Global test environment tear-down
209 [==========] 2 tests from 1 test case ran. (1 ms total)
216 The --all argument is a bash associative array literal listing the
217 operating system version for each operating system type. For instance
219 docker-test.sh --all '([ubuntu]="16.04 17.04" [centos]="7")'
221 is strictly equivalent to
223 docker-test.sh --os-type ubuntu --os-version 16.04
224 docker-test.sh --os-type ubuntu --os-version 17.04
225 docker-test.sh --os-type centos --os-version 7
227 The --os-type and --os-version must be exactly as displayed by docker images:
230 REPOSITORY TAG IMAGE ID ...
231 centos 7 87e5b6b3ccc1 ...
232 ubuntu 16.04 6b4e8a7373fe ...
234 The --os-type value can be any string in the REPOSITORY column, the --os-version
235 can be any string in the TAG column.
237 The --shell and --remove actions are mutually exclusive.
239 Run make check in centos 7
240 docker-test.sh --os-type centos --os-version 7 -- make check
242 Run make check on a giant
243 docker-test.sh --ref giant -- make check
245 Run an interactive shell and set resolv.conf to use 172.17.42.1
246 docker-test.sh --opts --dns=172.17.42.1 --shell
248 Run make check on centos 7, ubuntu 16.04 and ubuntu 17.04
249 docker-test.sh --all '([ubuntu]="16.04 17.04" [centos]="7")' -- make check
253 function main_docker
() {
254 local dockercmd
="docker"
255 if type podman
> /dev
/null
; then
259 if ! $dockercmd ps
> /dev
/null
2>&1 ; then
260 echo "docker not available: $0"
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
270 local os_version
=16.04
275 local ref
=$
(git rev-parse HEAD
)
286 PS4
='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: '
326 echo "unexpected argument $1"
332 if test -z "$all" ; then
333 all
="([$os_type]=\"$os_version\")"
336 declare -A os_type2versions
337 eval os_type2versions
="$all"
343 for os_type
in ${!os_type2versions[@]} ; do
344 for os_version
in ${os_type2versions[$os_type]} ; do
346 remove_all
$os_type $os_version $dockercmd ||
return 1
348 run_in_docker
$os_type $os_version $ref $dockercmd "$opts" SHELL ||
return 1
350 run_in_docker
$os_type $os_version $ref $dockercmd "$opts" "$@" ||
return 1