apache-ignite

Форк
0
678 строк · 24.3 Кб
1
#!/usr/bin/env bash
2

3
# Licensed to the Apache Software Foundation (ASF) under one or more
4
# contributor license agreements.  See the NOTICE file distributed with
5
# this work for additional information regarding copyright ownership.
6
# The ASF licenses this file to You under the Apache License, Version 2.0
7
# (the "License"); you may not use this file except in compliance with
8
# the License.  You may obtain a copy of the License at
9
#
10
#    http://www.apache.org/licenses/LICENSE-2.0
11
#
12
# Unless required by applicable law or agreed to in writing, software
13
# distributed under the License is distributed on an "AS IS" BASIS,
14
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
# See the License for the specific language governing permissions and
16
# limitations under the License.
17

18
#
19
# Ducker-Ignite: a tool for running Apache Ignite system tests inside Docker images.
20
#
21
# Note: this should be compatible with the version of bash that ships on most
22
# Macs, bash 3.2.57.
23
#
24

25
script_path="${0}"
26

27
# The absolute path to the directory which this script is in.  This will also be the directory
28
# which we run docker build from.
29
ducker_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
30

31
# The absolute path to the root Ignite directory
32
ignite_dir="$( cd "${ducker_dir}/../../../.." && pwd )"
33

34
# The memory consumption to allow during the docker build.
35
# This does not include swap.
36
docker_build_memory_limit="8000m"
37

38
# The maximum mmemory consumption to allow in containers.
39
docker_run_memory_limit="8000m"
40

41
# The default number of cluster nodes to bring up if a number is not specified.
42
default_num_nodes=4
43

44
# The default OpenJDK base image.
45
default_jdk="openjdk:8"
46

47
# The default ducker-ignite image name.
48
default_image_name="ducker-ignite"
49

50
# Display a usage message on the terminal and exit.
51
#
52
# $1: The exit status to use
53
usage() {
54
    local exit_status="${1}"
55
    cat <<EOF
56
ducker-ignite: a tool for running Apache Ignite tests inside Docker images.
57

58
Usage: ${script_path} [command] [options]
59

60
help|-h|--help
61
    Display this help message
62

63
build [-j|--jdk JDK] [-c|--context] [image-name]
64
    Build a docker image that represents ducker node. Image is tagged with specified ${image_name}.
65

66
    If --jdk is specified then we will use this argument as base image for ducker docker images.
67
    Otherwise ${default_jdk} is used.
68

69
    If --context is specified then build docker image from this path. Context directory must contain Dockerfile.
70

71
up [-n|--num-nodes NUM_NODES] [-f|--force] [docker-image]
72
        [-C|--custom-ducktape DIR] [-e|--expose-ports ports] [-j|--jdk JDK_VERSION]
73
        [--subnet SUBNET]
74
    Bring up a cluster with the specified amount of nodes (defaults to ${default_num_nodes}).
75
    The docker image name defaults to ${default_image_name}. If --force is specified, we will
76
    attempt to bring up an image even some parameters are not valid.
77

78
    If --custom-ducktape is specified, we will install the provided custom
79
    ducktape source code directory before bringing up the nodes.  The provided
80
    directory should be the ducktape git repo, not the ducktape installed module directory.
81

82
    if --expose-ports is specified then we will expose those ports to random ephemeral ports
83
    on the host. The argument can be a single port (like 5005), a port range like (5005-5009)
84
    or a combination of port/port-range separated by comma (like 2181,9092 or 2181,5005-5008).
85
    By default no port is exposed. See README.md for more detail on this option.
86

87
    If --jdk is specified then we will use this argument as base image for ducktest's docker images.
88
    Otherwise ${default_jdk} is used.
89

90
    If --subnet is specified then nodes are assigned IP addresses in this subnetwork. SUBNET is specified
91
    in the CIDR format and passed directly to the docker create network command.
92

93
test [test-name(s)]
94
    Run a test or set of tests inside the currently active Ducker nodes.
95
    For example, to run the system test produce_bench_test, you would run:
96
        ./tests/docker/ducker-ignite test ./tests/ignitetest/test/core/rebalance_test.py
97

98
ssh [node-name|user-name@node-name] [command]
99
    Log in to a running ducker container.  If node-name is not given, it prints
100
    the names of all running nodes.  If node-name is 'all', we will run the
101
    command on every node.  If user-name is given, we will try to log in as
102
    that user.  Otherwise, we will log in as the 'ducker' user.  If a command
103
    is specified, we will run that command.  Otherwise, we will provide a login
104
    shell.
105

106
down [-q|--quiet] [-f|--force]
107
    Tear down all the currently active ducker-ignite nodes.  If --quiet is specified,
108
    only error messages are printed. If --force or -f is specified, "docker rm -f"
109
    will be used to remove the nodes, which kills currently running ducker-ignite test.
110

111
purge [--f|--force]
112
    Purge Docker images created by ducker-ignite.  This will free disk space.
113
    If --force is set, we run 'docker rmi -f'.
114

115
compare [docker-image]
116
    Compare image id of last run and last build for specified docker-image. If they are different then cluster runs
117
    non-actual version of image. Rerun is required.
118

119
EOF
120
    exit "${exit_status}"
121
}
122

