podman

Форк
0
/
250-systemd.bats 
494 строки · 16.7 Кб
1
#!/usr/bin/env bats   -*- bats -*-
2
#
3
# Tests generated configurations for systemd.
4
#
5

6
load helpers
7
load helpers.systemd
8
load helpers.network
9

10
SERVICE_NAME="podman_test_$(random_string)"
11

12
UNIT_FILE="$UNIT_DIR/$SERVICE_NAME.service"
13
TEMPLATE_FILE="$UNIT_DIR/$SERVICE_NAME@.service"
14

15
function setup() {
16
    skip_if_remote "systemd tests are meaningless over remote"
17

18
    basic_setup
19
}
20

21
function teardown() {
22
    if [[ -e "$UNIT_FILE" ]]; then
23
        run systemctl stop "$SERVICE_NAME"
24
        if [ $status -ne 0 ]; then
25
            echo "# WARNING: systemctl stop failed in teardown: $output" >&3
26
        fi
27

28
        rm -f "$UNIT_FILE"
29
        systemctl daemon-reload
30
    fi
31

32
    basic_teardown
33
}
34

35
# Helper to start a systemd service running a container
36
function service_setup() {
37
    # January 2024: we can no longer do "run_podman generate systemd" followed
38
    # by "echo $output >file", because generate-systemd is deprecated and now
39
    # says so loudly, to stderr, with no way to silence it. Since BATS gloms
40
    # stdout + stderr, that warning goes to the unit file. (Today's systemd
41
    # is forgiving about that, but RHEL8 systemd chokes with EINVAL)
42
    (
43
        cd $UNIT_DIR
44
        run_podman generate systemd --files --name \
45
               -e http_proxy -e https_proxy -e no_proxy \
46
               -e HTTP_PROXY -e HTTPS_PROXY -e NO_PROXY \
47
               --new $cname
48
        mv "container-$cname.service" $UNIT_FILE
49
    )
50
    run_podman rm $cname
51

52
    systemctl daemon-reload
53

54
    # Also test enabling services (see #12438).
55
    run systemctl enable "$SERVICE_NAME"
56
    assert $status -eq 0 "Error enabling systemd unit $SERVICE_NAME: $output"
57

58
    systemctl_start "$SERVICE_NAME"
59

60
    run systemctl status "$SERVICE_NAME"
61
    assert $status -eq 0 "systemctl status $SERVICE_NAME: $output"
62
}
63

64
# Helper to stop a systemd service running a container
65
function service_cleanup() {
66
    run systemctl stop "$SERVICE_NAME"
67
    assert $status -eq 0 "Error stopping systemd unit $SERVICE_NAME: $output"
68

69
    # Regression test for #11304: confirm that unit stops into correct state
70
    local expected_state="$1"
71
    if [[ -n "$expected_state" ]]; then
72
        run systemctl show --property=ActiveState "$SERVICE_NAME"
73
        assert "$output" = "ActiveState=$expected_state" \
74
               "state of service after systemctl stop"
75
    fi
76

77
    run systemctl disable "$SERVICE_NAME"
78
    assert $status -eq 0 "Error disabling systemd unit $SERVICE_NAME: $output"
79

80
    rm -f "$UNIT_FILE"
81
    systemctl daemon-reload
82
}
83

84
# These tests can fail in dev. environment because of SELinux.
85
# quick fix: chcon -t container_runtime_exec_t ./bin/podman
86
@test "podman generate - systemd - basic" {
87
    # Warn when a custom restart policy is used without --new (see #15284)
88
    run_podman create --restart=always $IMAGE
89
    cid="$output"
90
    run_podman 0+w generate systemd $cid
91
    require_warning "Container $cid has restart policy .*always.* which can lead to issues on shutdown" \
92
                    "generate systemd emits warning"
93
    run_podman rm -f $cid
94

95
    cname=$(random_string)
96
    # See #7407 for --pull=always.
97
    run_podman create --pull=always --name $cname --label "io.containers.autoupdate=registry" $IMAGE \
98
        sh -c "trap 'echo Received SIGTERM, finishing; exit' SIGTERM; echo WAITING; while :; do sleep 0.1; done"
99

100
    # Start systemd service to run this container
101
    service_setup
102

103
    # Give container time to start; make sure output looks top-like
104
    sleep 2
105
    run_podman logs $cname
106
    is "$output" ".*WAITING.*" "running is waiting for signal"
107

108
    # All good. Stop service, clean up.
109
    # Also make sure the service is in the `inactive` state (see #11304).
110
    service_cleanup inactive
111
}
112

