mirror of
https://github.com/containers/podman.git
synced 2026-03-13 08:01:19 +08:00
Support running `podman play kube` in systemd by exploiting the previously added "service containers". During `play kube`, a service container is started before all the pods and containers, and is stopped last. The service container communicates its conmon PID via sdnotify. Add a new systemd template to dispatch such k8s workloads. The argument of the template is the path to the k8s file. Note that the path must be escaped for systemd not to bark: Let's assume we have a `top.yaml` file in the home directory: ``` $ escaped=$(systemd-escape ~/top.yaml) $ systemctl --user start podman-play-kube@$escaped.service ``` Closes: https://issues.redhat.com/browse/RUN-1287 Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
357 lines
10 KiB
Bash
357 lines
10 KiB
Bash
#!/usr/bin/env bats -*- bats -*-
|
|
#
|
|
# Test podman play
|
|
#
|
|
|
|
load helpers
|
|
|
|
# This is a long ugly way to clean up pods and remove the pause image
|
|
function teardown() {
|
|
run_podman pod rm -t 0 -f -a
|
|
run_podman rm -t 0 -f -a
|
|
run_podman image list --format '{{.ID}} {{.Repository}}'
|
|
while read id name; do
|
|
if [[ "$name" =~ /podman-pause ]]; then
|
|
run_podman rmi $id
|
|
fi
|
|
done <<<"$output"
|
|
|
|
basic_teardown
|
|
}
|
|
|
|
testYaml="
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
labels:
|
|
app: test
|
|
name: test_pod
|
|
spec:
|
|
containers:
|
|
- command:
|
|
- sleep
|
|
- \"100\"
|
|
env:
|
|
- name: PATH
|
|
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
- name: TERM
|
|
value: xterm
|
|
- name: container
|
|
value: podman
|
|
image: $IMAGE
|
|
name: test
|
|
resources: {}
|
|
securityContext:
|
|
runAsUser: 1000
|
|
runAsGroup: 3000
|
|
fsGroup: 2000
|
|
allowPrivilegeEscalation: true
|
|
capabilities: {}
|
|
privileged: false
|
|
seLinuxOptions:
|
|
level: \"s0:c1,c2\"
|
|
readOnlyRootFilesystem: false
|
|
volumeMounts:
|
|
- mountPath: /testdir:z
|
|
name: home-podman-testdir
|
|
workingDir: /
|
|
volumes:
|
|
- hostPath:
|
|
path: TESTDIR
|
|
type: Directory
|
|
name: home-podman-testdir
|
|
status: {}
|
|
"
|
|
|
|
RELABEL="system_u:object_r:container_file_t:s0"
|
|
|
|
@test "podman play with stdin" {
|
|
TESTDIR=$PODMAN_TMPDIR/testdir
|
|
mkdir -p $TESTDIR
|
|
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
|
|
|
|
run_podman play kube - < $PODMAN_TMPDIR/test.yaml
|
|
if [ -e /usr/sbin/selinuxenabled -a /usr/sbin/selinuxenabled ]; then
|
|
run ls -Zd $TESTDIR
|
|
is "$output" "${RELABEL} $TESTDIR" "selinux relabel should have happened"
|
|
fi
|
|
|
|
# Make sure that the K8s pause image isn't pulled but the local podman-pause is built.
|
|
run_podman images
|
|
run_podman 1 image exists k8s.gcr.io/pause
|
|
run_podman version --format "{{.Server.Version}}-{{.Server.Built}}"
|
|
run_podman image exists localhost/podman-pause:$output
|
|
|
|
run_podman stop -a -t 0
|
|
run_podman pod rm -t 0 -f test_pod
|
|
}
|
|
|
|
@test "podman play" {
|
|
TESTDIR=$PODMAN_TMPDIR/testdir
|
|
mkdir -p $TESTDIR
|
|
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
|
|
run_podman play kube $PODMAN_TMPDIR/test.yaml
|
|
if [ -e /usr/sbin/selinuxenabled -a /usr/sbin/selinuxenabled ]; then
|
|
run ls -Zd $TESTDIR
|
|
is "$output" "${RELABEL} $TESTDIR" "selinux relabel should have happened"
|
|
fi
|
|
|
|
run_podman stop -a -t 0
|
|
run_podman pod rm -t 0 -f test_pod
|
|
}
|
|
|
|
@test "podman play --service-container" {
|
|
skip_if_remote "service containers only work locally"
|
|
|
|
# Create the YAMl file
|
|
yaml_source="$PODMAN_TMPDIR/test.yaml"
|
|
cat >$yaml_source <<EOF
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
labels:
|
|
app: test
|
|
name: test_pod
|
|
spec:
|
|
containers:
|
|
- command:
|
|
- top
|
|
image: $IMAGE
|
|
name: test
|
|
resources: {}
|
|
EOF
|
|
run_podman play kube --service-container=true $yaml_source
|
|
|
|
# The name of the service container is predictable: the first 12 characters
|
|
# of the hash of the YAML file followed by the "-service" suffix
|
|
yaml_sha=$(sha256sum $yaml_source)
|
|
service_container="${yaml_sha:0:12}-service"
|
|
|
|
# Make sure that the service container exists and runs.
|
|
run_podman container inspect $service_container --format "{{.State.Running}}"
|
|
is "$output" "true"
|
|
|
|
# Stop the *main* container and make sure that
|
|
# 1) The pod transitions to Exited
|
|
# 2) The service container is stopped
|
|
# #) The service container is marked as an service container
|
|
run_podman stop test_pod-test
|
|
_ensure_pod_state test_pod Exited
|
|
_ensure_container_running $service_container false
|
|
run_podman container inspect $service_container --format "{{.IsService}}"
|
|
is "$output" "true"
|
|
|
|
# Restart the pod, make sure the service is running again
|
|
run_podman pod restart test_pod
|
|
run_podman container inspect $service_container --format "{{.State.Running}}"
|
|
is "$output" "true"
|
|
|
|
# Check for an error when trying to remove the service container
|
|
run_podman 125 container rm $service_container
|
|
is "$output" "Error: container .* is the service container of pod(s) .* and cannot be removed without removing the pod(s)"
|
|
|
|
# Kill the pod and make sure the service is not running
|
|
run_podman pod kill test_pod
|
|
_ensure_container_running $service_container false
|
|
|
|
# Remove the pod and make sure the service is removed along with it
|
|
run_podman pod rm test_pod
|
|
run_podman 1 container exists $service_container
|
|
}
|
|
|
|
@test "podman play --network" {
|
|
TESTDIR=$PODMAN_TMPDIR/testdir
|
|
mkdir -p $TESTDIR
|
|
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
|
|
run_podman 125 play kube --network host $PODMAN_TMPDIR/test.yaml
|
|
is "$output" ".*invalid value passed to --network: bridge or host networking must be configured in YAML" "podman plan-network should fail with --network host"
|
|
run_podman play kube --network slirp4netns:port_handler=slirp4netns $PODMAN_TMPDIR/test.yaml
|
|
run_podman pod inspect --format {{.InfraContainerID}} "${lines[1]}"
|
|
infraID="$output"
|
|
run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID
|
|
is "$output" "slirp4netns" "network mode slirp4netns is set for the container"
|
|
|
|
run_podman stop -a -t 0
|
|
run_podman pod rm -t 0 -f test_pod
|
|
|
|
run_podman play kube --network none $PODMAN_TMPDIR/test.yaml
|
|
run_podman pod inspect --format {{.InfraContainerID}} "${lines[1]}"
|
|
infraID="$output"
|
|
run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID
|
|
is "$output" "none" "network mode none is set for the container"
|
|
|
|
run_podman stop -a -t 0
|
|
run_podman pod rm -t 0 -f test_pod
|
|
}
|
|
|
|
@test "podman play with user from image" {
|
|
TESTDIR=$PODMAN_TMPDIR/testdir
|
|
mkdir -p $TESTDIR
|
|
|
|
testUserYaml="
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
labels:
|
|
app: test
|
|
name: test_pod
|
|
spec:
|
|
containers:
|
|
- command:
|
|
- id
|
|
env:
|
|
- name: PATH
|
|
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
- name: TERM
|
|
value: xterm
|
|
- name: container
|
|
value: podman
|
|
image: userimage
|
|
name: test
|
|
resources: {}
|
|
status: {}
|
|
"
|
|
|
|
cat > $PODMAN_TMPDIR/Containerfile << _EOF
|
|
from $IMAGE
|
|
USER bin
|
|
_EOF
|
|
|
|
echo "$testUserYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
|
|
run_podman build -t userimage $PODMAN_TMPDIR
|
|
run_podman play kube --start=false $PODMAN_TMPDIR/test.yaml
|
|
run_podman inspect --format "{{ .Config.User }}" test_pod-test
|
|
is "$output" bin "expect container within pod to run as the bin user"
|
|
|
|
run_podman stop -a -t 0
|
|
run_podman pod rm -t 0 -f test_pod
|
|
run_podman rmi -f userimage:latest
|
|
}
|
|
|
|
@test "podman play --build --context-dir" {
|
|
skip_if_remote "--build is not supported in context remote"
|
|
testUserYaml="
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
labels:
|
|
app: test
|
|
name: test_pod
|
|
spec:
|
|
containers:
|
|
- command:
|
|
- id
|
|
env:
|
|
- name: PATH
|
|
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
- name: TERM
|
|
value: xterm
|
|
- name: container
|
|
value: podman
|
|
image: quay.io/libpod/userimage
|
|
name: test
|
|
resources: {}
|
|
status: {}
|
|
"
|
|
|
|
mkdir -p $PODMAN_TMPDIR/userimage
|
|
cat > $PODMAN_TMPDIR/userimage/Containerfile << _EOF
|
|
from $IMAGE
|
|
USER bin
|
|
_EOF
|
|
|
|
echo "$testUserYaml" > $PODMAN_TMPDIR/test.yaml
|
|
run_podman 125 play kube --build --start=false $PODMAN_TMPDIR/test.yaml
|
|
run_podman play kube --replace --context-dir=$PODMAN_TMPDIR --build --start=false $PODMAN_TMPDIR/test.yaml
|
|
run_podman inspect --format "{{ .Config.User }}" test_pod-test
|
|
is "$output" bin "expect container within pod to run as the bin user"
|
|
|
|
run_podman stop -a -t 0
|
|
run_podman pod rm -t 0 -f test_pod
|
|
run_podman rmi -f userimage:latest
|
|
|
|
cd $PODMAN_TMPDIR
|
|
run_podman play kube --replace --build --start=false $PODMAN_TMPDIR/test.yaml
|
|
run_podman inspect --format "{{ .Config.User }}" test_pod-test
|
|
is "$output" bin "expect container within pod to run as the bin user"
|
|
|
|
run_podman stop -a -t 0
|
|
run_podman pod rm -t 0 -f test_pod
|
|
run_podman rmi -f userimage:latest
|
|
}
|
|
|
|
@test "podman play --annotation" {
|
|
TESTDIR=$PODMAN_TMPDIR/testdir
|
|
RANDOMSTRING=$(random_string 15)
|
|
mkdir -p $TESTDIR
|
|
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
|
|
run_podman play kube --annotation "name=$RANDOMSTRING" $PODMAN_TMPDIR/test.yaml
|
|
run_podman inspect --format "{{ .Config.Annotations }}" test_pod-test
|
|
is "$output" ".*name:$RANDOMSTRING" "Annotation should be added to pod"
|
|
|
|
run_podman stop -a -t 0
|
|
run_podman pod rm -t 0 -f test_pod
|
|
}
|
|
|
|
@test "podman play --annotation > Max" {
|
|
TESTDIR=$PODMAN_TMPDIR/testdir
|
|
RANDOMSTRING=$(random_string 65)
|
|
mkdir -p $TESTDIR
|
|
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
|
|
run_podman 125 play kube --annotation "name=$RANDOMSTRING" $PODMAN_TMPDIR/test.yaml
|
|
assert "$output" =~ "annotation exceeds maximum size, 63, of kubernetes annotation:" "Expected to fail with Length greater than 63"
|
|
}
|
|
|
|
@test "podman play Yaml with annotation > Max" {
|
|
RANDOMSTRING=$(random_string 65)
|
|
testBadYaml="
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
annotations:
|
|
test: ${RANDOMSTRING}
|
|
labels:
|
|
app: test
|
|
name: test_pod
|
|
spec:
|
|
containers:
|
|
- command:
|
|
- id
|
|
env:
|
|
- name: PATH
|
|
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
- name: TERM
|
|
value: xterm
|
|
- name: container
|
|
|
|
value: podman
|
|
image: quay.io/libpod/userimage
|
|
name: test
|
|
resources: {}
|
|
status: {}
|
|
"
|
|
TESTDIR=$PODMAN_TMPDIR/testdir
|
|
mkdir -p $TESTDIR
|
|
echo "$testBadYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
|
|
|
|
run_podman 125 play kube - < $PODMAN_TMPDIR/test.yaml
|
|
assert "$output" =~ "invalid annotation \"test\"=\"$RANDOMSTRING\"" "Expected to fail with annotation length greater than 63"
|
|
}
|
|
|
|
@test "podman play kube - default log driver" {
|
|
TESTDIR=$PODMAN_TMPDIR/testdir
|
|
mkdir -p $TESTDIR
|
|
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
|
|
# Get the default log driver
|
|
run_podman info --format "{{.Host.LogDriver}}"
|
|
default_driver=$output
|
|
|
|
# Make sure that the default log driver is used
|
|
run_podman play kube $PODMAN_TMPDIR/test.yaml
|
|
run_podman inspect --format "{{.HostConfig.LogConfig.Type}}" test_pod-test
|
|
is "$output" "$default_driver" "play kube uses default log driver"
|
|
|
|
run_podman stop -a -t 0
|
|
run_podman pod rm -t 0 -f test_pod
|
|
}
|