123
# Exit with an error message.
124
die() {
125
    echo $@
126
    exit 1
127
}
128

129
# Check for the presence of certain commands.
130
#
131
# $@: The commands to check for.  This function will die if any of these commands are not found by
132
#       the 'which' command.
133
require_commands() {
134
    local cmds="${@}"
135
    for cmd in ${cmds}; do
136
        which -- "${cmd}" &> /dev/null || die "You must install ${cmd} to run this script."
137
    done
138
}
139

140
# Set a global variable to a value.
141
#
142
# $1: The variable name to set.  This function will die if the variable already has a value.  The
143
#     variable will be made readonly to prevent any future modifications.
144
# $2: The value to set the variable to.  This function will die if the value is empty or starts
145
#     with a dash.
146
# $3: A human-readable description of the variable.
147
set_once() {
148
    local key="${1}"
149
    local value="${2}"
150
    local what="${3}"
151
    [[ -n "${!key}" ]] && die "Error: more than one value specified for ${what}."
152
    verify_command_line_argument "${value}" "${what}"
153
    # It would be better to use declare -g, but older bash versions don't support it.
154
    export ${key}="${value}"
155
}
156

157
# Verify that a command-line argument is present and does not start with a slash.
158
#
159
# $1: The command-line argument to verify.
160
# $2: A human-readable description of the variable.
161
verify_command_line_argument() {
162
    local value="${1}"
163
    local what="${2}"
164
    [[ -n "${value}" ]] || die "Error: no value specified for ${what}"
165
    [[ ${value} == -* ]] && die "Error: invalid value ${value} specified for ${what}"
166
}
167

168
# Echo a message if a flag is set.
169
#
170
# $1: If this is 1, the message will be echoed.
171
# $@: The message
172
maybe_echo() {
173
    local verbose="${1}"
174
    shift
175
    [[ "${verbose}" -eq 1 ]] && echo "${@}"
176
}
177

178
# Counts the number of elements passed to this subroutine.
179
count() {
180
    echo $#
181
}
182

183
# Push a new directory on to the bash directory stack, or exit with a failure message.
184
#
185
# $1: The directory push on to the directory stack.
186
must_pushd() {
187
    local target_dir="${1}"
188
    pushd -- "${target_dir}" &> /dev/null || die "failed to change directory to ${target_dir}"
189
}
190

191
# Pop a directory from the bash directory stack, or exit with a failure message.
192
must_popd() {
193
    popd &> /dev/null || die "failed to popd"
194
}
195

196
# Run a command and die if it fails.
197
#
198
# Optional flags:
199
# -v: print the command before running it.
200
# -o: display the command output.
201
# $@: The command to run.
202
must_do() {
203
    local verbose=0
204
    local output="/dev/null"
205
    while true; do
206
        case ${1} in
207
            -v) verbose=1; shift;;
208
            -o) output="/dev/stdout"; shift;;
209
            *) break;;
210
        esac
211
    done
212