113
@test "podman autoupdate local" {
114
    # Note that the entrypoint may be a JSON string which requires preserving the quotes (see #12477)
115
    cname=$(random_string)
116

117
    # Create a scratch image (copy of our regular one)
118
    image_copy=base$(random_string | tr A-Z a-z)
119
    run_podman tag $IMAGE $image_copy
120

121
    # Create a container based on that
122
    run_podman create --name $cname --label "io.containers.autoupdate=local" --entrypoint '["top"]' $image_copy
123

124
    # Start systemd service to run this container
125
    service_setup
126

127
    # Give container time to start; make sure output looks top-like
128
    wait_for_output 'Load average' $cname
129

130
    # Run auto-update and check that it restarted the container
131
    run_podman commit --change "CMD=/bin/bash" $cname $image_copy
132
    run_podman auto-update
133
    is "$output" ".*$SERVICE_NAME.*" "autoupdate local restarted container"
134

135
    # All good. Stop service, clean up.
136
    service_cleanup
137
    run_podman rmi $image_copy
138
}
139

140
# These tests can fail in dev. environment because of SELinux.
141
# quick fix: chcon -t container_runtime_exec_t ./bin/podman
142
@test "podman generate systemd - envar" {
143
    cname=$(random_string)
144
    FOO=value BAR=%s run_podman create --name $cname --env FOO -e BAR --env MYVAR=myval \
145
        $IMAGE sh -c 'printenv && sleep 100'
146

147
    # Start systemd service to run this container
148
    service_setup
149

150
    # Give container time to start; make sure output looks top-like
151
    sleep 2
152
    run_podman logs $cname
153
    is "$output" ".*FOO=value.*" "FOO environment variable set"
154
    is "$output" ".*BAR=%s.*" "BAR environment variable set"
155
    is "$output" ".*MYVAR=myval.*" "MYVAL environment variable set"
156

157
    # All good. Stop service, clean up.
158
    service_cleanup
159
}
160

161
# Regression test for #11438
162
@test "podman generate systemd - restart policy & timeouts" {
163
    cname=$(random_string)
164
    run_podman create --restart=always --name $cname $IMAGE
165
    run_podman generate systemd --new $cname
166
    is "$output" ".*Restart=always.*" "Use container's restart policy if set"
167
    run_podman generate systemd --new --restart-policy=on-failure $cname
168
    is "$output" ".*Restart=on-failure.*" "Override container's restart policy"
169

170
    cname2=$(random_string)
171
    run_podman create --restart=unless-stopped --name $cname2 $IMAGE
172
    run_podman generate systemd --new $cname2
173
    is "$output" ".*Restart=always.*" "unless-stopped translated to always"
174

175
    cname3=$(random_string)
176
    run_podman create --restart=on-failure:42 --name $cname3 $IMAGE
177
    run_podman generate systemd --new $cname3
178
    is "$output" ".*Restart=on-failure.*" "on-failure:xx is parsed correctly"
179
    is "$output" ".*StartLimitBurst=42.*" "on-failure:xx is parsed correctly"
180

181
    run_podman rm -t 0 -f $cname $cname2 $cname3
182
}
183

184
function set_listen_env() {
185
    export LISTEN_PID="100" LISTEN_FDS="1" LISTEN_FDNAMES="listen_fdnames"
186
}
187

188
function unset_listen_env() {
189
    unset LISTEN_PID LISTEN_FDS LISTEN_FDNAMES
190
}
191

