diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:04:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:04:41 +0000 |
commit | 975f66f2eebe9dadba04f275774d4ab83f74cf25 (patch) | |
tree | 89bd26a93aaae6a25749145b7e4bca4a1e75b2be /ansible_collections/containers/podman/tests | |
parent | Initial commit. (diff) | |
download | ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.tar.xz ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.zip |
Adding upstream version 7.7.0+dfsg.upstream/7.7.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/containers/podman/tests')
72 files changed, 8122 insertions, 0 deletions
diff --git a/ansible_collections/containers/podman/tests/.gitignore b/ansible_collections/containers/podman/tests/.gitignore new file mode 100644 index 000000000..ea1472ec1 --- /dev/null +++ b/ansible_collections/containers/podman/tests/.gitignore @@ -0,0 +1 @@ +output/ diff --git a/ansible_collections/containers/podman/tests/integration/targets/__init__.py b/ansible_collections/containers/podman/tests/integration/targets/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/__init__.py diff --git a/ansible_collections/containers/podman/tests/integration/targets/connection/create-nonroot-user.yml b/ansible_collections/containers/podman/tests/integration/targets/connection/create-nonroot-user.yml new file mode 100644 index 000000000..8669cfe35 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/connection/create-nonroot-user.yml @@ -0,0 +1,7 @@ +- hosts: "{{ target_hosts }}" + gather_facts: false + tasks: + + - name: Create a user + user: + name: testuser diff --git a/ansible_collections/containers/podman/tests/integration/targets/connection/test_connection.yml b/ansible_collections/containers/podman/tests/integration/targets/connection/test_connection.yml new file mode 100644 index 000000000..65f7e114d --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/connection/test_connection.yml @@ -0,0 +1,43 @@ +- hosts: "{{ target_hosts }}" + gather_facts: false + serial: 1 + tasks: + + ### raw with unicode arg and output + + - name: raw with unicode arg and output + raw: echo 汉语 + register: command + - name: check output of raw with unicode arg and output + assert: + that: + - "'汉语' in command.stdout" + - command is changed # as of 2.2, raw should default to changed: true for consistency w/ shell/command/script modules + + ### copy local file with unicode filename and content + + - name: create local file with unicode filename and content + local_action: lineinfile dest={{ local_tmp }}-汉语/汉语.txt create=true line=汉语 + - name: remove remote file with unicode filename and content + action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语/汉语.txt state=absent" + - name: create remote directory with unicode name + action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语 state=directory" + - name: copy local file with unicode filename and content + action: "{{ action_prefix }}copy src={{ local_tmp }}-汉语/汉语.txt dest={{ remote_tmp }}-汉语/汉语.txt" + + ### fetch remote file with unicode filename and content + + - name: remove local file with unicode filename and content + local_action: file path={{ local_tmp }}-汉语/汉语.txt state=absent + - name: fetch remote file with unicode filename and content + fetch: src={{ remote_tmp }}-汉语/汉语.txt dest={{ local_tmp }}-汉语/汉语.txt fail_on_missing=true validate_checksum=true flat=true + + ### remove local and remote temp files + + - name: remove local temp file + local_action: file path={{ local_tmp }}-汉语 state=absent + - name: remove remote temp file + action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语 state=absent" + + ### test wait_for_connection plugin + - wait_for_connection: diff --git a/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/runme.sh b/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/runme.sh new file mode 100755 index 000000000..b7fbcff45 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/runme.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +set -o pipefail +set -eux + +# New requirement from ansible-core 2.14 +export LC_ALL=en_US.UTF-8 +export LANG=en_US.UTF-8 +export LANGUAGE=en_US.UTF-8 + +function run_ansible { + ${SUDO:-} ${ANSIBLECMD:-ansible-playbook} ../connection/test_connection.yml -i "test_connection.inventory" \ + -e target_hosts="buildah" \ + -e action_prefix= \ + -e local_tmp=/tmp/ansible-local \ + -e remote_tmp=/tmp/ansible-remote \ + "$@" + +} + +# Issue in buildah: https://github.com/containers/buildah/issues/3126 +# Hack is from: https://github.com/containers/buildah/issues/3120#issuecomment-815889314 +# PR is merged here: https://github.com/containers/storage/pull/871 +export STORAGE_OPTS="overlay.mount_program=/usr/bin/fuse-overlayfs" +# First run as root +run_ansible "$@" + +# Create a non-root user +${SUDO:-} ${ANSIBLECMD:-ansible-playbook} -i "test_connection.inventory" ../connection/create-nonroot-user.yml \ + -e target_hosts="buildah" + +# Second run as normal user +ANSIBLE_VERBOSITY=4 ANSIBLE_REMOTE_USER="testuser" run_ansible "$@" | tee check_log +${SUDO:-} grep -q "Using buildah connection from collection" check_log +${SUDO:-} rm -f check_log diff --git a/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/test_connection.inventory b/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/test_connection.inventory new file mode 100644 index 000000000..e6d090ee4 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/test_connection.inventory @@ -0,0 +1,12 @@ +[buildah] +buildah-container ansible_ssh_pipelining=true +[buildah:vars] +# 1. install buildah +# 2. create container: +# $ sudo buildah from --name=buildah-container python:2 +# 3. run test: +# $ ansible-test integration connection_buildah +# 6. remove container +# $ sudo buildah rm buildah-container +ansible_host=buildah-container +ansible_connection=containers.podman.buildah diff --git a/ansible_collections/containers/podman/tests/integration/targets/connection_podman/runme.sh b/ansible_collections/containers/podman/tests/integration/targets/connection_podman/runme.sh new file mode 100755 index 000000000..598794e71 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/connection_podman/runme.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +set -o pipefail +set -eux + +function run_ansible { + ${SUDO:-} ${ANSIBLECMD:-ansible-playbook} ../connection/test_connection.yml -i "test_connection.inventory" \ + -e target_hosts="podman" \ + -e action_prefix= \ + -e local_tmp=/tmp/ansible-local \ + -e remote_tmp=/tmp/ansible-remote \ + "$@" + +} + +run_ansible "$@" +LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 run_ansible "$@" +ANSIBLE_VERBOSITY=4 ANSIBLE_REMOTE_TMP="/tmp" ANSIBLE_REMOTE_USER="1000" run_ansible "$@" | tee check_log +${SUDO:-} grep -q "Using podman connection from collection" check_log +${SUDO:-} rm -f check_log +set +o pipefail +ANSIBLE_PODMAN_EXECUTABLE=fakepodman run_ansible "$@" 2>&1 | grep "fakepodman command not found in PATH" +set -o pipefail +ANSIBLE_PODMAN_EXECUTABLE=fakepodman run_ansible "$@" && { + echo "Playbook with fakepodman should fail!" + exit 1 +} +ANSIBLE_VERBOSITY=4 ANSIBLE_PODMAN_EXTRA_ARGS=" --log-level debug " run_ansible "$@" | grep "level=debug msg=" diff --git a/ansible_collections/containers/podman/tests/integration/targets/connection_podman/test_connection.inventory b/ansible_collections/containers/podman/tests/integration/targets/connection_podman/test_connection.inventory new file mode 100644 index 000000000..c64c399f6 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/connection_podman/test_connection.inventory @@ -0,0 +1,15 @@ +[podman] +podman-container +[podman:vars] +# 1. install podman +# 2. create container: +# podman pull python:3-alpine +# podman run -d --name podman-container python:3-alpine sleep 999999 +# 3. run test: +# ./bin/ansible-test integration connection_podman +# 6. remove container +# podman stop podman-container +# podman rm podman-container +ansible_host=podman-container +ansible_connection=containers.podman.podman +ansible_python_interpreter=/usr/local/bin/python diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container/tasks/main.yml new file mode 100644 index 000000000..3a66f6a82 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container/tasks/main.yml @@ -0,0 +1,800 @@ +- name: Test podman_container + block: + - name: Delete all container leftovers from tests + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - "alpine:3.7" + - "container" + - "container1" + - "container2" + - "container3" + - "testidem-pod" + + - name: Test no image with default action + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + ignore_errors: true + register: no_image + + - name: Test no image with state 'started' + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: created + ignore_errors: true + register: no_image1 + + - name: Test no image with state 'present' + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: present + ignore_errors: true + register: no_image2 + + - name: Check no image + assert: + that: + - no_image is failed + - no_image1 is failed + - no_image2 is failed + - no_image.msg == "Cannot start container when image is not specified!" + - no_image1.msg == "State 'created' required image to be configured!" + - no_image2.msg == "State 'present' required image to be configured!" + fail_msg: No image test failed! + success_msg: No image test passed! + + - name: Ensure image doesn't exist + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: alpine:3.7 + state: absent + + - name: Check pulling image + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: alpine:3.7 + state: started + command: sleep 1d + register: image + + - name: Check using already pulled image + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container2 + image: alpine:3.7 + state: started + command: sleep 1d + register: image2 + + - name: Check output is correct + assert: + that: + - image is changed + - image.container is defined + - image.container['State']['Running'] + - "'pulled image alpine:3.7' in image.actions" + - "'started container' in image.actions" + - image2 is changed + - image2.container is defined + - image2.container['State']['Running'] + - "'pulled image alpine:3.7' not in image2.actions" + - "'started container2' in image2.actions" + fail_msg: Pulling image test failed! + success_msg: Pulling image test passed! + + - name: Check failed image pull + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: ineverneverneverexist + state: started + command: sleep 1d + register: imagefail + ignore_errors: true + + - name: Check output is correct + assert: + that: + - imagefail is failed + - imagefail.msg == "Can't pull image ineverneverneverexist" + + - name: Force container recreate + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: alpine + state: started + command: sleep 1d + recreate: true + register: recreated + + - name: Check output is correct + assert: + that: + - recreated is changed + - recreated.container is defined + - recreated.container['State']['Running']|bool + - "'recreated container' in recreated.actions" + fail_msg: Force recreate test failed! + success_msg: Force recreate test passed! + + - name: Start container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: started + + - name: Present container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: alpine + state: present + command: sleep 1d + register: start_present + + - name: Check output is correct + assert: + that: + - start_present.container['State']['Running'] + + - name: Stop container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: stopped + register: stopped + + - name: Stop the same container again (idempotency) + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: stopped + register: stopped_again + + - name: Check output is correct + assert: + that: + - stopped is changed + - stopped.container is defined + - not stopped.container['State']['Running'] + - "'stopped container' in stopped.actions" + - stopped_again is not changed + - stopped_again.container is defined + - not stopped_again.container['State']['Running'] + - stopped_again.actions == [] + fail_msg: Stopping container test failed! + success_msg: Stopping container test passed! + + - name: Delete stopped container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: absent + register: deleted + + - name: Delete again container (idempotency) + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: absent + register: deleted_again + + - name: Check output is correct + assert: + that: + - deleted is changed + - deleted.container is defined + - deleted.container == {} + - "'deleted container' in deleted.actions" + - deleted_again is not changed + - deleted_again.container is defined + - deleted_again.container == {} + - deleted_again.actions == [] + fail_msg: Deleting stopped container test failed! + success_msg: Deleting stopped container test passed! + + - name: Create container in 'stopped' state + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: alpine:3.7 + state: stopped + command: sleep 1d + register: created + + - name: Check output is correct + assert: + that: + - created is changed + - created.container is defined + - created.container != {} + - not created.container['State']['Running'] + - "'created container' in created.actions" + fail_msg: "Creating stopped container test failed!" + success_msg: "Creating stopped container test passed!" + + - name: Delete created container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: absent + + - name: Create container in 'created' state + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: alpine:3.7 + state: created + command: sleep 1d + register: created + + - name: Check output is correct + assert: + that: + - created is changed + - created.container is defined + - created.container != {} + - not created.container['State']['Running'] + - "'created container' in created.actions" + fail_msg: "Creating stopped container test failed!" + success_msg: "Creating stopped container test passed!" + + - name: Force container recreate + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: alpine + state: created + command: sleep 1d + recreate: true + register: recreated + + - name: Check output is correct + assert: + that: + - recreated is changed + - recreated.container is defined + - not recreated.container['State']['Running'] + - "'recreated container' in recreated.actions" + fail_msg: Force recreate test failed! + + - name: Restart container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + restart: true + register: restarted + + - name: Check output is correct + assert: + that: + - restarted is changed + - restarted.container is defined + - restarted.container['State']['Running'] + - "'restarted container' in restarted.actions" + fail_msg: Restart container test failed! + + - name: Restart running container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + restart: true + register: restarted + + - name: Check output is correct + assert: + that: + - restarted is changed + - restarted.container is defined + - restarted.container['State']['Running'] + - "'restarted container' in restarted.actions" + fail_msg: Restart running container test failed! + + - name: Delete created container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: absent + + - name: Start container that was deleted + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: alpine:3.7 + state: started + command: sleep 1d + register: started + + - name: Check output is correct + assert: + that: + - started is changed + - started.container is defined + - started.container['State']['Running'] + - "'pulled image alpine:3.7' not in started.actions" + + - name: Delete started container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: absent + register: deleted + + - name: Delete again container (idempotency) + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: absent + register: deleted_again + + - name: Check output is correct + assert: + that: + - deleted is changed + - deleted.container is defined + - deleted.container == {} + - "'deleted container' in deleted.actions" + - deleted_again is not changed + - deleted_again.container is defined + - deleted_again.container == {} + - deleted_again.actions == [] + fail_msg: Deleting started container test failed! + success_msg: Deleting started container test passed! + + - name: Recreate container with parameters + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: docker.io/alpine:3.7 + state: started + command: sleep 1d + recreate: true + etc_hosts: + host1: 127.0.0.1 + host2: 127.0.0.1 + annotation: + this: "annotation_value" + dns: + - 1.1.1.1 + - 8.8.4.4 + dns_search: example.com + cap_add: + - SYS_TIME + - NET_ADMIN + publish: + - "9000:80" + - "9001:8000" + workdir: "/bin" + env: + FOO: bar=1 + BAR: foo + TEST: 1 + BOOL: false + label: + somelabel: labelvalue + otheralbe: othervalue + volumes: + - /tmp:/data + mounts: + - type=devpts,destination=/dev/pts + register: test + + - name: Check output is correct + assert: + that: + - test is changed + - test.container is defined + - test.container != {} + - test.container['State']['Running'] + # test capabilities + - "'CAP_SYS_TIME' in test.container['BoundingCaps']" + - "'CAP_NET_ADMIN' in test.container['BoundingCaps']" + # test annotations + - test.container['Config']['Annotations']['this'] is defined + - test.container['Config']['Annotations']['this'] == "annotation_value" + # test DNS + - >- + (test.container['HostConfig']['Dns'] is defined and + test.container['HostConfig']['Dns'] == ['1.1.1.1', '8.8.4.4']) or + (test.container['HostConfig']['DNS'] is defined and + test.container['HostConfig']['DNS'] == ['1.1.1.1', '8.8.4.4']) + # test ports + - test.container['NetworkSettings']['Ports']|length == 2 + # test working dir + - test.container['Config']['WorkingDir'] == "/bin" + # test dns search + - >- + (test.container['HostConfig']['DnsSearch'] is defined and + test.container['HostConfig']['DnsSearch'] == ['example.com']) or + (test.container['HostConfig']['DNSSearch'] is defined and + test.container['HostConfig']['DNSSearch'] == ['example.com']) + # test environment variables + - "'FOO=bar=1' in test.container['Config']['Env']" + - "'BAR=foo' in test.container['Config']['Env']" + - "'TEST=1' in test.container['Config']['Env']" + - "'BOOL=False' in test.container['Config']['Env']" + # test labels + - test.container['Config']['Labels'] | length == 2 + - test.container['Config']['Labels']['somelabel'] == "labelvalue" + - test.container['Config']['Labels']['otheralbe'] == "othervalue" + # test mounts + - test.container['Mounts'][0]['Type'] is defined and test.container['Mounts'][0]['Type'] == 'bind' + - >- + test.container['Mounts'][0]['Source'] is defined and test.container['Mounts'][0]['Source'] == 'devpts' or + test.container['Mounts'][1]['Source'] is defined and test.container['Mounts'][1]['Source'] == 'devpts' + - >- + test.container['Mounts'][0]['Destination'] is defined and test.container['Mounts'][0]['Destination'] == '/dev/pts' or + test.container['Mounts'][1]['Destination'] is defined and test.container['Mounts'][1]['Destination'] == '/dev/pts' + # test volumes + # test volumes + - >- + (test.container['Mounts'][0]['Destination'] is defined and + '/data' in test.container['Mounts'] | map(attribute='Destination') | list) + - >- + (test.container['Mounts'][1]['Source'] is defined and + '/tmp' in test.container['Mounts'] | map(attribute='Source') | list) + fail_msg: Parameters container test failed! + success_msg: Parameters container test passed! + + - name: Check basic idempotency of running container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testidem + image: docker.io/alpine + state: started + command: sleep 20m + + - name: Check basic idempotency of running container - run it again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testidem + image: alpine:latest + state: started + command: sleep 20m + register: idem + + - name: Check that nothing was changed + assert: + that: + - not idem.changed + + - name: Check force restart option - run again and force restart + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testidem + image: alpine:latest + state: started + command: sleep 20m + force_restart: true + register: idem_r + + - name: Check that task was changed + assert: + that: + - idem_r is changed + + - name: Check removing force_restart option + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testidem + image: alpine:latest + state: started + command: sleep 20m + register: idem_r1 + + - name: Check that task was not changed + assert: + that: + - idem_r1 is not changed + + - name: Run changed container (with tty enabled) + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testidem + image: alpine + state: started + command: sleep 20m + tty: true + register: idem1 + + - name: Check that container is recreated when changed + assert: + that: + - idem1 is changed + + - name: Run changed container without specifying an option, use defaults + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testidem + image: alpine + state: started + command: sleep 20m + register: idem2 + + - name: Check that container is recreated when changed to default value + assert: + that: + - idem2 is changed + + - name: Remove container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testidem + state: absent + register: remove + + - name: Check podman_actions + assert: + that: + - "'podman rm -f testidem' in remove.podman_actions" + + # - name: Create a pod + # shell: podman pod create --name testidempod + + - name: Check basic idempotency of pod container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testidem-pod + image: docker.io/alpine + state: started + command: sleep 20m + pod: "new:testidempod" + + - name: Check basic idempotency of pod container - run it again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testidem-pod + image: alpine:latest + state: started + command: sleep 20m + pod: testidempod + register: idem3 + + - name: Check that nothing was changed in pod containers + assert: + that: + - not idem3.changed + + - name: Run changed pod container (with tty enabled) + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testidem-pod + image: alpine + state: started + command: sleep 20m + tty: true + pod: testidempod + register: idem4 + + - name: Check that container is recreated when changed + assert: + that: + - idem4 is changed + - idem4.podman_systemd.keys() | list | length > 0 + - idem4.podman_systemd.values() | list | length > 0 + + - name: Run container with systemd generation parameters + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container1 + image: alpine + state: started + command: sleep 20m + generate_systemd: + path: /tmp/ + restart_policy: always + time: 120 + no_header: true + names: true + pod_prefix: whocares + separator: zzzz + container_prefix: contain + register: system1 + + - name: Check service file presents + stat: + path: /tmp/containzzzzcontainer1.service + register: service_file + + - name: Check that container has correct systemd output + assert: + that: + - system1.podman_systemd.keys() | list | first == 'containzzzzcontainer1' + - system1.podman_systemd.values() | list | length > 0 + - service_file.stat.exists | bool + - "'-t 120 container1' in system1.podman_systemd.values() | list | first" + - "'Restart=always' in system1.podman_systemd.values() | list | first" + - "'autogenerated by Podman' not in system1.podman_systemd.values() | list | first" + + - name: Delete container with systemd generation parameters + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container1 + image: alpine + state: absent + command: sleep 20m + generate_systemd: + path: /tmp/ + restart_policy: always + time: 120 + no_header: true + names: true + pod_prefix: whocares + separator: zzzz + container_prefix: contain + register: system1 + + - name: Check service file doesn't present + stat: + path: /tmp/containzzzzcontainer1.service + register: service2_file + + - name: Check that service file was deleted + assert: + that: + - not service2_file.stat.exists | bool + + - name: Create temporary rootfs directory + ansible.builtin.tempfile: + state: directory + suffix: container-rootfs + register: container_tempdir + - name: Debug container_tempdir + ansible.builtin.debug: + var: container_tempdir + + - name: Download alpine releases file + ansible.builtin.get_url: + url: "https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/{{ ansible_architecture }}/latest-releases.yaml" + dest: "{{ container_tempdir.path }}/latest-releases.yaml" + register: alpine_releases_file + + - name: Download alpine latest rootfs + vars: + latest_releases: "{{ lookup('file', alpine_releases_file.dest) }}" + latest_version: "{{ (latest_releases | from_yaml)[0].version }}" + latest_branch: "{{ (latest_releases | from_yaml)[0].branch }}" + ansible.builtin.unarchive: + src: "https://dl-cdn.alpinelinux.org/alpine/{{ latest_branch }}/releases/{{ ansible_architecture }}/alpine-minirootfs-{{ latest_version }}-{{ ansible_architecture }}.tar.gz" + dest: "{{ container_tempdir.path }}" + remote_src: true + + - name: Check invalid rootfs image pull + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: /ineverneverneverexist + rootfs: true + state: started + command: sleep 1d + register: imagerootfsfail + ignore_errors: true + + - name: Check output is correct + assert: + that: + - imagerootfsfail is failed + - imagerootfsfail.msg == "Image rootfs doesn't exist /ineverneverneverexist" + + - name: Check rootfs container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container3 + image: "{{ container_tempdir.path }}" + rootfs: true + state: started + command: sleep 1d + register: image + + - name: Check output is correct + assert: + that: + - image is changed + - image.container is defined + - image.container['State']['Running'] + - image.container['Image'] == "" + - image.container['Rootfs'] == "{{ container_tempdir.path }}" + - "'started container3' in image.actions" + fail_msg: Rootfs container test failed! + success_msg: Rootfs container test passed! + + - name: Check basic idempotency of running rootfs container - run it again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container3 + image: "{{ container_tempdir.path }}" + rootfs: true + state: started + command: sleep 1d + register: idem + + - name: Check that nothing was changed + assert: + that: + - not idem.changed + + - name: Rebuild rootfs container with image + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container3 + image: alpine:3.7 + state: started + command: sleep 1d + register: image + + - name: Debug image + ansible.builtin.debug: + var: image + + - name: Check output is correct + assert: + that: + - image is changed + - image.container is defined + - image.container['State']['Running'] + - image.container['Rootfs'] == "" + - "'alpine:3.7' in image.container['ImageName']" + - "'recreated container3' in image.actions" + fail_msg: Rootfs container test failed! + success_msg: Rootfs container test passed! + + - name: Rebuild container with rootfs again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container3 + image: "{{ container_tempdir.path }}" + rootfs: true + state: started + command: sleep 1d + register: image + + - name: Check output is correct + assert: + that: + - image is changed + - image.container is defined + - image.container['State']['Running'] + - image.container['Image'] == "" + - image.container['Rootfs'] == "{{ container_tempdir.path }}" + - "'recreated container3' in image.actions" + fail_msg: Rootfs container test failed! + success_msg: Rootfs container test passed! + + always: + + - name: Remove container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testidem-pod + state: absent + + - name: Delete all container leftovers from tests + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - "alpine:3.7" + - "container" + - "container1" + - "container2" + - "container3" + - "testidem-pod" + + - name: Remove pod + shell: podman pod rm -f testidempod + ignore_errors: true + + - name: Remove temporary rootfs directory + ansible.builtin.file: + path: "{{ container_tempdir.path }}" + state: absent + when: container_tempdir is defined + ignore_errors: true diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/Dockerfile b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/Dockerfile new file mode 100644 index 000000000..a42fc5689 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/Dockerfile @@ -0,0 +1,32 @@ +FROM alpine + +LABEL "key"="amazing value" +LABEL nobody=cares + +ARG build_arg + +ENV password root +ENV username root + +WORKDIR /work + +RUN adduser -D user && \ + adduser -D user2 + +COPY start.sh /start + +RUN chmod a+rwx /start + +EXPOSE 80 +EXPOSE 8080/tcp +VOLUME ["/data", "/data2"] +USER user +STOPSIGNAL KILL + +# problem with OS w/o systemd +# HEALTHCHECK --interval=5m --timeout=3s \ +# CMD date + +CMD ["1d"] +ENTRYPOINT ["/start"] + diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/start.sh b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/start.sh new file mode 100755 index 000000000..1217239e6 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/start.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +s=${1:-"3h"} +sleep "$s" + diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/build_test_container.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/build_test_container.yml new file mode 100644 index 000000000..c23e41aa0 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/build_test_container.yml @@ -0,0 +1,35 @@ +--- +- name: Create directory for user build images + file: + path: /tmp/usr_img + state: directory + +- name: Copy files to container build directory + copy: + src: "{{ item }}" + dest: "/tmp/usr_img/{{ item }}" + mode: 777 + loop: + - Dockerfile + - start.sh + +- name: Build test docker image for regular user + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: "{{ idem_image }}" + path: /tmp/usr_img + build: + format: docker + extra_args: --cgroup-manager=cgroupfs + +- name: Build test docker image for root user + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: "{{ idem_image }}" + path: /tmp/usr_img + build: + format: docker + become: true + environment: + XDG_RUNTIME_DIR: "" + DBUS_SESSION_BUS_ADDRESS: "" diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_all.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_all.yml new file mode 100644 index 000000000..48247d71f --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_all.yml @@ -0,0 +1,339 @@ +# Other settings +- name: Remove leftovers from other tests + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency + state: absent + +- name: Run container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + +- name: Run container again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test1 + +- name: Check info when running container again + assert: + that: test1 is not changed + +- name: Run container with environment vars + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + env: + mykey: "amazing value" + ENV1: "one=two=three" + command: 1h + register: test2 + +- name: Check info with environment vars + assert: + that: test2 is changed + +- name: Run container with environment vars again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + env: + mykey: "amazing value" + ENV1: "one=two=three" + command: 1h + register: test3 + +- name: Check info with environment vars again + assert: + that: test3 is not changed + +- name: Run container with changed environment vars + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + env: + mykey: "amazing value1" + ENV1: "one=two=three" + command: 1h + register: test4 + +- name: Check info with changed environment vars + assert: + that: test4 is changed + +- name: Run container with log opt tag + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + log_opt: + tag: nonotag + log_driver: journald + command: 1h + register: test9 + +- name: Check info with log opt tag + assert: + that: test9 is changed + +- name: Run container with log opt tag - again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + log_opt: + tag: nonotag + log_driver: journald + command: 1h + register: test10 + +- name: Check info with log opt tag - again + assert: + that: test10 is not changed + +- name: Run container with default log opt tag + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + log_driver: journald + register: test11 + +- name: Check info with default log opt tag + assert: + that: test11 is changed + +- name: Run container with log opt path + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + log_opt: + path: /tmp/container.log + log_driver: journald + command: 1h + register: test12 + +- name: Check info with log opt path + assert: + that: test12 is changed + +- name: Run container with changed log opt path + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + log_opt: + path: /tmp/container2.log + log_driver: journald + command: 1h + register: test13 + +- name: Check info with changed log opt path + assert: + that: test13 is changed + +- name: Run container with default log opt path + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + log_driver: journald + command: 1h + register: test14 + +# We can't guess the default log path +- name: Check info with default log opt path + assert: + that: test14 is not changed + +- name: Run container with all log-opts + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + log_driver: journald + log_opt: + path: /tmp/container3.log + max_size: 100mb + tag: sometag + command: 1h + +- name: Run container with mounted /dev/fuse + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + device: + - /dev/fuse + register: test15 + +- name: Run container with mounted /dev/fuse again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + device: + - /dev/fuse + register: test16 + +- name: Run container with mounted /dev/fuse:/dev/fuse + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + device: + - /dev/fuse:/dev/fuse + register: test17 + +- name: Run container with mounted /dev/fuse third time + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + device: + - /dev/fuse + register: test18 + +- name: Run container without mounted device + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + register: test19 + +- name: Check info with mounted devices + assert: + that: + - test15 is changed + - test16 is not changed + - test17 is not changed + - test18 is not changed + - test19 is changed + +- name: Run container with etc_hosts + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + etc_hosts: + host1: 127.0.0.1 + host2: fd00::1 + command: 1h + register: test20 + +- name: Check info with etc_hosts + assert: + that: test20 is changed + +- name: Run container with etc_hosts again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + etc_hosts: + host1: 127.0.0.1 + host2: fd00::1 + command: 1h + register: test21 + +- name: Check info with etc_hosts again + assert: + that: test21 is not changed + +- name: Run default container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + +- name: Run container with restart policy always + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + restart_policy: always + register: test22 + +- name: Check info with restart policy always + assert: + that: test22 is changed + +- name: Run container with restart policy always again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + restart_policy: always + register: test23 + +- name: Check info with restart policy always again + assert: + that: test23 is not changed + +- name: Run container with a different restart policy on-failure + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + restart_policy: on-failure + register: test24 + +- name: Check info with restart policy on-failure + assert: + that: test24 is changed + +- name: Run default container w/o restart policy + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + register: test25 + +- name: Check info w/o restart policy + assert: + that: test25 is changed + +- name: Remove test container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency + state: absent diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_labels.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_labels.yml new file mode 100644 index 000000000..5d08d4505 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_labels.yml @@ -0,0 +1,200 @@ +# Labels +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test1 + +- name: check test1 + assert: + that: test1 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + label: + key: "amazing value" + nobody: "cares" + command: 1h + register: test2 + +- name: check test2 + assert: + that: test2 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test3 + +- name: check test3 + assert: + that: test3 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + label: + haha: kukuku + LLALA: WIWIWIW + OEIWIOP: eufslsa + ieui4: KDJSL4D + command: 1h + register: test4 + +- name: check test4 + assert: + that: test4 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + label: + haha: kukuku + LLALA: WIWIWIW + OEIWIOP: eufslsa + ieui4: KDJSL4D + command: 1h + register: test5 + +- name: check test5 + assert: + that: test5 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test6 + +- name: check test6 + assert: + that: test6 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + label: + test: notest + command: 1h + register: test7 + +- name: check test7 + assert: + that: test7 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + label: + key: "amazing value" + nobody: "cares" + command: 1h + register: test8 + +- name: check test8 + assert: + that: test8 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test9 + +- name: check test9 + assert: + that: test9 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency1 + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test10 + +- name: check test10 + assert: + that: test10 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + label: + razraz: dva + command: sleep 1h + register: test11 + +- name: check test11 + assert: + that: test11 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test12 + +- name: check test12 + assert: + that: test12 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test13 + +- name: check test13 + assert: + that: test13 is not changed diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_network_aliases.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_network_aliases.yml new file mode 100644 index 000000000..2da693cd7 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_network_aliases.yml @@ -0,0 +1,55 @@ +- name: Remove container netcontainer + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: netcontainer + state: absent + +- name: Run container with testnet and two aliases + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: netcontainer + image: "{{ idem_image }}" + command: 1h + state: started + network: testnet + network_aliases: + - netcontainer-alias-a + - netcontainer-alias-b + +- name: Run container again with testnet and same two aliases + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: netcontainer + image: "{{ idem_image }}" + command: 1h + state: present + network: testnet + network_aliases: + - netcontainer-alias-a + - netcontainer-alias-b + register: info + +- name: Check info for 2 runs of testnet + assert: + that: + - info is not changed + +- name: Run changed container with testnet and three aliases + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: netcontainer + image: "{{ idem_image }}" + command: 1h + state: present + network: testnet + network_aliases: + - netcontainer-alias-a + - netcontainer-alias-b + - netcontainer-alias-c + register: info1 + +- name: Check info + assert: + that: + - info1 is changed + ignore_errors: true diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_networks.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_networks.yml new file mode 100644 index 000000000..0eedfda66 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_networks.yml @@ -0,0 +1,44 @@ +- name: Remove container netcontainer + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: netcontainer + state: absent + +- name: Run container with {{ item.first_net }} + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: netcontainer + image: "{{ idem_image }}" + command: 1h + state: started + network: "{{ item.first_net }}" + +- name: Run container again with {{ item.first_net }} + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: netcontainer + image: "{{ idem_image }}" + command: 1h + state: present + network: "{{ item.first_net }}" + register: info + +- name: Check info for 2 runs of {{ item.first_net }} + assert: + that: + - info is not changed + +- name: Run changed container with {{ item.next_net }} + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: netcontainer + image: "{{ idem_image }}" + command: 1h + state: present + network: "{{ item.next_net }}" + register: info1 + +- name: Check info + assert: + that: + - info1 is changed diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_pods.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_pods.yml new file mode 100644 index 000000000..56e1e95d3 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_pods.yml @@ -0,0 +1,83 @@ +- name: Remove testing pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: testpod + state: absent + +- name: Remove test container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: testpod_container1 + state: absent + +- name: Create pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: testpod + publish: + - "11111:11111" + +- name: Start test container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: testpod_container1 + pod: testpod + state: started + label: + key: value + env: + test: test2 + volumes: + - /tmp:/data + +- name: Start test container again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: testpod_container1 + pod: testpod + state: started + label: + key: value + env: + test: test2 + volumes: + - /tmp:/data + register: info + +- name: Check starting container + assert: + that: info is not changed + +- name: Start test container changed + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: testpod_container1 + pod: testpod + state: started + register: info1 + +- name: Check starting container changed + assert: + that: info1 is changed + +- name: Start test container again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: testpod_container1 + pod: testpod + state: started + register: info2 + +- name: Check starting container again + assert: + that: info2 is not changed + +- name: Remove testing pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: testpod + state: absent diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_ports.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_ports.yml new file mode 100644 index 000000000..54a667c86 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_ports.yml @@ -0,0 +1,265 @@ +# Ports +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test1 + +- name: check test1 + assert: + that: test1 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + ports: + - "4444:4444/tcp" + - "1212:5555" + - "8888:19191/udp" + - "1900:1900/udp" + - "127.0.0.1:7671:7676/udp" + - "127.0.0.1:12122:8876/udp" + - "127.0.0.1:13122:8871/tcp" + - "127.0.0.1:43423:8872" + - "127.0.0.2:43423:8872/tcp" + - "127.0.0.3:43423:8872" + register: test2 + +- name: check test2 + assert: + that: test2 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + ports: + - "4444:4444/tcp" + - "1212:5555" + - "8888:19191/udp" + - "1900:1900/udp" + - "127.0.0.1:7671:7676/udp" + - "127.0.0.1:12122:8876/udp" + - "127.0.0.1:13122:8871/tcp" + - "127.0.0.1:43423:8872" + - "127.0.0.2:43423:8872/tcp" + - "127.0.0.3:43423:8872" + register: test3 + +- name: check test3 + assert: + that: test3 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + publish_all: true + command: 1h + register: test4 + +- name: check test4 + assert: + that: test4 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + publish_all: true + command: 1h + register: test5 + +- name: check test5 + assert: + that: test5 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test6 + +- name: check test6 + assert: + that: test6 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + ports: + - 10000:8080 + command: 1h + register: test7 + +- name: check test7 + assert: + that: test7 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + ports: + - 10001:8080 + command: 1h + register: test8 + +- name: check test8 + assert: + that: test8 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + ports: + - 10001:8080/tcp + command: 1h + register: test9 + +- name: check test9 + assert: + that: test9 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + ports: + - 10001:8080/tcp + publish_all: false + command: 1h + register: test9a + +- name: check test9a + assert: + that: test9a is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test9b + +- name: check test9b + assert: + that: test9b is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency1 + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test10 + +- name: check test10 + assert: + that: test10 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + publish_all: false + command: sleep 1h + register: test11 + +- name: check test11 + assert: + that: test11 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + publish_all: true + command: sleep 1h + register: test11a + +- name: check test11a + assert: + that: test11a is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + ports: + - 10000:8080 + command: sleep 1h + register: test12 + +- name: check test12 + assert: + that: test12 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test13 + +- name: check test13 + assert: + that: test13 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test14 + +- name: check test14 + assert: + that: test14 is not changed diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_stopsignal.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_stopsignal.yml new file mode 100644 index 000000000..98586aece --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_stopsignal.yml @@ -0,0 +1,224 @@ +# Stop signal +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test1 + +- name: check test1 + assert: + that: test1 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + stop_signal: 9 + command: 1h + register: test2 + +- name: check test2 + assert: + that: test2 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test3 + +- name: check test3 + assert: + that: test3 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + stop_signal: 10 + command: 1h + register: test4 + +- name: check test4 + assert: + that: test4 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + stop_signal: 10 + command: 1h + register: test5 + +- name: check test5 + assert: + that: test5 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test6 + +- name: check test6 + assert: + that: test6 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + stop_signal: 15 + command: 1h + register: test7 + +- name: check test7 + assert: + that: test7 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + stop_signal: 9 + command: 1h + register: test8 + +- name: check test8 + assert: + that: test8 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test9 + +- name: check test9 + assert: + that: test9 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + stop_signal: 15 + command: 1h + register: test9a + +- name: check test9a + assert: + that: test9a is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test9b + +- name: check test9b + assert: + that: test9b is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency1 + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test10 + +- name: check test10 + assert: + that: test10 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + stop_signal: 15 + command: sleep 1h + register: test11 + +- name: check test11 + assert: + that: test11 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + stop_signal: 10 + command: sleep 1h + register: test12 + +- name: check test12 + assert: + that: test12 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test13 + +- name: check test13 + assert: + that: test13 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test14 + +- name: check test14 + assert: + that: test14 is not changed diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_users.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_users.yml new file mode 100644 index 000000000..6be03bb1a --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_users.yml @@ -0,0 +1,186 @@ +# Users +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test1 + +- name: check test1 + assert: + that: test1 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + user: user + command: 1h + register: test2 + +- name: check test2 + assert: + that: test2 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test3 + +- name: check test3 + assert: + that: test3 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + user: user2 + command: 1h + register: test4 + +- name: check test4 + assert: + that: test4 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + user: user2 + command: 1h + register: test5 + +- name: check test5 + assert: + that: test5 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test6 + +- name: check test6 + assert: + that: test6 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + user: user2 + command: 1h + register: test7 + +- name: check test7 + assert: + that: test7 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + user: user + command: 1h + register: test8 + +- name: check test8 + assert: + that: test8 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test9 + +- name: check test9 + assert: + that: test9 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency1 + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test10 + +- name: check test10 + assert: + that: test10 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + user: nobody + command: sleep 1h + register: test11 + +- name: check test11 + assert: + that: test11 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test12 + +- name: check test12 + assert: + that: test12 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test13 + +- name: check test13 + assert: + that: test13 is not changed diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_volumes.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_volumes.yml new file mode 100644 index 000000000..3fff4e34a --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_volumes.yml @@ -0,0 +1,255 @@ +# Volumes +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test1 + +- name: check test1 + assert: + that: test1 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test2 + +- name: check test2 + assert: + that: test2 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test3 + +- name: check test3 + assert: + that: test3 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + volumes: + - /opt:/somedir/ + command: 1h + register: test4 + +- name: check test4 + assert: + that: test4 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + volumes: + - /opt/://somedir/ + command: 1h + register: test5 + +- name: check test5 + assert: + that: test5 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test6 + +- name: check test6 + assert: + that: test6 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + volumes: + - /opt:/somedir + - /data + command: 1h + register: test7 + +- name: check test7 + assert: + that: test7 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + volumes: + - /data + command: 1h + register: test8 + +- name: check test8 + assert: + that: test8 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test9 + +- name: check test9 + assert: + that: test9 is not changed + +- name: Create volumes + shell: | + podman volume inspect local_volume1 || podman volume create local_volume1 + podman volume inspect local_volume2 || podman volume create local_volume2 + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + volumes: + - "/opt:/anotherdir" + - "local_volume1:/data" + register: test10 + +- name: check test10 + assert: + that: test10 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + volumes: + - "/opt//:/anotherdir" + - "local_volume1:/data/" + register: test11 + +- name: check test11 + assert: + that: test11 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + volumes: + - "/opt:/anotherdir" + - "local_volume2:/data" + register: test12 + +- name: check test12 + assert: + that: test12 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + volumes: + - "/opt:/anotherdir" + register: test13 + +- name: check test13 + assert: + that: test13 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency1 + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test14 + +- name: check test14 + assert: + that: test14 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + volumes: + - /opt:/data + command: sleep 1h + register: test15 + +- name: check test15 + assert: + that: test15 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test16 + +- name: check test16 + assert: + that: test16 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test17 + +- name: check test17 + assert: + that: test17 is not changed diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_workdir.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_workdir.yml new file mode 100644 index 000000000..ef1103188 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_workdir.yml @@ -0,0 +1,224 @@ +# Workdir +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: started + command: 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test1 + +- name: check test1 + assert: + that: test1 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + workdir: /work + command: 1h + register: test2 + +- name: check test2 + assert: + that: test2 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test3 + +- name: check test3 + assert: + that: test3 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + workdir: /var + command: 1h + register: test4 + +- name: check test4 + assert: + that: test4 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + workdir: /var + command: 1h + register: test5 + +- name: check test5 + assert: + that: test5 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test6 + +- name: check test6 + assert: + that: test6 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + workdir: /var + command: 1h + register: test7 + +- name: check test7 + assert: + that: test7 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + workdir: /work + command: 1h + register: test8 + +- name: check test8 + assert: + that: test8 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test9 + +- name: check test9 + assert: + that: test9 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + workdir: / + command: 1h + register: test9a + +- name: check test9a + assert: + that: test9a is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: idempotency + state: present + command: 1h + register: test9b + +- name: check test9b + assert: + that: test9b is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: idempotency1 + state: absent + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test10 + +- name: check test10 + assert: + that: test10 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + workdir: / + command: sleep 1h + register: test11 + +- name: check test11 + assert: + that: test11 is not changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + workdir: /var + command: sleep 1h + register: test12 + +- name: check test12 + assert: + that: test12 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test13 + +- name: check test13 + assert: + that: test13 is changed + +- containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: alpine + name: idempotency1 + state: present + command: sleep 1h + register: test14 + +- name: check test14 + assert: + that: test14 is not changed diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/main.yml new file mode 100644 index 000000000..0b538ad85 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/main.yml @@ -0,0 +1,46 @@ +--- +- name: Prepare a container + include_tasks: build_test_container.yml + +- name: Test idempotency of users + include_tasks: idem_users.yml + +- name: Test idempotency of workdir + include_tasks: idem_workdir.yml + +- name: Test idempotency of labels + include_tasks: idem_labels.yml + +- name: Test idempotency of stop signal + include_tasks: idem_stopsignal.yml + +- name: Test idempotency of ports + include_tasks: idem_ports.yml + +- name: Test idempotency of volumes + include_tasks: idem_volumes.yml + +- name: Test idempotency of containers in pods + include_tasks: idem_pods.yml + +- name: Test idempotency of other settings + include_tasks: idem_all.yml + +- name: Test idempotency for root containers + include_tasks: root-podman.yml + vars: + ansible_python_interpreter: "/usr/bin/python" + args: + apply: + become: true + +- name: Test idempotency for root network containers + include_tasks: root-podman-network.yml + vars: + ansible_python_interpreter: "/usr/bin/python" + args: + apply: + become: true + +- name: Test idempotency for rootless network containers + include_tasks: rootless-podman-network.yml diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman-network.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman-network.yml new file mode 100644 index 000000000..6d5b7bb08 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman-network.yml @@ -0,0 +1,71 @@ +- name: Test podman rootful container with networks + block: + + - name: Remove container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: netcontainer + state: absent + + - name: Create network testnet + command: podman network create testnet --subnet 10.92.92.0/24 + + - name: Create network anothernet + command: podman network create anothernet --subnet 10.72.72.0/24 + + - name: List current networks + command: podman network ls + + - name: Set test data + set_fact: + testdata: + - first_net: host + next_net: bridge + - first_net: bridge + next_net: host + - first_net: none + next_net: host + - first_net: host + next_net: none + - first_net: anothernet + next_net: testnet + - first_net: testnet + next_net: + - testnet + - anothernet + - first_net: + - testnet + - anothernet + next_net: anothernet + - first_net: + - testnet + - anothernet + next_net: bridge + - first_net: + - testnet + - anothernet + next_net: host + - first_net: host + next_net: anothernet + - first_net: bridge + next_net: + - anothernet + - testnet + + - include_tasks: idem_networks.yml + loop: "{{ testdata }}" + + - include_tasks: idem_network_aliases.yml + + always: + + - name: Delete all pods leftovers from tests + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: netcontainer + state: absent + + - name: Delete all network leftovers from tests + shell: | + podman network rm -f anothernet + podman network rm -f testnet diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman.yml new file mode 100644 index 000000000..f41587367 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman.yml @@ -0,0 +1,213 @@ +--- +# Ulimits testing +- name: Make sure container doesn't exist + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: root-idempotency + state: absent + +- name: Run container as is + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: started + command: 1h + +- name: Run container as is again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: present + command: 1h + register: info_a + +- name: Check that it is not recreated + assert: + that: + - info_a is not changed + +- name: Run containers with ulimits + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: present + command: 1h + ulimit: + - 'nofile=55535:55535' + - 'memlock=-1:-1' + register: info + +- name: Check that it is recreated + assert: + that: + - info is changed + +- name: Run containers with ulimits - idempotency + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: present + command: 1h + ulimit: + - 'nofile=55535:55535' + - 'memlock=-1:-1' + register: info1 + +- name: Check that it is recreated + assert: + that: + - info1 is not changed + +- name: Run containers with changed ulimits + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: present + command: 1h + ulimit: + - 'nofile=55535:65535' + - 'memlock=-1:-1' + register: info2 + +- name: Check that it is recreated + assert: + that: + - info2 is changed + +- name: Run containers with changed ulimits - idempotency + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: present + command: 1h + ulimit: + - 'nofile=55535:65535' + - 'memlock=-1:-1' + register: info3 + +- name: Check that it is recreated + assert: + that: + - info3 is not changed + +- name: Run default container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: started + command: 1h + +- name: Run containers with MAC address + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: started + command: 1h + mac_address: 44:55:66:77:88:99 + register: info4 + +- name: Check that it is not recreated + assert: + that: + - info4 is changed + - info4.container['NetworkSettings']['MacAddress'] == '44:55:66:77:88:99' + +- name: Run containers with MAC address again - idempotency + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: present + command: 1h + mac_address: 44:55:66:77:88:99 + register: info5 + +- name: Check that it is not recreated + assert: + that: + - info5 is not changed + +- name: Run containers with MAC address changed + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: present + command: 1h + mac_address: 44:55:66:77:88:33 + register: info6 + +- name: Check that it is recreated + assert: + that: + - info6 is changed + +- name: Run again default container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: present + command: 1h + register: info7 + +- name: Check that it is recreated + assert: + that: + - info7 is not changed + +- name: Run container with publishing ports and ipv6 + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: present + command: 1h + ports: + - "4444:4444/tcp" + - "1212:5555" + - "8888:19191/udp" + - "127.0.0.1:7671:7676/udp" + - "127.0.0.3:43423:8872" + - "[::1]:34523:35425" + register: info8 + +- name: Check that it is recreated + assert: + that: + - info8 is changed + +- name: Run container with publishing ports and ipv6 again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + image: "{{ idem_image }}" + name: root-idempotency + state: present + command: 1h + ports: + - "4444:4444/tcp" + - "1212:5555" + - "8888:19191/udp" + - "127.0.0.1:7671:7676/udp" + - "127.0.0.3:43423:8872" + - "[::1]:34523:35425" + register: info9 + +- name: Check that it is recreated + assert: + that: + - info9 is not changed + +- name: Make sure container doesn't exist + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: root-idempotency + state: absent diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/rootless-podman-network.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/rootless-podman-network.yml new file mode 100644 index 000000000..62dd3a5a0 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/rootless-podman-network.yml @@ -0,0 +1,229 @@ +- name: Test podman rootful container with networks + block: + + - name: Remove container rootlessnet2 + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet2 + state: absent + + - name: Remove container rootlessnet + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + state: absent + + - name: Run container with no specified networks + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: started + + - name: Run container again with no specified networks + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: present + register: info + + - name: Check info for no specified networks + assert: + that: + - info is not changed + + - name: Run container with network mode host + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: present + network: host + register: info1 + + - name: Check info with network mode host + assert: + that: + - info1 is changed + + - name: Run container with network mode host again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: present + network: host + register: info2 + + - name: Check info with network mode host again + assert: + that: + - info2 is not changed + + - name: Run container without network at all + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: present + network: none + register: info3 + + - name: Check info without network at all + assert: + that: + - info3 is changed + + - name: Run container without network at all again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: present + network: none + register: info4 + + - name: Check info without network at all again + assert: + that: + - info4 is not changed + + - name: Run container with default network mode + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: present + register: info5 + + - name: Check info with default network mode + assert: + that: + - info5 is changed + + - name: Run container with slirp4netns options + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: present + network: + - slirp4netns:allow_host_loopback=true,cidr=10.0.3.0/24 + register: info6 + + - name: Check info with slirp4netns options + assert: + that: + - info6 is changed + + - name: Run container with slirp4netns options - again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: present + network: + - slirp4netns:allow_host_loopback=true,cidr=10.0.3.0/24 + register: info7 + + - name: Check info with slirp4netns options - again + assert: + that: + - info7 is not changed + + - name: Run container with different slirp4netns options + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: present + network: + - slirp4netns:allow_host_loopback=true,cidr=10.0.4.0/24 + register: info8 + + - name: Check info with different slirp4netns options + assert: + that: + - info8 is changed + + - name: Run container without options + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: present + register: info9 + + - name: Check info without options + assert: + that: + - info9 is changed + + - name: Run container without options - again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + image: "{{ idem_image }}" + command: 1h + state: present + register: info10 + + - name: Check info without options - again + assert: + that: + - info10 is not changed + + - name: Run container network attached to first one + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet2 + image: "{{ idem_image }}" + command: 1h + state: started + network: 'container:rootlessnet' + register: info11 + + - name: Check info container network attached to first one + assert: + that: + - info11 is changed + + - name: Run container network attached to first one - again + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet2 + image: "{{ idem_image }}" + command: 1h + state: started + network: 'container:rootlessnet' + register: info12 + + - name: Check info container network attached to first one - again + assert: + that: + - info12 is not changed + always: + + - name: Delete all containers leftovers from tests + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet2 + state: absent + + - name: Delete all containers leftovers from tests 2 + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: rootlessnet + state: absent diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_container_info/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_container_info/tasks/main.yml new file mode 100644 index 000000000..d62bf8f1b --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_container_info/tasks/main.yml @@ -0,0 +1,101 @@ +- name: Test podman_container_info + block: + + - name: Generate random value for container name + set_fact: + container_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}" + + - name: Make sure container doesn't exist + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: "{{ container_name }}" + state: absent + + - name: Get missing container info + containers.podman.podman_container_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ container_name }}" + register: nonexist + + - name: Check results of missing container info + assert: + that: + - "'containers' in nonexist" + - nonexist is succeeded + - nonexist.containers == [] + + - name: Get missing multiple container info + containers.podman.podman_container_info: + executable: "{{ test_executable | default('podman') }}" + name: + - "{{ container_name }}" + - neverexist + - whatever + register: nonexist2 + ignore_errors: true + + - name: Check results of missing multiple container info + assert: + that: + - "'containers' in nonexist2" + - nonexist2 is succeeded + - nonexist2.containers == [] + + - name: Make sure container exists + command: podman container run -d --name {{ container_name }} alpine sleep 15m + + - name: Get existing container info + containers.podman.podman_container_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ container_name }}" + register: existing_container + + - name: Get mixed existing and non-existing container info + containers.podman.podman_container_info: + executable: "{{ test_executable | default('podman') }}" + name: + - "{{ container_name }}" + - whatever + register: mixed_existing_container + + - name: Get all containers info + containers.podman.podman_container_info: + executable: "{{ test_executable | default('podman') }}" + register: all_containers + + - name: Dump podman container inspect result + debug: var=existing_container + + - name: Comparison with 'podman container inspect' + command: podman container inspect "{{ container_name }}" + register: podman_inspect + + - name: Convert podman inspect output to JSON + set_fact: + podman_inspect_result: "{{ podman_inspect.stdout | from_json }}" + + - name: Cleanup + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: "{{ container_name }}" + state: absent + + - name: Make checks + # https://github.com/containers/podman/issues/9490 + assert: + that: + - "'containers' in existing_container" + - existing_container.containers + # - "existing_container.containers == podman_inspect_result" + # - all_containers.containers == existing_container.containers + - "'containers' in mixed_existing_container" + - mixed_existing_container.containers + # - existing_container.containers == mixed_existing_container.containers + + always: + + - name: Cleanup + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: "{{ container_name }}" + state: absent diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_containers/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_containers/tasks/main.yml new file mode 100644 index 000000000..69c94b313 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_containers/tasks/main.yml @@ -0,0 +1,725 @@ +- name: Test multiple podman_containers + block: + - name: Delete all containers leftovers from tests + containers.podman.podman_containers: + containers: + - name: "alpine:3.7" + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: "container" + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: "container1" + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: "container2" + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: "container3" + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: "container4" + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: "testidem" + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: "testidem1" + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: "testidem2" + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: "testidem3" + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: "testidem-pod" + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: "testidem-pod2" + state: absent + executable: "{{ test_executable | default('podman') }}" + + - name: Test no image with default action + containers.podman.podman_containers: + containers: + - name: "container" + executable: "{{ test_executable | default('podman') }}" + - name: "container2" + executable: "{{ test_executable | default('podman') }}" + - name: "container3" + executable: "{{ test_executable | default('podman') }}" + image: alpine + ignore_errors: true + register: no_image + + - name: Test no image with state 'started' + containers.podman.podman_containers: + containers: + - name: "container" + state: started + executable: "{{ test_executable | default('podman') }}" + - name: "container2" + state: started + executable: "{{ test_executable | default('podman') }}" + ignore_errors: true + register: no_image1 + + - name: Test no image with state 'present' + containers.podman.podman_containers: + containers: + - name: "container" + state: present + executable: "{{ test_executable | default('podman') }}" + - name: "container2" + state: present + executable: "{{ test_executable | default('podman') }}" + - name: "container3" + state: present + image: alpine + executable: "{{ test_executable | default('podman') }}" + ignore_errors: true + register: no_image2 + + - name: Check no image + assert: + that: + - no_image is failed + - no_image1 is failed + - no_image2 is failed + - no_image.msg is search("State 'started' required image to be configured!") + - no_image1.msg is search ("State 'started' required image to be configured!") + - no_image2.msg is search("State 'present' required image to be configured!") + fail_msg: No-image test failed! + success_msg: No-image test passed! + + - name: Ensure image doesn't exist + containers.podman.podman_image: + name: alpine:3.7 + state: absent + executable: "{{ test_executable | default('podman') }}" + + - name: Check pulling image + containers.podman.podman_containers: + containers: + - name: container + image: alpine:3.7 + state: started + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + - name: container1 + image: alpine:3.7 + state: started + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + register: image + + - name: Check using already pulled image + containers.podman.podman_containers: + containers: + - name: container1 + image: alpine:3.7 + state: started + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + - name: container3 + image: alpine:3.7 + state: started + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + register: image2 + + - name: Check output is correct + assert: + that: + - image is changed + - image.containers[0] is defined + - image.containers[0]['State']['Running'] + - image.containers[1] is defined + - image.containers[1]['State']['Running'] + - "'pulled image alpine:3.7' in image.actions" + - "'started container' in image.actions" + - "'started container1' in image.actions" + - image2 is changed + - image2.containers is defined + - image2.containers[0]['State']['Running'] + - image2.containers[1]['State']['Running'] + - "'pulled image alpine:3.7' not in image2.actions" + - "'started container3' in image2.actions" + fail_msg: Pulling image test failed! + success_msg: Pulling image test passed! + + - name: Check failed image pull + containers.podman.podman_containers: + containers: + - name: container1 + image: alpine:3.7 + state: started + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + - name: container + image: ineverneverneverexist + state: started + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + register: imagefail + ignore_errors: true + + - name: Check output is correct + assert: + that: + - imagefail is failed + - imagefail.msg == "Can't pull image ineverneverneverexist" + + - name: Force containers recreate + containers.podman.podman_containers: + containers: + - name: container1 + image: alpine:3.7 + state: present + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + - name: container + image: alpine + state: present + command: sleep 1d + recreate: true + executable: "{{ test_executable | default('podman') }}" + register: recreated + + - name: Check output is correct + assert: + that: + - recreated is changed + - recreated.containers is defined + - recreated.containers[1]['State']['Running'] + - "'recreated container' in recreated.actions" + fail_msg: Force recreate test failed! + success_msg: Force recreate test passed! + + - name: Stop containers + containers.podman.podman_containers: + containers: + - name: container + state: stopped + executable: "{{ test_executable | default('podman') }}" + - name: container1 + state: stopped + executable: "{{ test_executable | default('podman') }}" + register: stopped + + - name: Stop the same containers again (idempotency) + containers.podman.podman_containers: + containers: + - name: container + state: stopped + executable: "{{ test_executable | default('podman') }}" + - name: container1 + state: stopped + executable: "{{ test_executable | default('podman') }}" + register: stopped_again + + - name: Check output is correct + assert: + that: + - stopped is changed + - stopped.containers is defined + - not stopped.containers[0]['State']['Running'] + - not stopped.containers[1]['State']['Running'] + - "'stopped container' in stopped.actions" + - stopped_again is not changed + - stopped_again.containers is defined + - not stopped_again.containers[0]['State']['Running'] + - not stopped_again.containers[1]['State']['Running'] + - stopped_again.actions == [] + fail_msg: Stopping container test failed! + success_msg: Stopping container test passed! + + - name: Delete stopped containers + containers.podman.podman_containers: + containers: + - name: container + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: container1 + state: absent + executable: "{{ test_executable | default('podman') }}" + register: deleted + + - name: Delete again containers (idempotency) + containers.podman.podman_containers: + containers: + - name: container + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: container1 + state: absent + executable: "{{ test_executable | default('podman') }}" + register: deleted_again + + - name: Check output is correct + assert: + that: + - deleted is changed + - deleted.containers is defined + - deleted.containers == [] + - "'deleted container' in deleted.actions" + - "'deleted container1' in deleted.actions" + - deleted_again is not changed + - deleted_again.containers is defined + - deleted_again.containers == [] + - deleted_again.actions == [] + fail_msg: Deleting stopped container test failed! + success_msg: Deleting stopped container test passed! + + - name: Create containers, but don't run + containers.podman.podman_containers: + containers: + - name: container + image: alpine:3.7 + state: stopped + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + - name: container1 + image: alpine:3.7 + state: created + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + register: created + + - name: Create containers, but don't run again + containers.podman.podman_containers: + containers: + - name: container + image: alpine:3.7 + state: stopped + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + - name: container1 + image: alpine:3.7 + state: created + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + register: created_again + + - name: Check output is correct + assert: + that: + - created is changed + - created.containers is defined + - created.containers != [] + - not created.containers[0]['State']['Running'] + - not created.containers[1]['State']['Running'] + - "'created container' in created.actions" + fail_msg: "Creating stopped container test failed!" + success_msg: "Creating stopped container test passed!" + + - name: Delete created containers + containers.podman.podman_containers: + containers: + - name: container + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: container1 + state: absent + executable: "{{ test_executable | default('podman') }}" + + - name: Start containers that were deleted + containers.podman.podman_containers: + containers: + - name: container + image: alpine:3.7 + state: started + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + - name: container1 + image: alpine:3.7 + state: started + command: sleep 1d + executable: "{{ test_executable | default('podman') }}" + register: started + + - name: Check output is correct + assert: + that: + - started.containers is defined + - started.containers[0]['State']['Running'] + - started.containers[1]['State']['Running'] + - "'started container' in started.actions" + - "'pulled image alpine:3.7' not in started.actions" + + - name: Delete started container + containers.podman.podman_containers: + containers: + - name: container + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: container1 + state: absent + executable: "{{ test_executable | default('podman') }}" + register: deleted + + - name: Delete again container (idempotency) + containers.podman.podman_containers: + containers: + - name: container + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: container1 + state: absent + executable: "{{ test_executable | default('podman') }}" + register: deleted_again + + - name: Check output is correct + assert: + that: + - deleted is changed + - deleted.containers is defined + - deleted.containers == [] + - "'deleted container' in deleted.actions" + - "'deleted container1' in deleted.actions" + - deleted_again is not changed + - deleted_again.containers is defined + - deleted_again.containers == [] + - deleted_again.actions == [] + fail_msg: Deleting started container test failed! + success_msg: Deleting started container test passed! + + - name: Recreate container with parameters + containers.podman.podman_containers: + containers: + - name: container + executable: "{{ test_executable | default('podman') }}" + image: docker.io/alpine:3.7 + state: started + command: sleep 1d + recreate: true + etc_hosts: + host1: 127.0.0.1 + host2: 127.0.0.1 + annotation: + this: "annotation_value" + dns_servers: + - 1.1.1.1 + - 8.8.4.4 + dns_search_domains: example.com + capabilities: + - SYS_TIME + - NET_ADMIN + ports: + - "9000:80" + - "9001:8000" + workdir: "/bin" + env: + FOO: bar=1 + BAR: foo + TEST: 1 + BOOL: false + label: + somelabel: labelvalue + otheralbe: othervalue + volumes: + - /tmp:/data + - name: container1 + executable: "{{ test_executable | default('podman') }}" + image: docker.io/alpine:3.7 + state: started + command: sleep 1d + recreate: true + etc_hosts: + host1: 127.0.0.1 + host2: 127.0.0.1 + annotation: + this: "annotation_value" + dns_servers: + - 1.1.1.1 + - 8.8.4.4 + dns_search_domains: example.com + capabilities: + - SYS_TIME + - NET_ADMIN + ports: + - "9002:80" + - "9003:8000" + workdir: "/bin" + env: + FOO: bar=1 + BAR: foo + TEST: 1 + BOOL: false + label: + somelabel: labelvalue + otheralbe: othervalue + volumes: + - /tmp:/data + register: test + + - name: Check output is correct + assert: + that: + - test is changed + - test.containers is defined + - test.containers != [] + - test.containers[0]['State']['Running'] + # test capabilities + - "'CAP_SYS_TIME' in test.containers[0]['BoundingCaps']" + - "'CAP_NET_ADMIN' in test.containers[0]['BoundingCaps']" + # test annotations + - test.containers[0]['Config']['Annotations']['this'] is defined + - test.containers[0]['Config']['Annotations']['this'] == "annotation_value" + # test DNS + - >- + (test.containers[0]['HostConfig']['Dns'] is defined and + test.containers[0]['HostConfig']['Dns'] == ['1.1.1.1', '8.8.4.4']) or + (test.containers[0]['HostConfig']['DNS'] is defined and + test.containers[0]['HostConfig']['DNS'] == ['1.1.1.1', '8.8.4.4']) + # test ports + - test.containers[0]['NetworkSettings']['Ports']|length == 2 + # test working dir + - test.containers[0]['Config']['WorkingDir'] == "/bin" + # test dns search + - >- + (test.containers[0]['HostConfig']['DnsSearch'] is defined and + test.containers[0]['HostConfig']['DnsSearch'] == ['example.com']) or + (test.containers[0]['HostConfig']['DNSSearch'] is defined and + test.containers[0]['HostConfig']['DNSSearch'] == ['example.com']) + # test environment variables + - "'FOO=bar=1' in test.containers[0]['Config']['Env']" + - "'BAR=foo' in test.containers[0]['Config']['Env']" + - "'TEST=1' in test.containers[0]['Config']['Env']" + - "'BOOL=False' in test.containers[0]['Config']['Env']" + # test labels + - test.containers[0]['Config']['Labels'] | length == 2 + - test.containers[0]['Config']['Labels']['somelabel'] == "labelvalue" + - test.containers[0]['Config']['Labels']['otheralbe'] == "othervalue" + # test mounts + - >- + (test.containers[0]['Mounts'][0]['Destination'] is defined and + '/data' in test.containers[0]['Mounts'] | map(attribute='Destination') | list) or + (test.containers[0]['Mounts'][0]['destination'] is defined and + '/data' in test.containers[0]['Mounts'] | map(attribute='destination') | list) + - >- + (test.containers[0]['Mounts'][0]['Source'] is defined and + '/tmp' in test.containers[0]['Mounts'] | map(attribute='Source') | list) or + (test.containers[0]['Mounts'][0]['source'] is defined and + '/tmp' in test.containers[0]['Mounts'] | map(attribute='source') | list) + fail_msg: Parameters container test failed! + success_msg: Parameters container test passed! + + - name: Check basic idempotency of running container + containers.podman.podman_containers: + containers: + - name: testidem + image: docker.io/alpine + state: started + command: sleep 20m + executable: "{{ test_executable | default('podman') }}" + - name: testidem2 + image: docker.io/alpine + state: started + command: sleep 21m + executable: "{{ test_executable | default('podman') }}" + - name: testidem3 + image: docker.io/alpine + state: started + command: sleep 22m + executable: "{{ test_executable | default('podman') }}" + + - name: Check basic idempotency of running container - run it again + containers.podman.podman_containers: + containers: + - name: testidem + image: docker.io/alpine + state: present + command: sleep 20m + executable: "{{ test_executable | default('podman') }}" + - name: testidem2 + image: docker.io/alpine + state: present + command: sleep 21m + executable: "{{ test_executable | default('podman') }}" + - name: testidem3 + image: docker.io/alpine + state: present + command: sleep 22m + executable: "{{ test_executable | default('podman') }}" + register: idem + + - name: Check that nothing was changed + assert: + that: + - not idem.changed + + - name: Run changed container (with tty enabled) + containers.podman.podman_containers: + containers: + - name: testidem + image: docker.io/alpine + state: present + command: sleep 20m + tty: true + executable: "{{ test_executable | default('podman') }}" + - name: testidem2 + image: docker.io/alpine + state: present + command: sleep 21m + executable: "{{ test_executable | default('podman') }}" + - name: testidem3 + image: docker.io/alpine + state: present + command: sleep 22m + executable: "{{ test_executable | default('podman') }}" + register: idem1 + + - name: Check that container is recreated when changed + assert: + that: + - idem1 is changed + + - name: Run changed container without specifying an option, use defaults + containers.podman.podman_containers: + containers: + - name: testidem + image: docker.io/alpine + state: present + command: sleep 20m + executable: "{{ test_executable | default('podman') }}" + - name: testidem2 + image: docker.io/alpine + state: present + command: sleep 21m + executable: "{{ test_executable | default('podman') }}" + - name: testidem3 + image: docker.io/alpine + state: present + command: sleep 22m + executable: "{{ test_executable | default('podman') }}" + register: idem2 + + - name: Check that container is recreated when changed to default value + assert: + that: + - idem2 is changed + + - name: Remove container + containers.podman.podman_containers: + containers: + - name: testidem + state: absent + executable: "{{ test_executable | default('podman') }}" + register: remove + + - name: Check podman_actions + assert: + that: + - "'podman rm -f testidem' in remove.podman_actions" + + - name: Create a pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: testidempod + + - name: Check basic idempotency of pod container + containers.podman.podman_containers: + containers: + - name: testidem-pod + image: docker.io/alpine + state: present + command: sleep 20m + pod: "testidempod" + executable: "{{ test_executable | default('podman') }}" + - name: testidem-pod2 + image: docker.io/alpine + state: present + command: sleep 20m + pod: testidempod + executable: "{{ test_executable | default('podman') }}" + + - name: Check basic idempotency of pod container - run it again + containers.podman.podman_containers: + containers: + - name: testidem-pod + image: alpine:latest + state: present + command: sleep 20m + pod: testidempod + executable: "{{ test_executable | default('podman') }}" + - name: testidem-pod2 + image: docker.io/alpine + state: present + command: sleep 20m + pod: testidempod + executable: "{{ test_executable | default('podman') }}" + register: idem + + - name: Check that nothing was changed in pod containers + assert: + that: + - not idem.changed + + - name: Run changed pod container (with tty enabled) + containers.podman.podman_containers: + containers: + - name: testidem-pod + image: alpine + state: present + command: sleep 20m + tty: true + pod: testidempod + executable: "{{ test_executable | default('podman') }}" + - name: testidem-pod2 + image: alpine + state: present + command: sleep 20m + pod: testidempod + executable: "{{ test_executable | default('podman') }}" + register: idem1 + + - name: Check that container is recreated when changed + assert: + that: + - idem1 is changed + + - name: Remove container + containers.podman.podman_containers: + containers: + - name: testidem-pod + state: absent + executable: "{{ test_executable | default('podman') }}" + - name: testidem-pod2 + state: absent + executable: "{{ test_executable | default('podman') }}" + + always: + - name: Delete all container leftovers from tests + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - "alpine:3.7" + - "container" + - "container1" + - "container2" + - "container3" + - "container4" + - "testidem" + - "testidem1" + - "testidem2" + - "testidem3" + - "testidem-pod" + - "testidem-pod2" + + - name: Remove pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: testidempod + state: absent + +- name: Test containers module for root + include_tasks: root-multi.yml + vars: + ansible_python_interpreter: "/usr/bin/python" + args: + apply: + become: true diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_containers/tasks/root-multi.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_containers/tasks/root-multi.yml new file mode 100644 index 000000000..d61c4e584 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_containers/tasks/root-multi.yml @@ -0,0 +1,115 @@ +--- +- name: Test podman rootful pod play + block: + + - name: Create networks + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: present + loop: + - testnet1 + - testnet2 + + - name: Create container with parameters + register: continfo + containers.podman.podman_containers: + containers: + - name: cont1 + executable: "{{ test_executable | default('podman') }}" + image: docker.io/alpine:3.7 + state: started + command: sleep 1d + debug: true + network: testnet1 + add_hosts: + host1: 127.0.0.1 + host2: 127.0.0.1 + annotation: + this: "annotation_value" + dns_servers: + - 1.1.1.1 + - 8.8.4.4 + dns_search_domains: example.com + capabilities: + - SYS_TIME + - NET_ADMIN + ports: + - "9000:80" + - "9001:8000" + workdir: "/bin" + env: + FOO: bar=1 + BAR: foo + TEST: 1 + BOOL: false + label: + somelabel: labelvalue + otheralbe: othervalue + volumes: + - /tmp:/data + interactive: true + - name: cont2 + executable: "{{ test_executable | default('podman') }}" + image: docker.io/alpine:3.7 + state: started + command: sleep 1d + recreate: true + network: + - testnet2 + - testnet1 + etc_hosts: + host1: 127.0.0.1 + host2: 127.0.0.1 + annotation: + this: "annotation_value" + dns_servers: + - 1.1.1.1 + - 8.8.4.4 + dns_search_domains: example.com + capabilities: + - SYS_TIME + - NET_ADMIN + ports: + - "9002:80" + - "9003:8000" + workdir: "/bin" + env: + FOO: bar=1 + BAR: foo + TEST: 1 + BOOL: false + label: + somelabel: labelvalue + otheralbe: othervalue + volumes: + - /tmp:/data + interactive: false + + - name: Check multiple root containers + assert: + that: + - continfo.containers[0]['NetworkSettings']['Networks'].keys() | list == ['testnet1'] + - continfo.containers[1]['NetworkSettings']['Networks'].keys() | list == ['testnet1', 'testnet2'] or + continfo.containers[1]['NetworkSettings']['Networks'].keys() | list == ['testnet2', 'testnet1'] + + always: + + - name: Delete all containers leftovers from tests + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - cont1 + - cont2 + - cont3 + + - name: Delete all networks leftovers from tests + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - testnet1 + - testnet2 diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_export/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_export/tasks/main.yml new file mode 100644 index 000000000..70f8d3852 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_export/tasks/main.yml @@ -0,0 +1,71 @@ +--- +- name: Test podman export + block: + - name: Start container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: alpine:3.7 + state: started + command: sleep 1d + + - name: Export container + containers.podman.podman_export: + executable: "{{ test_executable | default('podman') }}" + container: container + dest: /tmp/container + + - name: Check file + stat: + path: /tmp/container + register: img + + - name: Check it's exported + assert: + that: + - img.stat.exists + + - name: Import container + containers.podman.podman_import: + executable: "{{ test_executable | default('podman') }}" + src: /tmp/container + register: image + + - name: Check it's imported + assert: + that: + - image is success + + - name: Export container without force + containers.podman.podman_export: + executable: "{{ test_executable | default('podman') }}" + container: container + dest: /tmp/container + force: false + register: image2 + + - name: Check it's exported + assert: + that: + - image2 is success + - image2 is not changed + + - name: Export container with force + containers.podman.podman_export: + executable: "{{ test_executable | default('podman') }}" + container: container + dest: /tmp/container + force: true + register: image3 + + - name: Check it's not exported + assert: + that: + - image3 is changed + + always: + - name: Remove container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: absent diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_generate_systemd/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_generate_systemd/tasks/main.yml new file mode 100644 index 000000000..6b0d18cb2 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_generate_systemd/tasks/main.yml @@ -0,0 +1,94 @@ +- name: A postgres container must exist, stopped + containers.podman.podman_container: + name: postgres_local + image: docker.io/library/postgres:latest + state: stopped + +- name: Generate the systemd units as Ansible variables + containers.podman.podman_generate_systemd: + name: postgres_local + register: postgres_local_systemd_unit + ignore_errors: true + +- name: Check systemd unit are generated + assert: + that: + - postgres_local_systemd_unit is succeeded + +- name: Check systemd unit exist in registered vars + assert: + that: + - item.key == "container-postgres_local" + - item.value != None + loop: "{{ postgres_local_systemd_unit.systemd_units | dict2items }}" + +- name: Check podman command used to generate systemd units is returned + assert: + that: + - postgres_local_systemd_unit.podman_command != "" + +- name: Regenerate the systemd units and write them + containers.podman.podman_generate_systemd: + name: postgres_local + dest: /tmp/podman_generate_systemd + register: postgres_local_systemd_unit + ignore_errors: true + +- name: Check the unit files exists + ansible.builtin.stat: + path: "/tmp/podman_generate_systemd/{{ item.key }}.service" + loop: "{{ postgres_local_systemd_unit.systemd_units | dict2items }}" + +- name: Regenerate the systemd units with all the options + containers.podman.podman_generate_systemd: + name: postgres_local + new: true + restart_policy: on-abnormal + restart_sec: 19 + start_timeout: 21 + stop_timeout: 23 + env: + POSTGRES_USER: my_app + POSTGRES_PASSWORD: example + use_names: true + container_prefix: more + pod_prefix: less + separator: + + no_header: true + after: drink.service + wants: water.service + requires: ice.service + executable: /usr/bin/podman + register: postgres_local_systemd_unit + ignore_errors: true + +- name: Check the correct podman command is build + assert: + that: + - postgres_local_systemd_unit.podman_command is search("postgres_local") + - postgres_local_systemd_unit.podman_command is search("--new") + - postgres_local_systemd_unit.podman_command is search("--restart-policy=on-abnormal") + - postgres_local_systemd_unit.podman_command is search("--restart-sec=19") + - postgres_local_systemd_unit.podman_command is search("--start-timeout=21") + - postgres_local_systemd_unit.podman_command is search("--stop-timeout=23") + - postgres_local_systemd_unit.podman_command is search("-e='POSTGRES_USER=my_app'") + - postgres_local_systemd_unit.podman_command is search("-e='POSTGRES_PASSWORD=example'") + - postgres_local_systemd_unit.podman_command is search("--name") + - postgres_local_systemd_unit.podman_command is search("--container-prefix=more") + - postgres_local_systemd_unit.podman_command is search("--pod-prefix=less") + - postgres_local_systemd_unit.podman_command is search("--separator=+") + - postgres_local_systemd_unit.podman_command is search("--no-header") + - postgres_local_systemd_unit.podman_command is search("--after=drink.service") + - postgres_local_systemd_unit.podman_command is search("--wants=water.service") + - postgres_local_systemd_unit.podman_command is search("--requires=ice.service") + - postgres_local_systemd_unit.podman_command is search("/usr/bin/podman") + +- name: Remove container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: postgres_local + state: absent +- name: Remove the systemd unit files directory + ansible.builtin.file: + path: /tmp/podman_generate_systemd + state: absent diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_image/files/Containerfile b/ansible_collections/containers/podman/tests/integration/targets/podman_image/files/Containerfile new file mode 100644 index 000000000..d4bd8edb9 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_image/files/Containerfile @@ -0,0 +1,3 @@ +FROM quay.io/coreos/alpine-sh +ENV VAR testing +WORKDIR ${VAR} diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_image/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_image/tasks/main.yml new file mode 100644 index 000000000..645d0a033 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_image/tasks/main.yml @@ -0,0 +1,331 @@ +- name: Test podman_image + block: + - name: Pull image + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: quay.io/coreos/alpine-sh + register: pull1 + + - name: Pull image again + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: quay.io/coreos/alpine-sh + register: pull2 + + - name: Pull image from docker.io with short url + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/alpine + register: pull3 + + - name: Pull image from docker.io with short url again + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/alpine + register: pull4 + + - name: Pull image from docker.io with official/normalised url again + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/library/alpine + register: pull5 + + - name: Pull image for testing image deletion with image id + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/library/ubuntu + register: pull6 + + - name: List images + command: podman image ls + register: images + + - name: Ensure image were pulled properly + assert: + that: + - pull1 is changed + - pull1.podman_actions is defined + - pull2 is not changed + - pull3 is changed + - pull4 is changed + - pull5 is not changed + - pull6 is changed + - "'alpine-sh' in images.stdout" + - "'library/alpine' in images.stdout" + - "'library/ubuntu' in images.stdout" + + - name: add another tag (repository url) + command: + argv: + - podman + - tag + - quay.io/coreos/alpine-sh + - quay.io/coreos/library/alpine-sh + + - name: Remove image (tag) + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: quay.io/coreos/alpine-sh + state: absent + register: rmi1 + + - name: Remove image again + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: quay.io/coreos/alpine-sh + state: absent + register: rmi2 + + - name: Remove image using new repository url + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: quay.io/coreos/library/alpine-sh + state: absent + register: rmi3 + + - name: Try to remove docker.io image using short url + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/alpine + state: absent + register: rmi4 + + - name: Remove docker.io image using normalised url + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/library/alpine + state: absent + register: rmi5 + + - name: Get image id of the target image + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/library/ubuntu + register: imageinfo + + - name: Remove an image with image id + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item.Id }}" + state: absent + loop: "{{ imageinfo.images }}" + register: rmi6 + + - name: List images + command: podman image ls + register: images + + - name: Ensure image were removed properly + assert: + that: + - rmi1 is changed + - rmi2 is not changed + - rmi3 is changed + - rmi4 is not changed + - rmi5 is changed + - rmi6 is changed + - "'alpine-sh' not in images.stdout" + - "'library/ubuntu' not in images.stdout" + + - name: Pull a specific version of an image + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: quay.io/coreos/etcd + tag: v3.3.11 + register: specific_image1 + + - name: Pull a specific version of an image again + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: quay.io/coreos/etcd + tag: v3.3.11 + register: specific_image2 + + - name: List images + command: podman image ls + register: images + + - name: Ensure specific image was pulled properly + assert: + that: + - specific_image1 is changed + - specific_image2 is not changed + - "'v3.3.11' in images.stdout" + + - name: Get info about pulled image + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + name: quay.io/coreos/etcd:v3.3.11 + register: sha_image_info + + - name: Pull image with SHA256 tag + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: "quay.io/coreos/etcd@{{ sha_image_info.images.0.Digest }}" #quay.io/coreos/coreos-installer:latest + state: present + + - name: Create a build directory with a subdirectory + file: + path: /var/tmp/build/subdir + state: directory + + - name: Copy Containerfile + copy: + src: Containerfile + dest: /var/tmp/build/Dockerfile + + - name: Build OCI image + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: testimage + path: /var/tmp/build + register: oci_build1 + + - name: Build OCI image again + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: testimage + path: /var/tmp/build + register: oci_build2 + + - name: Build OCI image from a directory without Containerfile (should fail) + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: testimage2 + path: /var/tmp/build/subdir + register: oci_build3 + ignore_errors: true + + - name: Build OCI image, point to location of Containerfile + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: testimage2 + path: /var/tmp/build/subdir + build: + file: /var/tmp/build/Dockerfile + register: oci_build4 + + - name: Inspect first image + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + name: testimage + register: testimage_info + + - name: Inspect second image + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + name: testimage2 + register: testimage2_info + + - name: Ensure OCI images were built properly + assert: + that: + - oci_build1 is changed + - oci_build2 is not changed + - oci_build3 is not changed + - oci_build3 is failed + - oci_build4 is changed + - "'localhost/testimage:latest' in testimage_info.images[0]['RepoTags'][0]" + - "'localhost/testimage2:latest' in testimage2_info.images[0]['RepoTags'][0]" + - "'no such file or directory' in oci_build3.msg" + + - name: Build Docker image + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: dockerimage + path: /var/tmp/build + build: + format: docker + register: docker_build1 + + - name: Build Docker image again + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: dockerimage + path: /var/tmp/build + build: + format: docker + register: docker_build2 + + - name: Inspect built image + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + name: dockerimage + register: dockerimage_info + + - name: Ensure Docker image was built properly + assert: + that: + - docker_build1 is changed + - docker_build2 is not changed + - "'localhost/dockerimage:latest' in dockerimage_info.images[0]['RepoTags'][0]" + + - name: push image that doesn't exit to nowhere + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: bad_image + pull: false + push: true + register: bad_push + ignore_errors: true + + - name: Ensure that Image failed correctly. + assert: + that: + - "bad_push is failed" + - "bad_push is not changed" + - "'Failed to find image bad_image' in bad_push.msg" + - "'image pull set to False' in bad_push.msg" + + - name: Pull an image for a specific CPU architecture + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/library/ubuntu + arch: amd64 + register: pull_arch1 + + - name: Pull the same image for the same CPU architecture + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/library/ubuntu + arch: amd64 + register: pull_arch2 + + - name: Pull the same image but for another CPU architecture + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/library/ubuntu + arch: arm + register: pull_arch3 + + - name: Ensure the result of pulling image for another CPU architecture + assert: + that: + - "pull_arch2 is not changed" + - "pull_arch3 is changed" + + - name: Get the image info + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/library/ubuntu + register: imageinfo_arch + + - name: Ensure the CPU architecture of the image is as expected + assert: + that: + - item.Architecture == "arm" + loop: "{{ imageinfo_arch.images }}" + + always: + - name: Cleanup images + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - docker.io/library/ubuntu + - quay.io/coreos/alpine-sh + - quay.io/coreos/etcd:v3.3.11 + - localhost/testimage + - localhost/testimage2 + - localhost/dockerimage diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_image_info/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_image_info/tasks/main.yml new file mode 100644 index 000000000..105ffcd1f --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_image_info/tasks/main.yml @@ -0,0 +1,66 @@ +- name: Test podman_image_info + block: + + - name: Get info on images when no images + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + register: info_0 + + - name: Check results for no images + assert: + that: + - info_0.images | length == 0 + + - name: Pull image + command: podman pull quay.io/coreos/etcd + + - name: Get info on all images + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + register: all_image_result + + - name: Pull another image + command: podman pull quay.io/coreos/dnsmasq + + - name: Get info on specific image + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + name: dnsmasq + register: named_image_result + + - name: Check results + assert: + that: + - all_image_result.images | length > 0 + - named_image_result.images | length == 1 + - "'dnsmasq' in named_image_result.images[0]['RepoTags'][0]" + + - name: Get info on single image that does not exist + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + name: nope + register: single_nonexistant + + - name: Get info on multiple images that do not exist + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + name: + - nope + - reallynope + register: multiple_nonexistant + + - name: Get info with one image that does not exist + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + name: + - dnsmasq + - nope + - etcd + register: mixed_nonexistant + + - name: Ensure image info was returned when non-existant image info was requisted + assert: + that: + - single_nonexistant.images | length == 0 + - multiple_nonexistant.images | length == 0 + - mixed_nonexistant.images | length == 2 diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_import/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_import/tasks/main.yml new file mode 100644 index 000000000..db8254e87 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_import/tasks/main.yml @@ -0,0 +1,72 @@ +--- +- name: Test podman import + block: + - name: Start container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + image: alpine:3.7 + state: started + command: sleep 1d + + - name: Export container + containers.podman.podman_export: + executable: "{{ test_executable | default('podman') }}" + container: container + dest: /tmp/container + + - name: Check file + stat: + path: /tmp/container + register: img + + - name: Check it's saved + assert: + that: + - img.stat.exists + + - name: Import container + containers.podman.podman_import: + executable: "{{ test_executable | default('podman') }}" + src: /tmp/container + register: test + + - name: Check it's imported + assert: + that: + - test is success + - test.image["Id"] != '' + + - name: Import container with commit message + containers.podman.podman_import: + executable: "{{ test_executable | default('podman') }}" + src: /tmp/container + commit_message: 'Test in CI' + register: test1 + + - name: Check it's imported with commit message + assert: + that: + - test1.image.Comment == "Test in CI" + + - name: Import container with changes + containers.podman.podman_import: + executable: "{{ test_executable | default('podman') }}" + src: /tmp/container + change: + - "User": "someuser" + - "CMD": "/bin/nonsh" + register: test2 + + - name: Check it's imported with changes + assert: + that: + - test2.image.User == 'someuser' + - test2.image["Config"]["Cmd"][2] == "/bin/nonsh" + + always: + - name: Remove container + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container + state: absent diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_load/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_load/tasks/main.yml new file mode 100644 index 000000000..087a869a7 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_load/tasks/main.yml @@ -0,0 +1,91 @@ +--- +- name: Pull image + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: k8s.gcr.io/pause + +- name: Save image + containers.podman.podman_save: + executable: "{{ test_executable | default('podman') }}" + image: k8s.gcr.io/pause + dest: /tmp/image.tar + +- name: Load image + containers.podman.podman_load: + executable: "{{ test_executable | default('podman') }}" + input: /tmp/image.tar + register: image + +- name: Check it's loaded + assert: + that: + - image.image != {} + - image.image.NamesHistory.0 == "k8s.gcr.io/pause:latest" + +- name: Save image + containers.podman.podman_save: + executable: "{{ test_executable | default('podman') }}" + image: k8s.gcr.io/pause + dest: /tmp/imagedir + format: oci-dir + +- name: Load image from oci-dir + containers.podman.podman_load: + executable: "{{ test_executable | default('podman') }}" + input: /tmp/imagedir + register: image + +- name: Check it's loaded + assert: + that: + - image.image != {} + - image.image.NamesHistory.0 == "localhost/tmp/imagedir:latest" + +- name: Save image with multi image archive + containers.podman.podman_save: + executable: "{{ test_executable | default('podman') }}" + image: k8s.gcr.io/pause + dest: /tmp/image2.tar + multi_image_archive: true + +- name: Load image from oci-dir multi image archive + containers.podman.podman_load: + executable: "{{ test_executable | default('podman') }}" + input: /tmp/image2.tar + register: image + +- name: Check it's loaded + assert: + that: + - image.image != {} + - image.image.NamesHistory.0 == "k8s.gcr.io/pause:latest" + +- name: Pull images + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: '{{ item }}' + loop: + - k8s.gcr.io/coredns:1.7.0 + - k8s.gcr.io/echoserver:1.10 + +- name: Clean up multifile + ansible.builtin.file: + path: /tmp/multi.tar + state: absent + +- name: Create multi image file + shell: >- + podman save k8s.gcr.io/coredns:1.7.0 k8s.gcr.io/echoserver:1.10 -o /tmp/multi.tar + +- name: Load image from oci-dir multi image archive + containers.podman.podman_load: + executable: "{{ test_executable | default('podman') }}" + input: /tmp/multi.tar + register: image + +- name: Check it's loaded + assert: + that: + - image.image != {} + - '"k8s.gcr.io/coredns:1.7.0" in image.image.NamesHistory' + - '"k8s.gcr.io/echoserver:1.10" in image.image.NamesHistory' diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_login/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_login/tasks/main.yml new file mode 100644 index 000000000..37c13a6e0 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_login/tasks/main.yml @@ -0,0 +1,50 @@ +- name: Test podman_login + block: + + - name: Print podman version + command: podman version + + - name: Logout from docker if it exists + command: docker logout + ignore_errors: true + + - name: Login with invalid executable + containers.podman.podman_login: + executable: podman_invalid + username: doesntmatter + password: nopassword + register: invalid_executable + ignore_errors: true + + - name: Check invalid executable results + assert: + that: + - invalid_executable is failed + + - name: Wrong login to registry.fedoraproject.org + containers.podman.podman_login: + executable: "{{ test_executable | default('podman') }}" + username: notexist + password: notexistaswell + registry: docker.io + register: loginf + ignore_errors: true + + - name: Check login + assert: + that: + - loginf is failed + + - name: Login to registry.fedoraproject.org + containers.podman.podman_login: + executable: "{{ test_executable | default('podman') }}" + username: foo + password: bar + registry: registry.fedoraproject.org + register: login + ignore_errors: true + + - name: Check login + assert: + that: + - login is not failed diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_login_info/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_login_info/tasks/main.yml new file mode 100644 index 000000000..8ee8366ff --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_login_info/tasks/main.yml @@ -0,0 +1,64 @@ +- name: Test podman_login_info + block: + + - name: Print podman version + command: podman version + + - name: Get login info with invalid executable + containers.podman.podman_login_info: + executable: podman_invalid + registry: quay.io + register: invalid_executable + ignore_errors: true + + - name: Check invalid executable results + assert: + that: + - invalid_executable is failed + + - name: Get login info without specifying registry + containers.podman.podman_login_info: + executable: podman_invalid + register: missing_registry + ignore_errors: true + + - name: Check missing registry results + assert: + that: + - missing_registry is failed + + - name: Get login info for a non-existing registry + containers.podman.podman_login_info: + executable: "{{ test_executable | default('podman') }}" + registry: non-existing.registry + register: non_existing_registry + + - name: Check non-existing registry results + assert: + that: + - "'login' in non_existing_registry" + - non_existing_registry.login + - "'registry' in non_existing_registry.login" + - "'username' in non_existing_registry.login" + - "'logged_in' in non_existing_registry.login" + - "non_existing_registry.login.registry == 'non-existing.registry'" + - "non_existing_registry.login.username == ''" + - "non_existing_registry.login.logged_in == False" + + - name: Get login info for a non-existing authfile + # This will return not logged in even if logged in via different authfile + containers.podman.podman_login_info: + executable: "{{ test_executable | default('podman') }}" + registry: quay.io + authfile: non-existing.authfile.json + register: non_existing_authfile + + - name: Check non-existing authfile results + assert: + that: + - "'login' in non_existing_authfile" + - non_existing_authfile.login + - "'username' in non_existing_authfile.login" + - "'logged_in' in non_existing_authfile.login" + - "non_existing_authfile.login.username == ''" + - "non_existing_authfile.login.logged_in == False" diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_logout/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_logout/tasks/main.yml new file mode 100644 index 000000000..e8632d53f --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_logout/tasks/main.yml @@ -0,0 +1,56 @@ +- name: Test podman_logout + block: + + - name: Print podman version + command: podman version + + - name: Logout from docker if it exists + command: docker logout + ignore_errors: true + + - name: Log out with invalid executable + containers.podman.podman_logout: + executable: podman_invalid + register: invalid_executable + ignore_errors: true + + - name: Check invalid executable results + assert: + that: + - invalid_executable is failed + + - name: Log out of non-existing registry + containers.podman.podman_logout: + executable: "{{ test_executable | default('podman') }}" + register: non_existing_registry + ignore_errors: true + + - name: Check results + assert: + that: + - "'changed' in non_existing_registry" + - "non_existing_registry.changed == False" + + - name: Log out with invalid authfile + containers.podman.podman_logout: + executable: "{{ test_executable | default('podman') }}" + authfile: authfile_invalid.json + register: invalid_authfile + ignore_errors: true + + - name: Check invalid authfile results + assert: + that: + - invalid_authfile is failed + + - name: Log out of all registries + containers.podman.podman_logout: + executable: "{{ test_executable | default('podman') }}" + all: true + register: all_registries + + - name: Check results + assert: + that: + - "'changed' in all_registries" + - "all_registries.changed == True" diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_network/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_network/tasks/main.yml new file mode 100644 index 000000000..d207e4cef --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_network/tasks/main.yml @@ -0,0 +1,357 @@ +- name: Test podman_network + become: true + block: + + - name: Print podman version + command: podman version + + - name: Check if dnsname plugin is installed + block: + + - name: Check if plugin is installed + stat: + path: "{{ item }}" + loop: + - /usr/libexec/cni/dnsname + - /usr/lib/cni/dnsname + - /opt/cni/bin/dnsname + - /opt/bridge/bin/dnsname + register: plugin_results + + - name: Set plugin fact + set_fact: + dns_plugin: "{{ true in plugin_results.results|map(attribute='stat.exists') }}" + + - name: Generate random value for network name + set_fact: + network_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}" + + - name: Make sure network doesn't exist + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: absent + + - name: Get missing network info + containers.podman.podman_network_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + register: info + ignore_errors: true + + - name: Check results + assert: + that: + - info is failed + + - name: Create network + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + register: net + + - name: Get existing network info + containers.podman.podman_network_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + register: info1 + + - name: Check info + assert: + that: + - info1 | length > 1 + - info1.networks.0.name == network_name + - net is changed + + - name: Create network again + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + register: info2 + + - name: Check info + assert: + that: + - info2 is not changed + + # TODO: Enable it when podman v4 is available in CI + + # - name: Create network with disable DNS + # containers.podman.podman_network: + # executable: "{{ test_executable | default('podman') }}" + # name: "{{ network_name }}" + # state: present + # disable_dns: true + # register: info3 + + # - name: Check info + # assert: + # that: + # - >- + # info3 is changed and dns_plugin|bool or + # info3 is not changed and not dns_plugin|bool + + # - name: Create network with disable DNS again + # containers.podman.podman_network: + # executable: "{{ test_executable | default('podman') }}" + # name: "{{ network_name }}" + # state: present + # disable_dns: true + # register: info4 + + # - name: Check info + # assert: + # that: + # - info4 is not changed + + # - name: Create network w/o disable DNS + # containers.podman.podman_network: + # executable: "{{ test_executable | default('podman') }}" + # name: "{{ network_name }}" + # state: present + # register: info5 + + # - name: Check info + # assert: + # that: + # - >- + # info5 is changed and dns_plugin|bool or + # info5 is not changed and not dns_plugin|bool + + - name: Create network with custom gateway + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + gateway: 10.100.100.100 + subnet: 10.100.100.0/24 + register: info6 + + - name: Check info + assert: + that: + - info6 is changed + ignore_errors: true + # In v4 subnets are added automatically and gateway idempotency is disabled + + - name: Create network with custom gateway again + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + gateway: 10.100.100.100 + subnet: 10.100.100.0/24 + register: info7 + + - name: Check info + assert: + that: + - info7 is not changed + + - name: Create internal network + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + internal: true + register: info9 + + - name: Check info + assert: + that: + - info9 is changed + + - name: Create internal network again + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + internal: true + register: info10 + + - name: Check info + assert: + that: + - info10 is not changed + + - name: Create a regular external network + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + register: info11 + + - name: Check info + assert: + that: + - info11 is changed + + - name: Create network with subnet + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + subnet: 10.200.200.0/24 + recreate: true + register: info12 + + - name: Check info + assert: + that: + - info12 is changed + # In v4 subnets are added automatically and subnets idempotency is disabled + + - name: Create network with subnet again + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + subnet: 10.200.200.0/24 + register: info13 + + - name: Check info + assert: + that: + - info13 is not changed + + - name: Create network with ipv6 subnet + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + subnet: 2001:cafe::/64 + ipv6: true + + - name: Make sure network doesn't exist + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: absent + + - name: Get existing network info + containers.podman.podman_network_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + register: info100 + ignore_errors: true + + - name: Check results + assert: + that: + - info100 is failed + + - name: Create network with opts MTU + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + opt: + mtu: 1311 + register: opt1 + + - name: Create network with opts VLAN + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + opt: + vlan: 4000 + register: opt2 + + - name: Create network with opts MTU and VLAN + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + opt: + mtu: 1311 + vlan: 4000 + register: opt3 + + - name: Create network with opts MTU and VLAN again + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + opt: + mtu: 1311 + vlan: 4000 + register: opt4 + + - name: Check results for network opts + assert: + that: + - opt1 is changed + - opt2 is changed + - opt3 is changed + - opt4 is not changed + + always: + + - name: Cleanup + command: podman network rm -f {{ network_name }} + ignore_errors: true + +- name: Test podman_network rootless + become: false + block: + + - name: Create network + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + register: net1 + + - name: Get existing network info + containers.podman.podman_network_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + register: info15 + + - name: Check info + assert: + that: + - info15 | length > 1 + - info15.networks.0.name == network_name + - net1 is changed + + - name: Create network again + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + state: present + register: info16 + + - name: Check info + assert: + that: + - info16 is not changed + + - name: Create network with IPv6 'exploded' + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + ipv6: true + subnet: fd4f:552c:830f:0000::/64 + state: present + + - name: Create network with IPv6 'exploded' again + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + ipv6: true + subnet: fd4f:552c:830f:0000::/64 + state: present + register: info17 + + - name: Check info + assert: + that: + - info17 is not changed + + always: + + - name: Cleanup + command: podman network rm -f {{ network_name }} + ignore_errors: true diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_network_info/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_network_info/tasks/main.yml new file mode 100644 index 000000000..f5eb4401a --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_network_info/tasks/main.yml @@ -0,0 +1,62 @@ +- name: Test podman_network_info + become: true + block: + + - name: Print podman version + command: podman version + + - name: Generate random value for network name + set_fact: + network_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}" + + - name: Make sure network doesn't exist + command: podman network rm {{ network_name }} + ignore_errors: true + + - name: Get missing network info + containers.podman.podman_network_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + register: nonexist + ignore_errors: true + + - name: Check results + assert: + that: + - "'networks' not in nonexist" + - nonexist is failed + + - name: Make sure network exists + command: podman network create {{ network_name }} + + - name: Get existing network info + containers.podman.podman_network_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ network_name }}" + register: existing_network + + - name: Dump podman network inspect result + debug: var=existing_network + + - name: Comparison with 'podman network inspect' + command: podman network inspect "{{ network_name }}" + register: podman_inspect + + - name: Convert podman inspect output to JSON + set_fact: + podman_inspect_result: "{{ podman_inspect.stdout | from_json }}" + + - name: Cleanup + command: podman network rm {{ network_name }} + + - name: Make checks + assert: + that: + - "'networks' in existing_network" + - existing_network.networks + - "existing_network.networks == podman_inspect_result" + always: + + - name: Cleanup + command: podman network rm {{ network_name }} + ignore_errors: true diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/envdata.yaml b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/envdata.yaml new file mode 100644 index 000000000..7d8ef5d28 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/envdata.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: envdata + namespace: default +data: + var1: somevalue1 + key2: value2 diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play-root1.yaml b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play-root1.yaml new file mode 100644 index 000000000..d96d6a097 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play-root1.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: web-deploy-root + labels: + app: webapp +spec: + selector: + matchLabels: + app: webapp + template: + metadata: + labels: + app: webapp + spec: + containers: + - name: alpinexroot + image: alpine + command: ['sleep', '1d'] + ports: + - containerPort: 80 + - name: alpineyroot + image: alpine + command: ['sleep', '1d'] + ports: + - containerPort: 7777 diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play-root3.yaml b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play-root3.yaml new file mode 100644 index 000000000..727e9a155 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play-root3.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: web-deploy-root + labels: + app: webapp +spec: + selector: + matchLabels: + app: webapp + template: + metadata: + labels: + app: webapp + spec: + containers: + - name: alpinexroot + image: alpine + command: ['sleep', '1d'] + ports: + - containerPort: 80 + hostPort: 80 + - name: alpineyroot + image: alpine + command: ['sleep', '1d'] + envFrom: + - configMapRef: + name: envdata + ports: + - containerPort: 7777 + hostPort: 7878 diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play1.yaml b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play1.yaml new file mode 100644 index 000000000..f24f2d497 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play1.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: web-deploy + labels: + app: webapp +spec: + selector: + matchLabels: + app: webapp + template: + metadata: + labels: + app: webapp + spec: + containers: + - name: alpinex + image: alpine + command: ['sleep', '1d'] + ports: + - containerPort: 8080 + - name: alpiney + image: alpine + command: ['sleep', '1d'] + ports: + - containerPort: 7777 diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play3.yaml b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play3.yaml new file mode 100644 index 000000000..2d18aec1a --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/files/play3.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: web-deploy + labels: + app: webapp +spec: + selector: + matchLabels: + app: webapp + template: + metadata: + labels: + app: webapp + spec: + containers: + - name: alpinex + image: alpine + command: ['sleep', '1d'] + envFrom: + - configMapRef: + name: envdata + ports: + - containerPort: 8080 + hostPort: 8080 + - name: alpiney + image: alpine + command: ['sleep', '1d'] + ports: + - containerPort: 7777 + hostPort: 8787 diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/main.yml new file mode 100644 index 000000000..30f53fa5f --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/main.yml @@ -0,0 +1,130 @@ +- name: Test podman play kube + block: + + - name: Discover podman version + shell: podman version | grep "^Version:" | awk {'print $2'} + register: podman_v + + - name: Discover cgroups version + shell: podman info | grep cgroupVersion | awk {'print $2'} + register: cgroups + + - name: Set cgroups version + set_fact: + cgroups_version: "{{ cgroups.stdout }}" + + - name: Copy files to known place + copy: + src: "{{ item }}" + dest: "/tmp/{{ item }}" + remote_src: false + loop: + - play1.yaml + - play3.yaml + - play-root1.yaml + - play-root3.yaml + - envdata.yaml + + - name: Delete all pods leftovers from tests + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - web-deploy + - web-deploy-pod + - web-deploy-pod-0 + + - name: Play kube file + containers.podman.podman_play: + executable: "{{ test_executable | default('podman') }}" + kube_file: /tmp/play1.yaml + state: started + register: play1 + + - name: Play same kube file again + containers.podman.podman_play: + executable: "{{ test_executable | default('podman') }}" + kube_file: /tmp/play1.yaml + state: started + register: play2 + + - name: Check info + assert: + that: + - play1 is changed + - play2 is not changed + + - name: Recreate play + containers.podman.podman_play: + executable: "{{ test_executable | default('podman') }}" + kube_file: /tmp/play1.yaml + state: started + recreate: true + register: play3 + + - name: Check info + assert: + that: + - play3 is changed + + - name: Check 'created' after 'started' + containers.podman.podman_play: + executable: "{{ test_executable | default('podman') }}" + kube_file: /tmp/play1.yaml + state: created + register: play4 + + - name: Check info + assert: + that: + - play4 is not changed + + - name: Run with configmap + containers.podman.podman_play: + executable: "{{ test_executable | default('podman') }}" + kube_file: /tmp/play3.yaml + debug: true + state: started + recreate: true + configmap: + - /tmp/envdata.yaml + register: play5 + + - name: Check info + assert: + that: + - play5 is changed + + - name: Check if pod is running well + containers.podman.podman_pod_info: + executable: "{{ test_executable | default('podman') }}" + name: web-deploy-pod + register: info1 + + - name: Check pod info + assert: + that: + - info1['pods'][0]['State'] == 'Running' + + always: + + - name: Delete all pods leftovers from tests + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - web-deploy + - web-deploy-pod + - web-deploy-pod-0 + - web-deploy-pod-1 + - web-deploy-pod-2 + +- name: Test idempotency for root pods + include_tasks: root-play.yml + vars: + ansible_python_interpreter: "/usr/bin/python" + args: + apply: + become: true diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/root-play.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/root-play.yml new file mode 100644 index 000000000..40a05211f --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_play/tasks/root-play.yml @@ -0,0 +1,105 @@ +- name: Test podman rootful pod play + block: + + - name: Discover cgroups version + shell: podman info | grep cgroupVersion | awk {'print $2'} + register: cgroups + + - name: Set cgroups version + set_fact: + cgroups_version: "{{ cgroups.stdout }}" + + - name: Delete all pods leftovers from tests + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - web-deploy-root + - web-deploy-root-pod + - web-deploy-root-pod-0 + + - name: Play kube file + containers.podman.podman_play: + executable: "{{ test_executable | default('podman') }}" + kube_file: /tmp/play-root1.yaml + state: started + register: play1 + + - name: Play same kube file again + containers.podman.podman_play: + executable: "{{ test_executable | default('podman') }}" + kube_file: /tmp/play-root1.yaml + state: started + register: play2 + + - name: Check info + assert: + that: + - play1 is changed + - play2 is not changed + + - name: Recreate play + containers.podman.podman_play: + executable: "{{ test_executable | default('podman') }}" + kube_file: /tmp/play-root1.yaml + state: started + recreate: true + register: play3 + + - name: Check info + assert: + that: + - play3 is changed + + - name: Check 'created' after 'started' + containers.podman.podman_play: + executable: "{{ test_executable | default('podman') }}" + kube_file: /tmp/play-root1.yaml + state: created + register: play4 + + - name: Check info + assert: + that: + - play4 is not changed + + - name: Run with configmap + containers.podman.podman_play: + executable: "{{ test_executable | default('podman') }}" + kube_file: /tmp/play-root3.yaml + state: started + recreate: true + configmap: + - /tmp/envdata.yaml + register: play5 + + - name: Check info + assert: + that: + - play5 is changed + + - name: Check if pod is running well + containers.podman.podman_pod_info: + executable: "{{ test_executable | default('podman') }}" + name: web-deploy-root-pod + register: info1 + + - name: Check pod info + assert: + that: + - info1['pods'][0]['State'] == 'Running' + + always: + + - name: Delete all pods leftovers from tests + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - web-deploy + - web-deploy-pod + - web-deploy-pod-0 + - web-deploy-pod-1 + - web-deploy-pod-2 diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/main.yml new file mode 100644 index 000000000..491d4a8a8 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/main.yml @@ -0,0 +1,883 @@ +- name: Test podman pod + block: + + - name: Discover podman version + shell: podman version | grep "^Version:" | awk {'print $2'} + register: podman_v + + - name: Set podman version to 1 + set_fact: + podman_version: 1 + when: podman_v.stdout is version('2.0.0', 'lt') + + - name: Set podman version to 2 + set_fact: + podman_version: 2 + when: podman_v.stdout is version('2.0.0', '>=') + + - name: Discover cgroups version + shell: podman info | grep cgroupVersion | awk {'print $2'} + register: cgroups + + - name: Set cgroups version + set_fact: + cgroups_version: "{{ cgroups.stdout }}" + + - name: Delete all pods leftovers from tests + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - "pod1" + - "pod2" + + - name: Delete all container leftovers from tests + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - "container1" + - "container2" + + - name: Create pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: created + register: pod1_info + + - name: Check info + assert: + that: + - >- + (pod1_info.pod['State']['status'] is defined and + pod1_info.pod['State']['status'] == 'Created') or + (pod1_info.pod['State']['status'] is not defined and + pod1_info.pod['State'] == 'Created') + + - name: Start pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + register: pod2_info + + - name: Check info + assert: + that: + - >- + (pod2_info.pod['State']['status'] is defined and + pod2_info.pod['State']['status'] == 'Running') or + (pod2_info.pod['State']['status'] is not defined and + pod2_info.pod['State'] == 'Running') + + # - name: Pause pod + # containers.podman.podman_pod: + # executable: "{{ test_executable | default('podman') }}" + # name: pod1 + # state: paused + # register: pod3_info + # when: cgroups_version == 'v2' + + # - name: Check info + # assert: + # that: + # - >- + # (pod3_info.pod['State']['status'] is defined and + # pod3_info.pod['State']['status'] == 'Paused') or + # (pod3_info.pod['State']['status'] is not defined and + # pod3_info.pod['State'] == 'Paused') + # when: cgroups_version == 'v2' + + # - name: Unpause pod + # containers.podman.podman_pod: + # executable: "{{ test_executable | default('podman') }}" + # name: pod1 + # state: unpaused + # register: pod4_info + # when: cgroups_version == 'v2' + + # - name: Check info + # assert: + # that: + # - >- + # (pod4_info.pod['State']['status'] is defined and + # pod4_info.pod['State']['status'] == 'Running') or + # (pod4_info.pod['State']['status'] is not defined and + # pod4_info.pod['State'] == 'Running') + # when: cgroups_version == 'v2' + + - name: Stop pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: stopped + register: pod5_info + + - name: Check info + assert: + that: + - >- + (pod5_info.pod['State']['status'] is defined and + pod5_info.pod['State']['status'] != 'Running') or + (pod5_info.pod['State']['status'] is not defined and + pod5_info.pod['State'] != 'Running') + + - name: Stop non-existing pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod-notexist + state: stopped + register: pod5a_info + ignore_errors: true + + - name: Check info + assert: + that: + - pod5a_info is failed + + - name: Kill pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: killed + register: pod6_info + + - name: Check info + assert: + that: + - >- + (pod6_info.pod['State']['status'] is defined and + pod6_info.pod['State']['status'] == 'Exited') or + (pod6_info.pod['State']['status'] is not defined and + pod6_info.pod['State'] == 'Exited') + + - name: Start pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + register: pod7_info + + - name: Check info + assert: + that: + - >- + (pod7_info.pod['State']['status'] is defined and + pod7_info.pod['State']['status'] == 'Running') or + (pod7_info.pod['State']['status'] is not defined and + pod7_info.pod['State'] == 'Running') + + - name: Start pod again for idempotency + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + register: pod8_info + + - name: Check info + assert: + that: + - pod8_info is not changed + + - name: Restart pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: restarted + register: pod121_info + + - name: Check info + assert: + that: + - pod121_info is changed + + - name: Stop pod before restart + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: stopped + + - name: Restart stopped pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: restarted + register: pod122_info + + - name: Check info + assert: + that: + - pod122_info is changed + + - name: Stop pod with additional config + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: stopped + ports: + - 9484:9483 + register: pod123_info + + - name: Check info + assert: + that: + - pod123_info is changed + - '"podman pod rm -f pod1" not in pod123_info.podman_actions' + + - name: Start pod with ports + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + ports: + - "4444:4444/tcp" + - "1212:5555" + - "8888:19191/udp" + - "1901:1901/udp" + - "127.0.0.1:7671:7676/udp" + - "127.0.0.1:12122:8876/udp" + - "127.0.0.1:13122:8871/tcp" + - "127.0.0.1:43423:8872" + register: pod9_info + + - name: Check info + assert: + that: + - pod9_info is changed + + - name: Start pod with ports for idempotency + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + ports: + - "4444:4444/tcp" + - "1212:5555" + - "8888:19191/udp" + - "1901:1901/udp" + - "127.0.0.1:7671:7676/udp" + - "127.0.0.1:12122:8876/udp" + - "127.0.0.1:13122:8871/tcp" + - "127.0.0.1:43423:8872" + register: pod10_info + + - name: Check info + assert: + that: + - pod10_info is not changed + + - name: Start pod again for idempotency + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + register: pod11_info + + - name: Check info + assert: + that: + - pod11_info is changed + + - name: Start pod with share + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + share: uts + register: pod12_info + + - name: Check info + assert: + that: + - pod12_info is changed + + - name: Start pod with share for idempotency + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + share: uts + register: pod13_info + + - name: Check info + assert: + that: + - pod13_info is not changed + + - name: Start pod with default shares + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + register: pod15_info + + - name: Check info + assert: + that: + - pod15_info is changed + + - name: Start pod with gidmap and uidmap + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + uidmap: 0:100:65536 + gidmap: 0:100:65536 + state: created + register: pod15_a_info + + - name: Check info + assert: + that: + - pod15_a_info is changed + + - name: Start pod with share for idempotency + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + uidmap: 0:100:65536 + gidmap: 0:100:65536 + state: created + register: pod15_b_info + + - name: Check info + assert: + that: + - pod15_b_info is not changed + + - name: Start pod with labels + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + label: + key: cval + otherkey: kddkdk + somekey: someval + register: pod16_info + + - name: Check info + assert: + that: + - pod16_info is changed + + - name: Start pod with labels again for idempotency + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + label: + key: cval + otherkey: kddkdk + somekey: someval + register: pod17_info + + - name: Check info + assert: + that: + - pod17_info is not changed + + - name: Start pod with different labels + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + label: + key: cval + otherkey: 23434dfsd + somekey: someval + register: pod18_info + + - name: Check info + assert: + that: + - pod18_info is changed + + - name: Start pod without labels + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + register: pod19_info + + - name: Check info + assert: + that: + - pod19_info is changed + + - name: Start pod with dns and hosts settings + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + add_host: + - "google:8.8.8.8" + - "site1:127.0.0.1" + dns: + - 1.1.1.1 + dns_opt: + - "option timeout:3" + dns_search: + - "redhat.com" + - "ibm.com" + hostname: happypod + register: pod20_info + + - name: Check info + assert: + that: + - pod20_info is changed + + - name: Start pod with dns and hosts settings again + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + add_host: + - "google:8.8.8.8" + - "site1:127.0.0.1" + dns: + - 1.1.1.1 + dns_opt: + - "option timeout:3" + dns_search: + - "redhat.com" + - "ibm.com" + hostname: happypod + register: pod21_info + + - name: Check info + assert: + that: + - pod21_info is not changed + + - name: Start pod with changed dns + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + add_host: + - "google:8.8.8.8" + - "site1:127.0.0.1" + dns: + - 1.1.1.1 + - 2.2.2.2 + dns_opt: + - "option timeout:3" + dns_search: + - "redhat.com" + - "ibm.com" + hostname: happypod + register: pod22_info + + - name: Check info + assert: + that: + - pod22_info is changed + + - name: Start pod with changed add host + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + add_host: + - "google:8.8.8.8" + - "site1:127.0.0.2" + dns: + - 1.1.1.1 + - 2.2.2.2 + dns_opt: + - "option timeout:3" + dns_search: + - "redhat.com" + - "ibm.com" + hostname: happypod + register: pod23_info + + - name: Check info + assert: + that: + - pod23_info is changed + + - name: Start pod with changed dns option + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + add_host: + - "google:8.8.8.8" + - "site1:127.0.0.2" + dns: + - 1.1.1.1 + - 2.2.2.2 + dns_opt: + - "option timeout:2" + dns_search: + - "redhat.com" + - "ibm.com" + hostname: happypod + register: pod24_info + + - name: Check info + assert: + that: + - pod24_info is changed + + - name: Start pod with changed dns search + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + add_host: + - "google:8.8.8.8" + - "site1:127.0.0.2" + dns: + - 1.1.1.1 + - 2.2.2.2 + dns_opt: + - "option timeout:2" + dns_search: + - "redhat.com" + hostname: happypod + register: pod25_info + + - name: Check info + assert: + that: + - pod25_info is changed + + - name: Start pod with changed hostname + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + add_host: + - "google:8.8.8.8" + - "site1:127.0.0.2" + dns: + - 1.1.1.1 + - 2.2.2.2 + dns_opt: + - "option timeout:2" + dns_search: + - "redhat.com" + hostname: bestpod + register: pod26_info + + - name: Check info + assert: + that: + - pod26_info is changed + + - name: Start pod with removed dns search + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + add_host: + - "google:8.8.8.8" + - "site1:127.0.0.2" + dns: + - 1.1.1.1 + - 2.2.2.2 + dns_opt: + - "option timeout:2" + hostname: bestpod + register: pod27_info + + - name: Check info + assert: + that: + - pod27_info is changed + + - name: Start pod with removed dns option + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + add_host: + - "google:8.8.8.8" + - "site1:127.0.0.2" + dns: + - 1.1.1.1 + - 2.2.2.2 + hostname: bestpod + register: pod28_info + + - name: Check info + assert: + that: + - pod28_info is changed + + - name: Start pod with removed dns + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + add_host: + - "google:8.8.8.8" + - "site1:127.0.0.2" + hostname: bestpod + register: pod29_info + + - name: Check info + assert: + that: + - pod29_info is changed + + - name: Start pod with removed add host + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + hostname: bestpod + register: pod30_info + + - name: Check info + assert: + that: + - pod30_info is changed + + - name: Start pod without infra + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: created + infra: false + register: pod31_info + + - name: Check info + assert: + that: + - pod31_info is changed + + - name: Start pod without infra again + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: created + infra: false + register: pod32_info + + - name: Check info + assert: + that: + - pod32_info is not changed + + - name: Start pod with infra + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + register: pod33_info + + - name: Check info + assert: + that: + - pod33_info is changed + + - name: Start pod with different infra image + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: created + infra_image: alpine:3.9 + register: pod34_info + + - name: Check info + assert: + that: + - pod34_info is changed + + - name: Start pod with different infra image again + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: created + infra_image: alpine:3.9 + register: pod35_info + + - name: Check info + assert: + that: + - pod35_info is not changed + + - name: Start pod2 with default settings + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod2 + state: created + register: pod36_info + + - name: Run container1 in pod + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container1 + image: alpine + command: top + pod: pod2 + state: started + + - name: Run container2 in pod + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container2 + image: alpine + command: top + pod: pod2 + state: started + + - name: Start pod2 + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod2 + state: started + generate_systemd: + path: /tmp/dir1 + restart_policy: always + time: 120 + no_header: true + names: true + pod_prefix: poditto + container_prefix: ainer + register: system1 + + - name: Check systemd file exists + stat: + path: /tmp/dir1/poditto-pod2.service + register: podsys_stat + + - name: Check that all settings from systemd are correct + assert: + that: + - system1.podman_systemd.keys() | list | length == 3 + - "'-t 120 ' in system1.podman_systemd['poditto-pod2']" + - "'Restart=always' in system1.podman_systemd['poditto-pod2']" + - "'autogenerated by Podman' not in system1.podman_systemd['poditto-pod2']" + - podsys_stat.stat.exists | bool + + - name: Delete pod2 + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod2 + state: absent + generate_systemd: + path: /tmp/dir1 + restart_policy: always + time: 120 + no_header: true + names: true + pod_prefix: poditto + container_prefix: ainer + + - name: Check if systemd file exists (should not) + stat: + path: /tmp/dir1/poditto-pod2.service + register: podsys2_stat + + - name: Check that systemd file was removed + assert: + that: + - not podsys2_stat.stat.exists|bool + + - name: Run pod2 with network slirp4netns + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod2 + state: started + network: slirp4netns:outbound_addr=10.10.10.46 + + - name: Run container1 in pod + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container1 + image: alpine + command: top + pod: pod2 + state: started + + - name: Run pod2 with network slirp4netns - again + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod2 + state: started + network: slirp4netns:outbound_addr=10.10.10.46 + register: slip4net_pod + + - name: Run container1 in pod slirp4netns + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container1 + image: alpine + command: top + pod: pod2 + state: started + register: slip4net_cont + + - name: Check that slirp4netns is idempotent + assert: + that: + - slip4net_pod is not changed + - slip4net_cont is not changed + + - name: Run pod2 with different network slirp4netns + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod2 + state: started + network: slirp4netns:outbound_addr=10.10.10.47 + register: slip4net_pod2 + + - name: Run container1 in different pod slirp4netns + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: container1 + image: alpine + command: top + pod: pod2 + state: started + register: slip4net_cont2 + + - name: Check that slirp4netns is idempotent and changed + assert: + that: + - slip4net_pod2 is changed + - slip4net_cont2 is changed + + always: + + - name: Delete all pods leftovers from tests + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - "pod1" + - "pod2" + + - name: Delete all container leftovers from tests + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - "container1" + - "container2" + +- name: Test idempotency for root pods + include_tasks: root-pod.yml + vars: + ansible_python_interpreter: "/usr/bin/python3" + args: + apply: + become: true + +- name: Test idempotency for root pods and networks + include_tasks: net-pod.yml + vars: + ansible_python_interpreter: "/usr/bin/python3" + args: + apply: + become: true diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/net-pod.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/net-pod.yml new file mode 100644 index 000000000..3341f52a8 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/net-pod.yml @@ -0,0 +1,78 @@ +- name: Test podman rootful pod + block: + + - name: Remove pods + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootnetpod" + state: absent + + - name: Delete all network leftovers from tests + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - testnet + - anothernet + + - name: Create network testnet + command: podman network create testnet --subnet 10.91.91.0/24 + + - name: Create network anothernet + command: podman network create anothernet --subnet 10.71.71.0/24 + + - name: List current networks + command: podman network ls + + - name: Set test data + set_fact: + testdata: + - first_net: host + next_net: bridge + - first_net: bridge + next_net: host + - first_net: anothernet + next_net: testnet + - first_net: testnet + next_net: + - testnet + - anothernet + - first_net: + - testnet + - anothernet + next_net: anothernet + - first_net: + - testnet + - anothernet + next_net: bridge + - first_net: + - testnet + - anothernet + next_net: host + - first_net: host + next_net: anothernet + - first_net: bridge + next_net: + - anothernet + - testnet + + - include_tasks: network-tests.yml + loop: "{{ testdata }}" + + always: + + - name: Delete all pods leftovers from tests + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootnetpod" + state: absent + + - name: Delete all network leftovers from tests + containers.podman.podman_network: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - testnet + - anothernet diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/network-tests.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/network-tests.yml new file mode 100644 index 000000000..12b7ae72a --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/network-tests.yml @@ -0,0 +1,43 @@ +--- +- name: Remove pod nettest + become: true + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: nettest + state: absent + +- name: Run pod with {{ item.first_net }} + become: true + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: nettest + state: started + network: "{{ item.first_net }}" + +- name: Run pod again with {{ item.first_net }} + become: true + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: nettest + state: started + network: "{{ item.first_net }}" + register: info + +- name: Check info that not changed + assert: + that: + - info is not changed + +- name: Run pod changed from {{ item.first_net }} to {{ item.next_net }} + become: true + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: nettest + state: started + network: "{{ item.next_net }}" + register: info1 + +- name: Check info + assert: + that: + - info1 is changed diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/root-pod.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/root-pod.yml new file mode 100644 index 000000000..968ec2cf3 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/root-pod.yml @@ -0,0 +1,179 @@ +- name: Test podman rootful pod + block: + + - name: Discover cgroups version + shell: podman info | grep cgroupVersion | awk {'print $2'} + register: cgroups + + - name: Set cgroups version + set_fact: + cgroups_version: "{{ cgroups.stdout }}" + + - name: Delete all pods leftovers from tests + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootpod" + state: absent + + - name: Create and start pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootpod" + state: started + + - name: Create and start pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootpod" + state: started + register: pod1_info + + - name: Check info + assert: + that: + - pod1_info is not changed + + - name: Add DNS to pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootpod" + state: started + dns: + - 1.1.1.1 + register: pod2_info + + - name: Check info + assert: + that: + - pod2_info is changed + + - name: Remove DNS from pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootpod" + state: started + register: pod3_info + + - name: Check info + assert: + that: + - pod3_info is changed + + - name: Create network newnet + command: podman network create newnet --subnet 10.90.90.0/24 + + - name: Create network net2 + command: podman network create net2 --subnet 10.70.70.0/24 + + - name: Start pod with networks + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootpod" + state: started + network: + - net2 + - newnet + register: pod4_info + + - name: Check info + assert: + that: + - pod4_info is changed + + - name: Start pod with networks again + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootpod" + state: started + network: + - newnet + - net2 + register: pod5_info + + - name: Check info + assert: + that: + - pod5_info is not changed + + - name: Start pod with one network + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootpod" + state: started + network: net2 + register: pod6_info + + - name: Check info + assert: + that: + - pod6_info is changed + + - name: Start pod without networks + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootpod" + state: started + register: pod7_info + + - name: Check info + assert: + that: + - pod7_info is changed + + - name: Start pod with ports for idempotency and ipv6 + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + ports: + - "4444:4444/tcp" + - "8888:19191/udp" + - "127.0.0.1:7671:7676/udp" + - "127.0.0.2:7671:7676/udp" + - "127.0.0.1:13122:8871/tcp" + - "127.0.0.1:43423:8872" + - "[::1]:8743:8745" + register: pod8_info + + - name: Check info + assert: + that: + - pod8_info is changed + + - name: Start pod with ports for idempotency and ipv6 again + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: pod1 + state: started + ports: + - "4444:4444/tcp" + - "8888:19191/udp" + - "127.0.0.1:7671:7676/udp" + - "127.0.0.2:7671:7676/udp" + - "127.0.0.1:13122:8871/tcp" + - "127.0.0.1:43423:8872" + - "[::1]:8743:8745" + register: pod9_info + + - name: Check info + assert: + that: + - pod9_info is not changed + + always: + + - name: Delete all pods leftovers from tests + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "rootpod" + state: absent + + - name: Delete all existing pods + shell: | + podman pod rm -fa; + ignore_errors: true + + - name: Delete all created networks + shell: | + podman network rm -f newnet net2 + ignore_errors: true diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_pod_info/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_pod_info/tasks/main.yml new file mode 100644 index 000000000..9c6066f6e --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_pod_info/tasks/main.yml @@ -0,0 +1,113 @@ +- name: Test podman_pod_info + block: + + - name: Print podman version + command: podman info --debug + + - name: Discover podman version + shell: podman version | grep "^Version:" | awk {'print $2'} + register: podman_version + + - name: Generate random value for pod name + set_fact: + pod_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}" + + - name: Make sure pod doesn't exist + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "{{ pod_name }}" + state: absent + + - name: Get missing pod info + containers.podman.podman_pod_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ pod_name }}" + register: nonexist + + - name: Check info for missing pod + assert: + that: + - nonexist.pods == [] + + - name: Get all missing pods info + containers.podman.podman_pod_info: + executable: "{{ test_executable | default('podman') }}" + register: nonexist2 + + - name: Check info for missing pod + assert: + that: + - nonexist2.pods == [] + + - name: Create test pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "{{ pod_name }}" + + - name: Get all pods info + containers.podman.podman_pod_info: + executable: "{{ test_executable | default('podman') }}" + register: info + + - name: Check info for pod + assert: + that: + - info.pods | length == 1 + - >- + (info.pods[0]['Config']['name'] is defined and + info.pods[0]['Config']['name'] == pod_name) or + (info.pods[0]['Name'] is defined and + info.pods[0]['Name'] == pod_name) + + - name: Get specific pod info + containers.podman.podman_pod_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ pod_name }}" + register: info2 + + - name: Check info for pod + assert: + that: + - info2.pods | length == 1 + - >- + (info2.pods[0]['Config']['name'] is defined and + info2.pods[0]['Config']['name'] == pod_name) or + (info2.pods[0]['Name'] is defined and + info2.pods[0]['Name'] == pod_name) + + - name: Create another test pod + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "{{ pod_name }}_1" + + - name: Get specific another pod info + containers.podman.podman_pod_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ pod_name }}" + register: info3 + + - name: Check info for missing pod + assert: + that: + - info3.pods | length == 1 + + - name: Get pods info + containers.podman.podman_pod_info: + executable: "{{ test_executable | default('podman') }}" + register: info4 + + - name: Check info for pods + assert: + that: + - info4.pods | length == 2 + + always: + + - name: Make sure pod doesn't exist + containers.podman.podman_pod: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - "{{ pod_name }}" + - "{{ pod_name }}_1" diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_prune/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_prune/tasks/main.yml new file mode 100644 index 000000000..804543fe5 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_prune/tasks/main.yml @@ -0,0 +1,131 @@ +- name: Create random names + ansible.builtin.set_fact: + cname: "{{ 'ansible-container-%0x' % ((2**32) | random) }}" + nname: "{{ 'ansible-network-%0x' % ((2**32) | random) }}" + vname: "{{ 'ansible-volume-%0x' % ((2**32) | random) }}" + +- name: Test podman_prune module + block: + # Create objects to be pruned + - name: Create container + containers.podman.podman_container: + name: "{{ cname }}" + image: quay.io/podman/hello:latest + state: present + register: container + + - name: Create network + containers.podman.podman_network: + name: "{{ nname }}" + state: present + register: network + + - name: Create volume + containers.podman.podman_volume: + name: "{{ vname }}" + state: present + register: volume + + # Prune objects + - name: Prune objects + containers.podman.podman_prune: + container: true + network: true + volume: true + + - name: Check if container exists + containers.podman.podman_container_info: + register: container_exists + + - name: Check if podman network exists + containers.podman.podman_network_info: + register: network_exists + + - name: Check if podman volume exists + containers.podman.podman_volume_info: + register: volume_exists + + - name: Verify assertions for network, container and volume + ansible.builtin.assert: + that: + # containers + - container.container.Id not in container_exists.containers | map(attribute='Name') | list | flatten + # networks + - network.network.name not in network_exists.networks | map(attribute='id') | list | flatten + # volumes + - volume.volume.Name not in volume_exists.volumes | map(attribute='Name') | list | flatten + + # Test with filters + - name: Prune objects with filters + containers.podman.podman_prune: + image: true + image_filters: + dangling_only: false + external: true + + - name: Check if image exists + containers.podman.podman_image_info: + register: image_exists + + - name: Verify assertions for image (with filters) + ansible.builtin.assert: + that: + - image_exists.images | length == 0 + + - name: Create container + containers.podman.podman_container: + name: "{{ cname }}" + image: quay.io/podman/hello:latest + state: present + register: container_system + + - name: Create network + containers.podman.podman_network: + name: "{{ nname }}" + state: present + register: network_system + + - name: Create volume + containers.podman.podman_volume: + name: "{{ vname }}" + state: present + register: volume_system + + - name: System prune + containers.podman.podman_prune: + system: true + system_all: true + system_volumes: true + + - name: Check if container exists + containers.podman.podman_container_info: + register: container_system_exists + + - name: Check if podman network exists + containers.podman.podman_network_info: + register: network_system_exists + + - name: Check if podman volume exists + containers.podman.podman_volume_info: + register: volume_system_exists + + - name: Check if image exists + containers.podman.podman_image_info: + register: image_system_exists + + - name: Verify assertions for system + ansible.builtin.assert: + that: + # container + - container_system.container.Id not in container_system_exists.containers | map(attribute='Name') | list | flatten + # networks + - network_system.network.name not in network_system_exists.networks | map(attribute='id') | list | flatten + # volumes + - volume_system.volume.Name not in volume_system_exists.volumes | map(attribute='Name') | list | flatten + # images + - image_system_exists.images | length == 0 + + always: + - name: Cleanup + ansible.builtin.command: podman system prune -a -f --volumes + ignore_errors: true diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_save/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_save/tasks/main.yml new file mode 100644 index 000000000..97c8a66f3 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_save/tasks/main.yml @@ -0,0 +1,99 @@ +--- +- name: Pull image + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: k8s.gcr.io/pause + +- name: Save image + containers.podman.podman_save: + executable: "{{ test_executable | default('podman') }}" + image: k8s.gcr.io/pause + dest: /tmp/image.tar + +- name: Check file + stat: + path: /tmp/image.tar + register: img + +- name: Check it's saved + assert: + that: + - img.stat.exists + +- name: Save image + containers.podman.podman_save: + executable: "{{ test_executable | default('podman') }}" + image: k8s.gcr.io/pause + dest: /tmp/image.tar + force: true + +- name: Check file + stat: + path: /tmp/image.tar + register: img + +- name: Check it's saved + assert: + that: + - img.stat.exists + +- name: Save image + containers.podman.podman_save: + executable: "{{ test_executable | default('podman') }}" + image: k8s.gcr.io/pause + dest: /tmp/imagedir + format: oci-dir + +- name: Check file + stat: + path: /tmp/imagedir + register: img + +- name: Check it's saved + assert: + that: + - img.stat.exists + +- name: Save image + containers.podman.podman_save: + executable: "{{ test_executable | default('podman') }}" + image: k8s.gcr.io/pause + dest: /tmp/imagedir-docker + force: true + format: docker-dir + compress: true + +- name: Save image + containers.podman.podman_save: + executable: "{{ test_executable | default('podman') }}" + image: k8s.gcr.io/pause + dest: /tmp/imagedir + force: true + format: oci-dir + +- name: Check file + stat: + path: /tmp/imagedir + register: img + +- name: Check it's saved + assert: + that: + - img.stat.exists + +- name: Save image + containers.podman.podman_save: + executable: "{{ test_executable | default('podman') }}" + image: k8s.gcr.io/pause + dest: /tmp/image2.tar + multi_image_archive: true + +- name: Check file + stat: + path: /tmp/image2.tar + register: img + +- name: Check it's saved + assert: + that: + - img.stat.exists diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_secret/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_secret/tasks/main.yml new file mode 100644 index 000000000..c6c90de90 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_secret/tasks/main.yml @@ -0,0 +1,117 @@ +- name: Test podman_secret + block: + + - name: Make sure secret doesn't exist + containers.podman.podman_secret: + executable: "{{ test_executable | default('podman') }}" + state: absent + name: mysecret + + - name: Create secret + containers.podman.podman_secret: + executable: "{{ test_executable | default('podman') }}" + name: mysecret + data: secret content + + - name: Recreate secret + containers.podman.podman_secret: + executable: "{{ test_executable | default('podman') }}" + name: mysecret + data: super secret content + force: true + register: forced + + - name: Skip secret + containers.podman.podman_secret: + executable: "{{ test_executable | default('podman') }}" + name: mysecret + data: super secret content + skip_existing: true + register: skipped + + - name: Check assertions + assert: + that: + - forced is changed + - skipped is not changed + + - name: Create container that uses secret + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: showmysecret + image: alpine:3.7 + secrets: + - mysecret + command: cat /run/secrets/mysecret + detach: false + rm: true + register: container + + - name: Check secret data + assert: + that: + - container.stdout == "super secret content" + + - name: Create container that uses secret with options + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: showmysecret + image: alpine:3.7 + secrets: + - mysecret,type=env,target=SECRET + command: ['/bin/sh', '-c', 'echo $SECRET'] + detach: false + rm: true + register: container + + - name: Check secret data + assert: + that: + - container.stdout == "super secret content\n" + + - name: Remove secret + containers.podman.podman_secret: + executable: "{{ test_executable | default('podman') }}" + state: absent + name: mysecret + register: removed + + - name: Check removed is changed + assert: + that: + - removed is changed + + - name: Remove secret + containers.podman.podman_secret: + executable: "{{ test_executable | default('podman') }}" + state: absent + name: mysecret + register: removed + + - name: Check removed is not changed + assert: + that: + - removed is not changed + + - name: Create secret with file driver and custom options + containers.podman.podman_secret: + executable: "{{ test_executable | default('podman') }}" + name: mysecret + data: secret content + driver: file + driver_opts: + a: b + c: d + + - name: Remove secret + containers.podman.podman_secret: + executable: "{{ test_executable | default('podman') }}" + state: absent + name: mysecret + + always: + - name: Remove container that uses secret + containers.podman.podman_container: + executable: "{{ test_executable | default('podman') }}" + name: showmysecret + state: absent diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_tag/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_tag/tasks/main.yml new file mode 100644 index 000000000..ee7a6e254 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_tag/tasks/main.yml @@ -0,0 +1,40 @@ +--- +- name: Test podman tag + block: + - name: Pull image + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/library/alpine + + - name: Tag image + containers.podman.podman_tag: + executable: "{{ test_executable | default('podman') }}" + image: docker.io/library/alpine + target_names: + - openjdk8 + - jdk8 + + - name: Get tagged image info + containers.podman.podman_image_info: + executable: "{{ test_executable | default('podman') }}" + name: docker.io/library/alpine + register: tagged_image_result + + - name: Check results + assert: + that: + - tagged_image_result.images | length == 1 + - "'docker.io/library/alpine' in tagged_image_result.images[0]['RepoTags'][0]" + - "'localhost/openjdk8:latest' in tagged_image_result.images[0]['RepoTags'][1]" + - "'localhost/jdk8:latest' in tagged_image_result.images[0]['RepoTags'][2]" + + always: + - name: Cleanup image + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: "{{ item }}" + state: absent + loop: + - docker.io/library/alpine + - localhost/openjdk8 + - localhost/jdk8 diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_volume/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_volume/tasks/main.yml new file mode 100644 index 000000000..144a39f63 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_volume/tasks/main.yml @@ -0,0 +1,170 @@ +- name: Test podman_volume + block: + + - name: Print podman version + command: "{{ podman_cmd | default('podman') }} version" + + - name: Generate random value for volume name + set_fact: + volume_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}" + + - name: Make sure volume doesn't exist + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: absent + + - name: Get missing volume info + containers.podman.podman_volume_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + register: info + ignore_errors: true + + - name: Check results + assert: + that: + - info is failed + + - name: Create volume + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + register: vol + + - name: Get existing volume info + containers.podman.podman_volume_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + register: info1 + + - name: Check info + assert: + that: + - info1 | length > 1 + - info1.volumes.0.Name == volume_name + - vol is changed + + - name: Create volume again + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: present + register: info2 + + - name: Check info + assert: + that: + - info2 is not changed + + - name: Create volume with labels + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: present + label: + key: val + nokey: noval + register: info3 + + - name: Check info + assert: + that: + - info3 is changed + + - name: Create volume with labels again + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: present + label: + key: val + nokey: noval + register: info4 + + - name: Check info + assert: + that: + - info4 is not changed + + - name: Create volume w/o labels + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: present + register: info5 + + - name: Check info + assert: + that: + - info5 is changed + + - name: Create volume with options + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: present + options: + - "device=/dev/something" + - "type=ext4" + register: info6 + + - name: Check info + assert: + that: + - info6 is changed + + - name: Create volume with options again + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: present + options: + - "device=/dev/something" + - "type=ext4" + register: info7 + + - name: Check info + assert: + that: + - info7 is not changed + + - name: Create volume w/o options + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: present + register: info8 + + - name: Check info + assert: + that: + - info8 is changed + + - name: Make sure volume doesn't exist + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: absent + register: delete + + - name: Get existing volume info + containers.podman.podman_volume_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + register: info10 + ignore_errors: true + + - name: Check results + assert: + that: + - info10 is failed + - delete.volume == {} + + always: + + - name: Make sure volume doesn't exist + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: absent diff --git a/ansible_collections/containers/podman/tests/integration/targets/podman_volume_info/tasks/main.yml b/ansible_collections/containers/podman/tests/integration/targets/podman_volume_info/tasks/main.yml new file mode 100644 index 000000000..95fe1fb26 --- /dev/null +++ b/ansible_collections/containers/podman/tests/integration/targets/podman_volume_info/tasks/main.yml @@ -0,0 +1,71 @@ +- name: Test podman_volume_info + block: + + - name: Print podman version + command: "{{ podman_cmd | default('podman') }} version" + + - name: Generate random value for volume name + set_fact: + volume_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}" + + - name: Make sure volume doesn't exist + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: absent + + - name: Get missing volume info + containers.podman.podman_volume_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + register: nonexist + ignore_errors: true + + - name: Check results + assert: + that: + - "'volumes' not in nonexist" + - nonexist is failed + + - name: Make sure volume exists + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: present + + - name: Get existing volume info + containers.podman.podman_volume_info: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + register: existing_volume + + - name: Dump podman volume inspect result + debug: var=existing_volume + + - name: Comparison with 'podman volume inspect' + command: "{{ podman_cmd | default('podman') }} volume inspect {{ volume_name }}" + register: podman_inspect + + - name: Convert podman inspect output to JSON + set_fact: + podman_inspect_result: "{{ podman_inspect.stdout | from_json }}" + + - name: Cleanup + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: absent + + - name: Make checks + assert: + that: + - "'volumes' in existing_volume" + - existing_volume.volumes + - "existing_volume.volumes == podman_inspect_result" + always: + + - name: Cleanup + containers.podman.podman_volume: + executable: "{{ test_executable | default('podman') }}" + name: "{{ volume_name }}" + state: absent diff --git a/ansible_collections/containers/podman/tests/sanity/ignore-2.10.txt b/ansible_collections/containers/podman/tests/sanity/ignore-2.10.txt new file mode 100644 index 000000000..f2f4ca9ca --- /dev/null +++ b/ansible_collections/containers/podman/tests/sanity/ignore-2.10.txt @@ -0,0 +1,2 @@ +tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086 +tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086 diff --git a/ansible_collections/containers/podman/tests/sanity/ignore-2.11.txt b/ansible_collections/containers/podman/tests/sanity/ignore-2.11.txt new file mode 100644 index 000000000..f2f4ca9ca --- /dev/null +++ b/ansible_collections/containers/podman/tests/sanity/ignore-2.11.txt @@ -0,0 +1,2 @@ +tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086 +tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086 diff --git a/ansible_collections/containers/podman/tests/sanity/ignore-2.12.txt b/ansible_collections/containers/podman/tests/sanity/ignore-2.12.txt new file mode 100644 index 000000000..f2f4ca9ca --- /dev/null +++ b/ansible_collections/containers/podman/tests/sanity/ignore-2.12.txt @@ -0,0 +1,2 @@ +tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086 +tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086 diff --git a/ansible_collections/containers/podman/tests/sanity/ignore-2.13.txt b/ansible_collections/containers/podman/tests/sanity/ignore-2.13.txt new file mode 100644 index 000000000..f2f4ca9ca --- /dev/null +++ b/ansible_collections/containers/podman/tests/sanity/ignore-2.13.txt @@ -0,0 +1,2 @@ +tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086 +tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086 diff --git a/ansible_collections/containers/podman/tests/sanity/ignore-2.14.txt b/ansible_collections/containers/podman/tests/sanity/ignore-2.14.txt new file mode 100644 index 000000000..f2f4ca9ca --- /dev/null +++ b/ansible_collections/containers/podman/tests/sanity/ignore-2.14.txt @@ -0,0 +1,2 @@ +tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086 +tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086 diff --git a/ansible_collections/containers/podman/tests/sanity/ignore-2.15.txt b/ansible_collections/containers/podman/tests/sanity/ignore-2.15.txt new file mode 100644 index 000000000..f2f4ca9ca --- /dev/null +++ b/ansible_collections/containers/podman/tests/sanity/ignore-2.15.txt @@ -0,0 +1,2 @@ +tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086 +tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086 diff --git a/ansible_collections/containers/podman/tests/sanity/ignore-2.16.txt b/ansible_collections/containers/podman/tests/sanity/ignore-2.16.txt new file mode 100644 index 000000000..f2f4ca9ca --- /dev/null +++ b/ansible_collections/containers/podman/tests/sanity/ignore-2.16.txt @@ -0,0 +1,2 @@ +tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086 +tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086 diff --git a/ansible_collections/containers/podman/tests/sanity/ignore-2.17.txt b/ansible_collections/containers/podman/tests/sanity/ignore-2.17.txt new file mode 100644 index 000000000..f2f4ca9ca --- /dev/null +++ b/ansible_collections/containers/podman/tests/sanity/ignore-2.17.txt @@ -0,0 +1,2 @@ +tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086 +tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086 diff --git a/ansible_collections/containers/podman/tests/sanity/ignore-2.18.txt b/ansible_collections/containers/podman/tests/sanity/ignore-2.18.txt new file mode 100644 index 000000000..f2f4ca9ca --- /dev/null +++ b/ansible_collections/containers/podman/tests/sanity/ignore-2.18.txt @@ -0,0 +1,2 @@ +tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086 +tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086 diff --git a/ansible_collections/containers/podman/tests/sanity/ignore-2.9.txt b/ansible_collections/containers/podman/tests/sanity/ignore-2.9.txt new file mode 100644 index 000000000..f2f4ca9ca --- /dev/null +++ b/ansible_collections/containers/podman/tests/sanity/ignore-2.9.txt @@ -0,0 +1,2 @@ +tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086 +tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086 diff --git a/ansible_collections/containers/podman/tests/sanity/requirements.txt b/ansible_collections/containers/podman/tests/sanity/requirements.txt new file mode 100644 index 000000000..fd9f609dc --- /dev/null +++ b/ansible_collections/containers/podman/tests/sanity/requirements.txt @@ -0,0 +1,8 @@ +packaging # needed for update-bundled and changelog +sphinx ; python_version >= '3.5' # docs build requires python 3+ +sphinx-notfound-page ; python_version >= '3.5' # docs build requires python 3+ +straight.plugin ; python_version >= '3.5' # needed for hacking/build-ansible.py which will host changelog generation and requires python 3+ +voluptuous +yamllint +pylint +virtualenv diff --git a/ansible_collections/containers/podman/tests/unit/plugins/modules/test_common.py b/ansible_collections/containers/podman/tests/unit/plugins/modules/test_common.py new file mode 100644 index 000000000..583e26dee --- /dev/null +++ b/ansible_collections/containers/podman/tests/unit/plugins/modules/test_common.py @@ -0,0 +1,19 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import pytest + +from ansible_collections.containers.podman.plugins.module_utils.podman.common import ( + lower_keys, +) + + +@pytest.mark.parametrize('test_input, expected', [ + (["AAA", "BBB"], ["AAA", "BBB"]), + ("AAQQ", "AAQQ"), + ({"AAA": "AaaAa", "11": 22, "AbCdEf": None, "bbb": "aaaAA"}, + {"aaa": "AaaAa", "11": 22, "abcdef": None, "bbb": "aaaAA"}) +]) +def test_lower_keys(test_input, expected): + print(lower_keys.__code__.co_filename) + assert lower_keys(test_input) == expected diff --git a/ansible_collections/containers/podman/tests/unit/plugins/modules/test_container_lib.py b/ansible_collections/containers/podman/tests/unit/plugins/modules/test_container_lib.py new file mode 100644 index 000000000..20dd4e66c --- /dev/null +++ b/ansible_collections/containers/podman/tests/unit/plugins/modules/test_container_lib.py @@ -0,0 +1,89 @@ +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import pytest + +from ansible_collections.containers.podman.plugins.module_utils.podman.podman_container_lib import ( + PodmanModuleParams, + PodmanContainerDiff, +) + + +@pytest.mark.parametrize( + "test_input, expected", + [ + ( + { + "cap_add": ["SYS_ADMIN"], + "name": "testcont", + "image": "testimage", + "command": None, + }, + [ + b"create", + b"--name", + b"testcont", + b"--cap-add", + b"SYS_ADMIN", + b"testimage", + ], + ), + ( + { + "stop_signal": 9, + "name": "testcont", + "image": "testimage", + "command": None, + "sig_proxy": True, + }, + [ + b"create", + b"--name", + b"testcont", + b"--stop-signal", + b"9", + b"--sig-proxy=True", + b"testimage", + ], + ), + ], +) +def test_container_add_params(test_input, expected): + podm = PodmanModuleParams( + "create", + test_input, + "4.0.0", + None, + ) + assert podm.construct_command_from_params() == expected + + +@pytest.mark.parametrize( + "test_input, expected", + [ + ( + [ + None, # module + {"conmon_pidfile": "bbb"}, # module params + {"conmonpidfile": "ccc"}, # container info + {}, # image info + "4.1.1", # podman version + ], + True, + ), + ( + [ + None, # module + {"conmon_pidfile": None}, # module params + {"conmonpidfile": "ccc"}, # container info + {}, # image info + "4.1.1", # podman version + ], + False, + ), + ], +) +def test_container_diff(test_input, expected): + diff = PodmanContainerDiff(*test_input) + assert diff.diffparam_conmon_pidfile() == expected |