213
    [[ "${verbose}" -eq 1 ]] && echo "${@}"
214
    eval "${@}" >${output} || die "${1} failed"
215
}
216

217
# Ask the user a yes/no question.
218
#
219
# $1: The prompt to use
220
# $_return: 0 if the user answered no; 1 if the user answered yes.
221
ask_yes_no() {
222
    local prompt="${1}"
223
    while true; do
224
        read -r -p "${prompt} " response
225
        case "${response}" in
226
            [yY]|[yY][eE][sS]) _return=1; return;;
227
            [nN]|[nN][oO]) _return=0; return;;
228
            *);;
229
        esac
230
        echo "Please respond 'yes' or 'no'."
231
        echo
232
    done
233
}
234

235
# Wait for all the background jobs
236
wait_jobs() {
237
  for job in `jobs -p`
238
  do
239
    wait $job
240
  done
241
}
242

243
# Build a docker image.
244
#
245
# $1: The docker build context
246
# $2: The name of the image to build.
247
ducker_build_image() {
248
    local docker_context="${1}"
249
    local image_name="${2}"
250

251
    # Use SECONDS, a builtin bash variable that gets incremented each second, to measure the docker
252
    # build duration.
253
    SECONDS=0
254

255
    must_pushd "${ducker_dir}"
256
    # Tip: if you are scratching your head for some dependency problems that are referring to an old code version
257
    # (for example java.lang.NoClassDefFoundError), add --no-cache flag to the build shall give you a clean start.
258
    must_do -v -o docker build --memory="${docker_build_memory_limit}" \
259
        --build-arg "ducker_creator=${user_name}" --build-arg "jdk_version=${jdk_version}" -t "${image_name}" \
260
        -f "${docker_context}/Dockerfile" -- "${docker_context}"
261
    docker_status=$?
262
    must_popd
263
    duration="${SECONDS}"
264
    if [[ ${docker_status} -ne 0 ]]; then
265
        die "** ERROR: Failed to build ${what} image after $((duration / 60))m $((duration % 60))s."
266
    fi
267

268
    # Save docker image id to the file. Then could use this file to find version of docker image built last time.
269
    # It could be useful if we don't confident about necessity of stoping the cluster.
270
    get_image_id "${image_name}" > "${ducker_dir}/build/image_${image_name}.build"
271

272
    echo "** Successfully built ${what} image in $((duration / 60))m $((duration % 60))s."
273
}
274

275
ducker_build() {
276
    require_commands docker
277

278
    local docker_context=
279
    while [[ $# -ge 1 ]]; do
280
        case "${1}" in
281
            -j|--jdk) set_once jdk_version "${2}" "the OpenJDK base image"; shift 2;;
282
            -c|--context) docker_context="${2}"; shift 2;;
283
            *) set_once image_name "${1}" "docker image name"; shift;;
284
        esac
285
    done
286

287
    [[ -n "${jdk_version}" ]] || jdk_version="${default_jdk}"
288
    [[ -n "${image_name}" ]] || image_name="${default_image_name}-${jdk_version/:/-}"
289
    [[ -n "${docker_context}" ]] || docker_context="${ducker_dir}"
290

291
    ducker_build_image "${docker_context}" "${image_name}"
292
}
293