192
function check_listen_env() {
193
    local stdenv="$1"
194
    local context="$2"
195
    if is_remote; then
196
        is "$output" "$stdenv" "LISTEN Environment did not pass: $context"
197
    else
198
        out=$(for o in $output; do echo $o; done| sort)
199
        std=$(echo "$stdenv
200
LISTEN_PID=1
201
LISTEN_FDS=1
202
LISTEN_FDNAMES=listen_fdnames" | sort)
203
       echo "<$out>"
204
       echo "<$std>"
205
       is "$out" "$std" "LISTEN Environment passed: $context"
206
    fi
207
}
208

209
@test "podman pass LISTEN environment " {
210
    # Note that `--hostname=host1` makes sure that all containers have the same
211
    # environment.
212
    run_podman run --hostname=host1 --rm $IMAGE printenv
213
    stdenv=$output
214

215
    # podman run
216
    set_listen_env
217
    run_podman run --hostname=host1 --rm $IMAGE printenv
218
    unset_listen_env
219
    check_listen_env "$stdenv" "podman run"
220

221
    # podman start
222
    run_podman create --hostname=host1 --rm $IMAGE printenv
223
    cid="$output"
224
    set_listen_env
225
    run_podman start --attach $cid
226
    unset_listen_env
227
    check_listen_env "$stdenv" "podman start"
228
}
229

230
@test "podman generate - systemd template" {
231
    cname=$(random_string)
232
    run_podman create --name $cname $IMAGE top
233

234
    # See note in service_setup() above re: using --files
235
    (
236
        cd $UNIT_DIR
237
        run_podman generate systemd --template --files -n $cname
238
        mv "container-$cname.service" $TEMPLATE_FILE
239
    )
240
    run_podman rm -f $cname
241

242
    systemctl daemon-reload
243

244
    INSTANCE="$SERVICE_NAME@1.service"
245
    systemctl_start "$INSTANCE"
246

247
    run systemctl status "$INSTANCE"
248
    assert $status -eq 0 "systemctl status $INSTANCE: $output"
249

250
    run systemctl stop "$INSTANCE"
251
    assert $status -eq 0 "Error stopping systemd unit $INSTANCE: $output"
252

253
    rm -f $TEMPLATE_FILE
254
    systemctl daemon-reload
255
}
256

257
@test "podman generate - systemd template no support for pod" {
258
    cname=$(random_string)
259
    podname=$(random_string)
260
    run_podman pod create --name $podname
261
    run_podman run --pod $podname -dt --name $cname $IMAGE top
262

263
    run_podman 125 generate systemd --new --template -n $podname
264
    is "$output" ".*--template is not supported for pods.*" "Error message contains 'not supported'"
265

266
    run_podman rm -f $cname
267
    run_podman pod rm -f $podname
268
    run_podman rmi $(pause_image)
269
}
270

271
@test "podman generate - systemd template only used on --new" {
272
    cname=$(random_string)
273
    run_podman create --name $cname $IMAGE top
274
    run_podman 125 generate systemd --new=false --template -n $cname
275
    is "$output" ".*--template cannot be set" "Error message should be '--template requires --new'"
276
}
277

278
@test "podman --cgroup=cgroupfs doesn't show systemd warning" {
279
    DBUS_SESSION_BUS_ADDRESS= run_podman --log-level warning --cgroup-manager=cgroupfs info -f ''
280
    is "$output" "" "output should be empty"
281
}
282

283
@test "podman --systemd sets container_uuid" {
284
    run_podman run --systemd=always --name test $IMAGE printenv container_uuid
285
    container_uuid=$output
286
    run_podman inspect test --format '{{ .ID }}'
287
    is "${container_uuid}" "${output:0:32}" "UUID should be first 32 chars of Container id"
288
}
289

290
@test "podman --systemd fails on cgroup v1 with a private cgroupns" {
291
    skip_if_cgroupsv2
292

293
    run_podman 126 run --systemd=always --cgroupns=private $IMAGE true
294
    assert "$output" =~ ".*cgroup namespace is not supported with cgroup v1 and systemd mode"
295
}
296

297
# https://github.com/containers/podman/issues/13153
298
@test "podman rootless-netns pasta processes should be in different cgroup" {
299
    is_rootless || skip "only meaningful for rootless"
300

301
    cname=$(random_string)
302
    local netname=testnet-$(random_string 10)
303

304
    # create network and container with network
305
    run_podman network create $netname
306
    run_podman create --name $cname --network $netname $IMAGE top
307

308
    # run container in systemd unit
309
    service_setup
310

311
    # run second container with network
312
    cname2=$(random_string)
313
    run_podman run -d --name $cname2 --network $netname $IMAGE top
314

315
    # stop systemd container
316
    service_cleanup
317

318
    pasta_iface=$(default_ifname)
319

320
    # now check that the rootless netns slirp4netns process is still alive and working
321
    run_podman unshare --rootless-netns ip addr
322
    is "$output" ".*$pasta_iface.*" "pasta interface exists in the netns"
323
    run_podman exec $cname2 nslookup google.com
324

325
    run_podman rm -f -t0 $cname2
326
    run_podman network rm -f $netname
327
}
328

329
@test "podman create --health-on-failure=kill" {
330
    cname=c_$(random_string)
331
    run_podman create --name $cname                  \
332
               --health-cmd /home/podman/healthcheck \
333
               --health-on-failure=kill              \
334
               --health-retries=1                    \
335
               --restart=on-failure                  \
336
               $IMAGE /home/podman/pause
337

338
    # run container in systemd unit
339
    service_setup
340

341
    run_podman container inspect $cname --format "{{.ID}}"
342
    oldID="$output"
343

344
    run_podman healthcheck run $cname
345

346
    # Now cause the healthcheck to fail
347
    run_podman exec $cname touch /uh-oh
348

349
    # healthcheck should now fail, with exit status 1 and 'unhealthy' output
350
    run_podman 1 healthcheck run $cname
351
    is "$output" "unhealthy" "output from 'podman healthcheck run'"
352

353
    # What is expected to happen now:
354
    #  1) The container gets killed as the health check has failed
355
    #  2) Systemd restarts the service as the restart policy is set to "on-failure"
356
    #  3) The /uh-oh file is gone and $cname has another ID
357

358
    # Wait at most 10 seconds for the service to be restarted
359
    local timeout=10
360
    while [[ $timeout -gt 1 ]]; do
361
        # Possible outcomes:
362
        #  - status 0, old container is still terminating: sleep and retry
363
        #  - status 0, new CID: yay, break
364
        #  - status 1, container not found: sleep and retry
365
        run_podman '?' container inspect $cname --format '{{.ID}}'
366
        if [[ $status == 0 ]]; then
367
            if [[ "$output" != "$oldID" ]]; then
368
                break
369
            fi
370
        fi
371
        sleep 1
372
        let timeout=$timeout-1
373
    done
374

375
    run_podman healthcheck run $cname
376

377
    # stop systemd container
378
    service_cleanup
379
}
380

381
@test "podman-kube@.service template" {
382
    install_kube_template
383
    # Create the YAMl file
384
    yaml_source="$PODMAN_TMPDIR/test.yaml"
385
    cat >$yaml_source <<EOF
386
apiVersion: v1
387
kind: Pod
388
metadata:
389
  annotations:
390
      io.containers.autoupdate: "local"
391
      io.containers.autoupdate/b: "registry"
392
  labels:
393
    app: test
394
  name: test_pod
395
spec:
396
  containers:
397
  - command:
398
    - sh
399
    - -c
400
    - echo a stdout; echo a stderr 1>&2; sleep inf
401
    image: $IMAGE
402
    name: a
403
  - command:
404
    - sh
405
    - -c
406
    - echo b stdout; echo b stderr 1>&2; sleep inf
407
    image: $IMAGE
408
    name: b
409
EOF
410

411
    # Dispatch the YAML file
412
    service_name="podman-kube@$(systemd-escape $yaml_source).service"
413
    systemctl_start $service_name
414
    systemctl is-active $service_name
415

416
    # Make sure that Podman is the service's MainPID
417
    run systemctl show --property=MainPID --value $service_name
418
    is "$(</proc/$output/comm)" "conmon" "podman is the service mainPID"
419

420
    # The name of the service container is predictable: the first 12 characters
421
    # of the hash of the YAML file followed by the "-service" suffix
422
    yaml_sha=$(sha256sum $yaml_source)
423
    service_container="${yaml_sha:0:12}-service"
424

425
    # Make sure that the service container exists and runs.
426
    run_podman container inspect $service_container --format "{{.State.Running}}"
427
    is "$output" "true"
428

429
    # Check for an error when trying to remove the service container
430
    run_podman 125 container rm $service_container
431
    is "$output" "Error: container .* is the service container of pod(s) .* and cannot be removed without removing the pod(s)"
432

433
    # containers/podman/issues/17482: verify that the log-driver for the Pod's containers is NOT passthrough
434
    for name in "a" "b"; do
435
        run_podman container inspect test_pod-${name} --format "{{.HostConfig.LogConfig.Type}}"
436
        assert $output != "passthrough"
437
        # check that we can get the logs with passthrough when we run in a systemd unit
438
        run_podman logs test_pod-$name
439
        assert "$output" == "$name stdout
440
$name stderr" "logs work with passthrough"
441
    done
442

443
    # we cannot assume the ordering between a b, this depends on timing and would flake in CI
444
    # use --names so we do not have to get the ID
445
    run_podman pod logs --names test_pod
446
    assert "$output" =~ ".*^test_pod-a a stdout.*" "logs from container a shown"
447
    assert "$output" =~ ".*^test_pod-b b stdout.*" "logs from container b shown"
448

449
    # Add a simple `auto-update --dry-run` test here to avoid too much redundancy
450
    # with 255-auto-update.bats
451
    run_podman auto-update --dry-run --format "{{.Unit}},{{.Container}},{{.Image}},{{.Updated}},{{.Policy}}"
452
    is "$output" ".*$service_name,.* (test_pod-a),$IMAGE,false,local.*" "global auto-update policy gets applied"
453
    is "$output" ".*$service_name,.* (test_pod-b),$IMAGE,false,registry.*" "container-specified auto-update policy gets applied"
454

455
    # Kill the pod and make sure the service is not running.
456
    run_podman pod kill test_pod
457
    for i in {0..20}; do
458
        # echos are for debugging test flakes
459
        echo "$_LOG_PROMPT systemctl is-active $service_name"
460
        run systemctl is-active $service_name
461
        echo "$output"
462
        if [[ "$output" == "inactive" ]]; then
463
            break
464
        fi
465
        sleep 0.5
466
    done
467
    is "$output" "inactive" "systemd service transitioned to 'inactive' state: $service_name"
468

469
    # Now stop and start the service again.
470
    systemctl stop $service_name
471
    systemctl_start $service_name
472
    systemctl is-active $service_name
473
    run_podman container inspect $service_container --format "{{.State.Running}}"
474
    is "$output" "true"
475

476
    # Clean up
477
    systemctl stop $service_name
478
    run_podman 1 container exists $service_container
479
    run_podman 1 pod exists test_pod
480
    run_podman rmi $(pause_image)
481
    rm -f $UNIT_DIR/$unit_name
482
}
483

484
@test "podman generate - systemd - DEPRECATED" {
485
    run_podman generate systemd --help
486
    is "$output" ".*[DEPRECATED] command:"
487
    is "$output" ".*\[DEPRECATED\] Generate systemd units.*"
488
    run_podman create --name test $IMAGE
489
    run_podman generate systemd test >/dev/null
490
    is "$output" ".*[DEPRECATED] command:"
491
    run_podman generate --help
492
    is "$output" ".*\[DEPRECATED\] Generate systemd units"
493
}
494
# vim: filetype=sh
495

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

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

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

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