294
docker_run() {
295
    local node=${1}
296
    local image_name=${2}
297
    local ports_option=${3}
298

299
    local expose_ports=""
300
    if [[ -n ${ports_option} ]]; then
301
        expose_ports="-P"
302
        for expose_port in ${ports_option//,/ }; do
303
            expose_ports="${expose_ports} --expose ${expose_port}"
304
        done
305
    fi
306

307
    # Invoke docker-run. We need privileged mode to be able to run iptables
308
    # and mount FUSE filesystems inside the container.  We also need it to
309
    # run iptables inside the container.
310
    must_do -v docker run --privileged \
311
        -d \
312
        -t \
313
        -h "${node}" \
314
        --network ducknet ${expose_ports} \
315
        --memory=${docker_run_memory_limit} \
316
        --memory-swappiness=1 \
317
        --mount type=bind,source="${ignite_dir}",target=/opt/ignite-dev,consistency=delegated \
318
        $DOCKER_OPTIONS \
319
        --name "${node}" \
320
        -- "${image_name}"
321
}
322

323
setup_custom_ducktape() {
324
    local custom_ducktape="${1}"
325
    local image_name="${2}"
326

327
    [[ -f "${custom_ducktape}/ducktape/__init__.py" ]] || \
328
        die "You must supply a valid ducktape directory to --custom-ducktape"
329
    docker_run ducker01 "${image_name}"
330
    local running_container
331
    running_container=$(docker ps -f=network=ducknet -q)
332
    must_do -v -o docker cp "${custom_ducktape}" "${running_container}:/opt/ducktape"
333
    docker exec --user=root ducker01 bash -c 'set -x && cd /opt/ignite-dev/modules/ducktests/tests && sudo python ./setup.py develop install && cd /opt/ducktape && sudo python ./setup.py develop install'
334
    [[ $? -ne 0 ]] && die "failed to install the new ducktape."
335
    must_do -v -o docker commit ducker01 "${image_name}"
336
    must_do -v docker kill "${running_container}"
337
    must_do -v docker rm ducker01
338
}
339

340
ducker_up() {
341
    require_commands docker
342
    while [[ $# -ge 1 ]]; do
343
        case "${1}" in
344
            -C|--custom-ducktape) set_once custom_ducktape "${2}" "the custom ducktape directory"; shift 2;;
345
            -f|--force) force=1; shift;;
346
            -n|--num-nodes) set_once num_nodes "${2}" "number of nodes"; shift 2;;
347
            -e|--expose-ports) set_once expose_ports "${2}" "the ports to expose"; shift 2;;
348
            --subnet) set_once subnet "${2}" "subnet in CIDR format that represents a network segment"; shift 2;;
349
            *) set_once image_name "${1}" "docker image name"; shift;;
350
        esac
351
    done
352
    [[ -n "${num_nodes}" ]] || num_nodes="${default_num_nodes}"
353
    [[ -n "${image_name}" ]] || image_name="${default_image_name}-${default_jdk/:/-}"
354
    [[ "${num_nodes}" =~ ^-?[0-9]+$ ]] || \
355
        die "ducker_up: the number of nodes must be an integer."
356
    [[ "${num_nodes}" -gt 0 ]] || die "ducker_up: the number of nodes must be greater than 0."
357
    if [[ "${num_nodes}" -lt 2 ]]; then
358
        if [[ "${force}" -ne 1 ]]; then
359
            echo "ducker_up: It is recommended to run at least 2 nodes, since ducker01 is only \
360
used to run ducktape itself.  If you want to do it anyway, you can use --force to attempt to \
361
use only ${num_nodes}."
362
            exit 1
363
        fi
364
    fi
365
    [[ "${subnet}" ]] && docker_network_options="--subnet ${subnet}"
366

367
    docker ps >/dev/null || die "ducker_up: failed to run docker.  Please check that the daemon is started."
368

369
    local running_containers="$(docker ps -f=network=ducknet -q)"
370
    local num_running_containers=$(count ${running_containers})
371
    if [[ ${num_running_containers} -gt 0 ]]; then
372
        die "ducker_up: there are ${num_running_containers} ducker containers \
373
running already.  Use ducker down to bring down these containers before \
374
attempting to start new ones."
375
    fi
376

377
    echo "ducker_up: Bringing up ${image_name} with ${num_nodes} nodes..."
378
    docker image inspect "${image_name}" &>/dev/null || \
379
      must_do -v -o docker pull "${image_name}"
380

381
    if docker network inspect ducknet &>/dev/null; then
382
        must_do -v docker network rm ducknet
383
    fi
384
    must_do -v docker network create "${docker_network_options}" ducknet
385
    if [[ -n "${custom_ducktape}" ]]; then
386
        setup_custom_ducktape "${custom_ducktape}" "${image_name}"
387
    fi
388
    for n in $(seq -f %02g 1 ${num_nodes}); do
389
        local node="ducker${n}"
390
        docker_run "${node}" "${image_name}" "${expose_ports}"
391
    done
392
    mkdir -p "${ducker_dir}/build"
393
    exec 3<> "${ducker_dir}/build/node_hosts"
394
    for n in $(seq -f %02g 1 ${num_nodes}); do
395
        local node="ducker${n}"
396
        docker exec --user=root "${node}" grep "${node}" /etc/hosts >&3
397
        [[ $? -ne 0 ]] && die "failed to find the /etc/hosts entry for ${node}"
398
    done
399
    exec 3>&-
400
    for n in $(seq -f %02g 1 ${num_nodes}); do
401
        local node="ducker${n}"
402
        docker exec --user=root "${node}" \
403
            bash -c "grep -v ${node} /opt/ignite-dev/modules/ducktests/tests/docker/build/node_hosts >> /etc/hosts"
404
        [[ $? -ne 0 ]] && die "failed to append to the /etc/hosts file on ${node}"
405
    done
406

407
    echo "ducker_up: added the latest entries to /etc/hosts on each node."
408
    generate_cluster_json_file "${num_nodes}" "${ducker_dir}/build/cluster.json"
409
    echo "ducker_up: successfully wrote ${ducker_dir}/build/cluster.json"
410

411
    # Save docker image id to the file. Then could use this file to find version of docker image that is running.
412
    # It could be useful if we don't confident about necessity of rebuilding image.
413
    get_image_id "${image_name}" > "${ducker_dir}/build/image_id.up"
414

415
    echo "** ducker_up: successfully brought up ${num_nodes} nodes."
416
}
417

418
# Generate the cluster.json file used by ducktape to identify cluster nodes.
419
#
420
# $1: The number of cluster nodes.
421
# $2: The path to write the cluster.json file to.
422
generate_cluster_json_file() {
423
    local num_nodes="${1}"
424
    local path="${2}"
425
    rm ${path}
426
    touch ${path}
427
    exec 3<> "${path}"
428
cat<<EOF >&3
429
{
430
  "_comment": [
431
    "Licensed to the Apache Software Foundation (ASF) under one or more",
432
    "contributor license agreements.  See the NOTICE file distributed with",
433
    "this work for additional information regarding copyright ownership.",
434
    "The ASF licenses this file to You under the Apache License, Version 2.0",
435
    "(the \"License\"); you may not use this file except in compliance with",
436
    "the License.  You may obtain a copy of the License at",
437
    "",
438
    "http://www.apache.org/licenses/LICENSE-2.0",
439
    "",
440
    "Unless required by applicable law or agreed to in writing, software",
441
    "distributed under the License is distributed on an \"AS IS\" BASIS,",
442
    "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.",
443
    "See the License for the specific language governing permissions and",
444
    "limitations under the License."
445
  ],
446
  "nodes": [
447
EOF
448
    for n in $(seq 2 ${num_nodes}); do
449
      if [[ ${n} -eq ${num_nodes} ]]; then
450
        suffix=""
451
      else
452
        suffix=","
453
      fi
454
      local node=$(printf ducker%02d ${n})
455
cat<<EOF >&3
456
    {
457
      "externally_routable_ip": "${node}",
458
      "ssh_config": {
459
        "host": "${node}",
460
        "hostname": "${node}",
461
        "identityfile": "/home/ducker/.ssh/id_rsa",
462
        "password": "",
463
        "port": 22,
464
        "user": "ducker"
465
      }
466
    }${suffix}
467
EOF
468
    done
469
cat<<EOF >&3
470
  ]
471
}
472
EOF
473
    exec 3>&-
474
}
475

476
ducker_test() {
477
    require_commands docker
478
    docker inspect ducker01 &>/dev/null || \
479
        die "ducker_test: the ducker01 instance appears to be down. Did you run 'ducker up'?"
480
    [[ $# -lt 1 ]] && \
481
        die "ducker_test: you must supply at least one system test to run. Type --help for help."
482
    local args=""
483
    local ignite_test=0
484
    for arg in "${@}"; do
485
        local regex=".*\/ignitetest\/(.*)"
486
        if [[ $arg =~ $regex ]]; then
487
            local ignpath=${BASH_REMATCH[1]}
488
            args="${args} ./modules/ducktests/tests/ignitetest/${ignpath}"
489
        else
490
            args="${args} ${arg}"
491
        fi
492
    done
493
    must_pushd "${ignite_dir}"
494
    #(test mvn) && mvn package -DskipTests -Dmaven.javadoc.skip=true -Plgpl,-examples,-clean-libs,-release,-scala,-clientDocs
495
    must_popd
496
    if [[ -n "${DUCKTAPE_EXTRA_SETUP}" ]]; then
497
        echo "executing extra ducktape setup with '${DUCKTAPE_EXTRA_SETUP}'"
498
        local nodes=$(echo_running_container_names)
499
        for node in ${nodes}; do
500
          docker exec --user=root ${node} bash -c "${DUCKTAPE_EXTRA_SETUP}" &
501
        done
502
        wait_jobs
503
        [[ $? -ne 0 ]] && die "failed to execute extra ducktape setup."
504
    fi
505
    cmd="cd /opt/ignite-dev && ducktape --cluster-file /opt/ignite-dev/modules/ducktests/tests/docker/build/cluster.json $args"
506
    echo "docker exec ducker01 bash -c \"${cmd}\""
507
    exec docker exec --user=ducker ducker01 bash -c "${cmd}"
508
}
509

510
ducker_ssh() {
511
    require_commands docker
512
    [[ $# -eq 0 ]] && die "ducker_ssh: Please specify a container name to log into. \
513
Currently active containers: $(echo_running_container_names)"
514
    local node_info="${1}"
515
    shift
516
    local guest_command="$*"
517
    local user_name="ducker"
518
    if [[ "${node_info}" =~ @ ]]; then
519
        user_name="${node_info%%@*}"
520
        local node_name="${node_info##*@}"
521
    else
522
        local node_name="${node_info}"
523
    fi
524
    local docker_flags=""
525
    if [[ -z "${guest_command}" ]]; then
526
        local docker_flags="${docker_flags} -t"
527
        local guest_command_prefix=""
528
        guest_command=bash
529
    else
530
        local guest_command_prefix="bash -c"
531
    fi
532
    if [[ "${node_name}" == "all" ]]; then
533
        local nodes=$(echo_running_container_names)
534
        [[ "${nodes}" == "(none)" ]] && die "ducker_ssh: can't locate any running ducker nodes."
535
        for node in ${nodes}; do
536
            docker exec --user=${user_name} -i ${docker_flags} "${node}" \
537
                ${guest_command_prefix} "${guest_command}" || die "docker exec ${node} failed"
538
        done
539
    else
540
        docker inspect --type=container -- "${node_name}" &>/dev/null || \
541
            die "ducker_ssh: can't locate node ${node_name}. Currently running nodes: \
542
$(echo_running_container_names)"
543
        exec docker exec --user=${user_name} -i ${docker_flags} "${node_name}" \
544
            ${guest_command_prefix} "${guest_command}"
545
    fi
546
}
547

548
# Echo all the running Ducker container names, or (none) if there are no running Ducker containers.
549
echo_running_container_names() {
550
    node_names="$(docker ps -f=network=ducknet -q --format '{{.Names}}' | sort)"
551
    if [[ -z "${node_names}" ]]; then
552
        echo "(none)"
553
    else
554
        echo ${node_names//$'\n'/ }
555
    fi
556
}
557

558
ducker_down() {
559
    require_commands docker
560
    local verbose=1
561
    local force_str=""
562
    while [[ $# -ge 1 ]]; do
563
        case "${1}" in
564
            -q|--quiet) verbose=0; shift;;
565
            -f|--force) force_str="-f"; shift;;
566
            *) die "ducker_down: unexpected command-line argument ${1}";;
567
        esac
568
    done
569
    local running_containers
570
    running_containers="$(docker ps -f=network=ducknet -q)"
571
    [[ $? -eq 0 ]]  || die "ducker_down: docker command failed.  Is the docker daemon running?"
572
    running_containers=${running_containers//$'\n'/ }
573
    local all_containers
574
    all_containers=$(docker ps -a -f=network=ducknet -q)
575
    all_containers=${all_containers//$'\n'/ }
576
    if [[ -z "${all_containers}" ]]; then
577
        maybe_echo "${verbose}" "No ducker containers found."
578
        return
579
    fi
580
    verbose_flag=""
581
    if [[ ${verbose} == 1 ]]; then
582
        verbose_flag="-v"
583
    fi
584
    if [[ -n "${running_containers}" ]]; then
585
        must_do ${verbose_flag} docker kill "${running_containers[@]}"
586
    fi
587
    must_do ${verbose_flag} docker rm ${force_str} "${all_containers}"
588
    must_do ${verbose_flag} -o rm -f -- "${ducker_dir}/build/node_hosts" "${ducker_dir}/build/cluster.json"
589
    if docker network inspect ducknet &>/dev/null; then
590
        must_do -v docker network rm ducknet
591
    fi
592
    rm "${ducker_dir}/build/image_id.up"
593
    maybe_echo "${verbose}" "ducker_down: removed $(count ${all_containers}) containers."
594
}
595

596
ducker_purge() {
597
    require_commands docker
598
    local force_str=""
599
    while [[ $# -ge 1 ]]; do
600
        case "${1}" in
601
            -f|--force) force_str="-f"; shift;;
602
            *) die "ducker_purge: unknown argument ${1}";;
603
        esac
604
    done
605
    echo "** ducker_purge: attempting to locate ducker images to purge"
606
    local images
607
    images=$(docker images -q -a -f label=ducker.creator)
608
    [[ $? -ne 0 ]] && die "docker images command failed"
609
    images=${images//$'\n'/ }
610
    declare -a purge_images=()
611
    if [[ -z "${images}" ]]; then
612
        echo "** ducker_purge: no images found to purge."
613
        exit 0
614
    fi
615
    echo "** ducker_purge: images to delete:"
616
    for image in ${images}; do
617
        echo -n "${image} "
618
        docker inspect --format='{{.Config.Labels}} {{.Created}}' --type=image "${image}"
619
        [[ $? -ne 0 ]] && die "docker inspect ${image} failed"
620
    done
621
    ask_yes_no "Delete these docker images? [y/n]"
622
    [[ "${_return}" -eq 0 ]] && exit 0
623
    must_do -v -o docker rmi ${force_str} ${images}
624
}
625

626
get_image_id() {
627
    require_commands docker
628
    local image_name="${1}"
629

630
    must_do -o docker image inspect --format "{{.Id}}" "${image_name}"
631
}
632

633
ducker_compare() {
634
    local cmd=""
635

636
    local verbose=1
637
    local force_str=""
638

639
    while [[ $# -ge 1 ]]; do
640
        case "${1}" in
641
            -q|--quiet) verbose=0; cmd="${cmd} ${1}"; shift;;
642
            -f|--force) force_str="-f"; cmd="${cmd} ${1}"; shift;;
643
            *) set_once image_name "${1}" "docker image name"; shift;;
644
        esac
645
    done
646

647
    [ -n "${image_name}" ] || image_name="${default_image_name}-${default_jdk/:/-}"
648

649
    cmp -s "${ducker_dir}/build/image_${image_name}.build" "${ducker_dir}/build/image_id.up"
650
    local ret="$?"
651

652
    if [[ $ret != "0" ]]; then
653
        echo "Docker image ${image_name} is outdated. Stop the cluster"
654
        ducker_down ${cmd}
655
    fi
656
}
657

658
# Parse command-line arguments
659
[[ $# -lt 1 ]] && usage 0
660
# Display the help text if -h or --help appears in the command line
661
for arg in ${@}; do
662
    case "${arg}" in
663
        -h|--help) usage 0;;
664
        --) break;;
665
        *);;
666
    esac
667
done
668
action="${1}"
669
shift
670
case "${action}" in
671
    help) usage 0;;
672

673
    build|up|test|ssh|down|purge|compare)
674
        ducker_${action} "${@}"; exit 0;;
675

676
    *)  echo "Unknown command '${action}'.  Type '${script_path} --help' for usage information."
677
        exit 1;;
678
esac
679

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.