add docker examples
This commit is contained in:
@ -0,0 +1,5 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
hidden
|
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -eux
|
||||
|
||||
[ -f "${INVENTORY}" ]
|
||||
|
||||
# Run connection tests with both the default and C locale.
|
||||
|
||||
ansible-playbook test_connection.yml -i "${INVENTORY}" "$@"
|
||||
|
||||
if ansible --version | grep ansible | grep -E ' 2\.(9|10|11|12|13)\.'; then
|
||||
LC_ALL=C LANG=C ansible-playbook test_connection.yml -i "${INVENTORY}" "$@"
|
||||
fi
|
@ -0,0 +1,48 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- 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
|
||||
- ansible.builtin.wait_for_connection:
|
@ -0,0 +1,7 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/4
|
||||
skip/docker # coverage does not work if we're inside a docker container, since we cannot access this container's /tmp dir from the new container; also privileged doesn't work
|
||||
destructive
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker
|
@ -0,0 +1 @@
|
||||
../connection_posix/test.sh
|
@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# If you use another image, you possibly also need to adjust
|
||||
# ansible_python_interpreter in test_connection.inventory.
|
||||
source ../setup_docker/vars/main.env
|
||||
IMAGE="${DOCKER_TEST_IMAGE_PYTHON3}"
|
||||
|
||||
# Setup phase
|
||||
|
||||
echo "Setup"
|
||||
ANSIBLE_ROLES_PATH=.. ansible-playbook setup.yml
|
||||
|
||||
# If docker wasn't installed, don't run the tests
|
||||
if [ "$(command -v docker)" == "" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
# Test phase
|
||||
|
||||
CONTAINER_SUFFIX=-${RANDOM}
|
||||
|
||||
DOCKER_CONTAINERS="docker-connection-test-container${CONTAINER_SUFFIX}"
|
||||
|
||||
[[ -n "$DEBUG" || -n "$ANSIBLE_DEBUG" ]] && set -x
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cleanup() {
|
||||
echo "Cleanup"
|
||||
docker rm -f ${DOCKER_CONTAINERS}
|
||||
echo "Shutdown"
|
||||
ANSIBLE_ROLES_PATH=.. ansible-playbook shutdown.yml
|
||||
echo "Done"
|
||||
}
|
||||
|
||||
trap cleanup INT TERM EXIT
|
||||
|
||||
echo "Start containers"
|
||||
for CONTAINER in ${DOCKER_CONTAINERS}; do
|
||||
if [ "${ANSIBLE_TEST_COVERAGE:-}" == "" ]; then
|
||||
docker run --rm --name "${CONTAINER}" --detach "${IMAGE}" /bin/sh -c 'sleep 10m'
|
||||
else
|
||||
docker run --rm --name "${CONTAINER}" --detach -v /tmp:/tmp "${IMAGE}" /bin/sh -c 'sleep 10m'
|
||||
docker exec "${CONTAINER}" pip3 install coverage
|
||||
fi
|
||||
echo "${CONTAINER}"
|
||||
done
|
||||
|
||||
cat > test_connection.inventory << EOF
|
||||
[docker]
|
||||
docker-no-pipelining ansible_pipelining=false
|
||||
docker-pipelining ansible_pipelining=true
|
||||
docker-working-dir ansible_docker_working_dir=/home
|
||||
docker-privileged ansible_docker_privileged=true
|
||||
|
||||
[docker:vars]
|
||||
ansible_host=docker-connection-test-container${CONTAINER_SUFFIX}
|
||||
ansible_connection=community.docker.docker
|
||||
ansible_python_interpreter=/usr/local/bin/python3
|
||||
EOF
|
||||
|
||||
echo "Run tests"
|
||||
./runme-connection.sh "$@"
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- hosts: localhost
|
||||
connection: local
|
||||
vars:
|
||||
docker_skip_cleanup: true
|
||||
|
||||
tasks:
|
||||
- name: Setup docker
|
||||
import_role:
|
||||
name: setup_docker
|
@ -0,0 +1,20 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- hosts: localhost
|
||||
connection: local
|
||||
vars:
|
||||
docker_skip_cleanup: true
|
||||
|
||||
tasks:
|
||||
- name: Remove docker packages
|
||||
action: "{{ ansible_facts.pkg_mgr }}"
|
||||
args:
|
||||
name:
|
||||
- docker
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
state: absent
|
||||
when: not docker_skip_cleanup
|
@ -0,0 +1,7 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/4
|
||||
skip/docker # coverage does not work if we're inside a docker container, since we cannot access this container's /tmp dir from the new container; also privileged doesn't work
|
||||
destructive
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker
|
||||
- setup_docker_python_deps
|
@ -0,0 +1 @@
|
||||
../connection_posix/test.sh
|
@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# If you use another image, you possibly also need to adjust
|
||||
# ansible_python_interpreter in test_connection.inventory.
|
||||
source ../setup_docker/vars/main.env
|
||||
IMAGE="${DOCKER_TEST_IMAGE_PYTHON3}"
|
||||
|
||||
# Setup phase
|
||||
|
||||
echo "Setup"
|
||||
ANSIBLE_ROLES_PATH=.. ansible-playbook setup.yml
|
||||
|
||||
# If docker wasn't installed, don't run the tests
|
||||
if [ "$(command -v docker)" == "" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
# Test phase
|
||||
|
||||
CONTAINER_SUFFIX=-${RANDOM}
|
||||
|
||||
DOCKER_CONTAINERS="docker-connection-test-container${CONTAINER_SUFFIX}"
|
||||
|
||||
[[ -n "$DEBUG" || -n "$ANSIBLE_DEBUG" ]] && set -x
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cleanup() {
|
||||
echo "Cleanup"
|
||||
docker rm -f ${DOCKER_CONTAINERS}
|
||||
echo "Shutdown"
|
||||
ANSIBLE_ROLES_PATH=.. ansible-playbook shutdown.yml
|
||||
echo "Done"
|
||||
}
|
||||
|
||||
trap cleanup INT TERM EXIT
|
||||
|
||||
echo "Start containers"
|
||||
for CONTAINER in ${DOCKER_CONTAINERS}; do
|
||||
if [ "${ANSIBLE_TEST_COVERAGE:-}" == "" ]; then
|
||||
docker run --rm --name "${CONTAINER}" --detach "${IMAGE}" /bin/sh -c 'sleep 10m'
|
||||
else
|
||||
docker run --rm --name "${CONTAINER}" --detach -v /tmp:/tmp "${IMAGE}" /bin/sh -c 'sleep 10m'
|
||||
docker exec "${CONTAINER}" pip3 install coverage
|
||||
fi
|
||||
echo "${CONTAINER}"
|
||||
done
|
||||
|
||||
cat > test_connection.inventory << EOF
|
||||
[docker_api]
|
||||
docker_api-no-pipelining ansible_pipelining=false
|
||||
docker_api-pipelining ansible_pipelining=true
|
||||
docker_api-working-dir ansible_docker_working_dir=/home
|
||||
docker_api-privileged ansible_docker_privileged=true
|
||||
|
||||
[docker_api:vars]
|
||||
ansible_host=docker-connection-test-container${CONTAINER_SUFFIX}
|
||||
ansible_connection=community.docker.docker_api
|
||||
ansible_python_interpreter=/usr/local/bin/python3
|
||||
EOF
|
||||
|
||||
echo "Run tests"
|
||||
./runme-connection.sh "$@"
|
@ -0,0 +1,18 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- hosts: localhost
|
||||
connection: local
|
||||
vars:
|
||||
docker_skip_cleanup: true
|
||||
|
||||
tasks:
|
||||
- name: Setup docker
|
||||
import_role:
|
||||
name: setup_docker
|
||||
|
||||
- name: Setup docker Python deps
|
||||
import_role:
|
||||
name: setup_docker_python_deps
|
@ -0,0 +1,20 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- hosts: localhost
|
||||
connection: local
|
||||
vars:
|
||||
docker_skip_cleanup: true
|
||||
|
||||
tasks:
|
||||
- name: Remove docker packages
|
||||
action: "{{ ansible_facts.pkg_mgr }}"
|
||||
args:
|
||||
name:
|
||||
- docker
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
state: absent
|
||||
when: not docker_skip_cleanup
|
@ -0,0 +1,8 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/5
|
||||
skip/docker # this requires unfettered access to the container host
|
||||
skip/rhel7.9 # nsenter does not work out of the box
|
||||
destructive
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker
|
@ -0,0 +1 @@
|
||||
../connection_posix/test.sh
|
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
[[ -n "${DEBUG:-}" || -n "${ANSIBLE_DEBUG:-}" ]] && set -x
|
||||
|
||||
readonly IMAGE="quay.io/ansible/ansible-runner:devel"
|
||||
# shellcheck disable=SC2155
|
||||
readonly PYTHON="$(command -v python3 python | head -n1)"
|
||||
|
||||
# Determine collection root
|
||||
COLLECTION_ROOT=./
|
||||
while true; do
|
||||
if [ -e ${COLLECTION_ROOT}galaxy.yml ] || [ -e ${COLLECTION_ROOT}MANIFEST.json ]; then
|
||||
break
|
||||
fi
|
||||
COLLECTION_ROOT="${COLLECTION_ROOT}../"
|
||||
done
|
||||
# shellcheck disable=SC2155
|
||||
readonly COLLECTION_ROOT="$(cd ${COLLECTION_ROOT} ; pwd)"
|
||||
|
||||
# Setup phase
|
||||
echo "Setup"
|
||||
ANSIBLE_ROLES_PATH=.. ansible-playbook setup.yml
|
||||
|
||||
# If docker wasn't installed, don't run the tests
|
||||
if [ "$(command -v docker)" == "" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
echo "Cleanup"
|
||||
echo "Shutdown"
|
||||
ANSIBLE_ROLES_PATH=.. ansible-playbook shutdown.yml
|
||||
echo "Done"
|
||||
}
|
||||
|
||||
envs=(--env "HOME=${HOME:-}")
|
||||
while IFS=$'\0' read -d '' -r line; do
|
||||
key="$(echo "$line" | cut -d= -f1)"
|
||||
value="$(echo "$line" | cut -d= -f2-)"
|
||||
if [[ "${key}" =~ ^(ANSIBLE_|JUNIT_OUTPUT_DIR$|OUTPUT_DIR$|PYTHONPATH$) ]]; then
|
||||
envs+=(--env "${key}=${value}")
|
||||
fi
|
||||
done < <(printenv -0)
|
||||
|
||||
# Test phase
|
||||
cat > test_connection.inventory << EOF
|
||||
[nsenter]
|
||||
nsenter-no-pipelining ansible_pipelining=false
|
||||
nsenter-pipelining ansible_pipelining=true
|
||||
|
||||
[nsenter:vars]
|
||||
ansible_host=localhost
|
||||
ansible_connection=community.docker.nsenter
|
||||
ansible_host_volume_mount=/host
|
||||
ansible_nsenter_pid=1
|
||||
ansible_python_interpreter=${PYTHON}
|
||||
EOF
|
||||
|
||||
echo "Run tests"
|
||||
set -x
|
||||
docker run \
|
||||
-i \
|
||||
--rm \
|
||||
--privileged \
|
||||
--pid host \
|
||||
"${envs[@]}" \
|
||||
--volume "${COLLECTION_ROOT}:${COLLECTION_ROOT}" \
|
||||
--workdir "$(pwd)" \
|
||||
"${IMAGE}" \
|
||||
./runme-connection.sh "$@"
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- hosts: localhost
|
||||
connection: local
|
||||
vars:
|
||||
docker_skip_cleanup: true
|
||||
|
||||
tasks:
|
||||
- name: Setup docker
|
||||
import_role:
|
||||
name: setup_docker
|
@ -0,0 +1,20 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- hosts: localhost
|
||||
connection: local
|
||||
vars:
|
||||
docker_skip_cleanup: true
|
||||
|
||||
tasks:
|
||||
- name: Remove docker packages
|
||||
action: "{{ ansible_facts.pkg_mgr }}"
|
||||
args:
|
||||
name:
|
||||
- docker
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
state: absent
|
||||
when: not docker_skip_cleanup
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
needs/target/connection
|
||||
hidden
|
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -eux
|
||||
|
||||
# Connection tests for POSIX platforms use this script by linking to it from the appropriate 'connection_' target dir.
|
||||
# The name of the inventory group to test is extracted from the directory name following the 'connection_' prefix.
|
||||
|
||||
PYTHON="$(command -v python3 python | head -n1)"
|
||||
|
||||
group=$(${PYTHON} -c \
|
||||
"from os import path; print(path.basename(path.abspath(path.dirname('$0'))).replace('connection_', ''))")
|
||||
|
||||
cd ../connection
|
||||
|
||||
INVENTORY="../connection_${group}/test_connection.inventory" ./test.sh \
|
||||
-e target_hosts="${group}" \
|
||||
-e action_prefix= \
|
||||
-e local_tmp=/tmp/ansible-local \
|
||||
-e remote_tmp=/tmp/ansible-remote \
|
||||
"$@"
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/4
|
||||
skip/rhel
|
@ -0,0 +1,41 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- name: Get facts
|
||||
current_container_facts:
|
||||
register: result
|
||||
|
||||
# WARNING: This is not a proper test as it won't fail when the module does not work!
|
||||
# To make this a proper test, we need to know the environment in which this
|
||||
# test runs, which we do not know in general...
|
||||
|
||||
- name: Print facts
|
||||
ansible.builtin.debug:
|
||||
var: result.ansible_facts
|
||||
|
||||
- name: Read files
|
||||
ansible.builtin.slurp:
|
||||
src: '{{ item }}'
|
||||
loop:
|
||||
- /proc/self/cgroup
|
||||
- /proc/self/cpuset
|
||||
- /proc/self/mountinfo
|
||||
register: slurp
|
||||
ignore_errors: true
|
||||
|
||||
- name: Print files
|
||||
ansible.builtin.debug:
|
||||
msg: |-
|
||||
{{ item.content | ansible.builtin.b64decode | split('
|
||||
') }}
|
||||
loop: '{{ slurp.results }}'
|
||||
loop_control:
|
||||
label: '{{ item.source | default(item.item) }}'
|
||||
when: item is not failed
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/4
|
||||
destructive
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker_cli_compose
|
||||
# The Python dependencies are needed for the other modules
|
||||
- setup_docker_python_deps
|
||||
- setup_remote_tmp_dir
|
@ -0,0 +1,56 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
# Create random name prefix (for services, ...)
|
||||
- name: Create random container name prefix
|
||||
set_fact:
|
||||
name_prefix: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
cnames: []
|
||||
dnetworks: []
|
||||
images: []
|
||||
|
||||
- debug:
|
||||
msg: "Using name prefix {{ name_prefix }}"
|
||||
|
||||
# Run the tests
|
||||
- block:
|
||||
- name: Show docker compose --help output
|
||||
command: docker compose --help
|
||||
|
||||
- include_tasks: run-test.yml
|
||||
with_fileglob:
|
||||
- "tests/*.yml"
|
||||
loop_control:
|
||||
loop_var: test_name
|
||||
|
||||
always:
|
||||
- name: "Make sure all containers are removed"
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
loop: "{{ cnames }}"
|
||||
diff: false
|
||||
|
||||
- name: "Make sure all networks are removed"
|
||||
docker_network:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force: true
|
||||
loop: "{{ dnetworks }}"
|
||||
diff: false
|
||||
|
||||
- name: "Make sure all images are removed"
|
||||
docker_image_remove:
|
||||
name: "{{ item }}"
|
||||
loop: "{{ images }}"
|
||||
diff: false
|
||||
|
||||
when: docker_has_compose and docker_compose_version is version('2.18.0', '>=')
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: "Loading tasks from {{ test_name }}"
|
||||
include_tasks: "{{ test_name }}"
|
@ -0,0 +1,135 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- vars:
|
||||
pname: "{{ name_prefix }}-build"
|
||||
cname: "{{ name_prefix }}-container"
|
||||
iname: "{{ name_prefix }}-image"
|
||||
project_src: "{{ remote_tmp_dir }}/{{ pname }}"
|
||||
test_service: |
|
||||
services:
|
||||
{{ cname }}:
|
||||
build: ./build
|
||||
image: "{{ iname }}"
|
||||
pull_policy: never
|
||||
stop_grace_period: 1s
|
||||
|
||||
block:
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [pname ~ '-' ~ cname ~ '-1'] }}"
|
||||
dnetworks: "{{ dnetworks + [pname ~ '_default'] }}"
|
||||
images: "{{ images + [iname] }}"
|
||||
|
||||
- name: Create project directory
|
||||
file:
|
||||
path: '{{ item }}'
|
||||
state: directory
|
||||
loop:
|
||||
- '{{ project_src }}'
|
||||
- '{{ project_src }}/build'
|
||||
|
||||
- name: Template default project file
|
||||
copy:
|
||||
dest: '{{ project_src }}/docker-compose.yml'
|
||||
content: '{{ test_service }}'
|
||||
|
||||
- name: Template Dockerfile
|
||||
copy:
|
||||
dest: '{{ project_src }}/build/Dockerfile'
|
||||
content: |
|
||||
FROM {{ docker_test_image_alpine }}
|
||||
ENTRYPOINT ["/bin/sh", "-c", "sleep 10m"]
|
||||
|
||||
- name: Present (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_1_check
|
||||
|
||||
- name: Present
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
register: present_1
|
||||
|
||||
- name: Present (idempotent check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_2_check
|
||||
|
||||
- name: Present (idempotent)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
register: present_2
|
||||
|
||||
- name: Present (idempotent check, build=always, ignore_build_events=false)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
build: always
|
||||
ignore_build_events: false
|
||||
check_mode: true
|
||||
register: present_3_check
|
||||
|
||||
- name: Present (idempotent, build=always, ignore_build_events=false)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
build: always
|
||||
ignore_build_events: false
|
||||
register: present_3
|
||||
|
||||
- name: Present (idempotent check, build=always, ignore_build_events=true)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
build: always
|
||||
ignore_build_events: true
|
||||
check_mode: true
|
||||
register: present_4_check
|
||||
|
||||
- name: Present (idempotent, build=always, ignore_build_events=true)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
build: always
|
||||
ignore_build_events: true
|
||||
register: present_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- present_1_check is changed
|
||||
- present_1_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_1 is changed
|
||||
- present_1.containers | length == 1
|
||||
- present_1.containers[0].Name == (pname ~ '-' ~ cname ~ '-1')
|
||||
- present_1.images | length == 1
|
||||
- present_1.images[0].ContainerName == (pname ~ '-' ~ cname ~ '-1')
|
||||
- present_1.images[0].Repository == iname
|
||||
- present_1.images[0].Tag == "latest"
|
||||
- present_1.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2_check is not changed
|
||||
- present_2_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2 is not changed
|
||||
- present_2.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_3_check is changed
|
||||
- present_3_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- ((present_3 is changed) if docker_compose_version is version('2.31.0', '>=') and docker_compose_version is version('2.32.2', '<') else (present_3 is not changed))
|
||||
- present_3.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_4_check is changed
|
||||
- present_4_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_4 is not changed
|
||||
- present_4.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
|
||||
always:
|
||||
- name: Cleanup
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: absent
|
@ -0,0 +1,70 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- vars:
|
||||
pname: "{{ name_prefix }}-exit"
|
||||
cname: "{{ name_prefix }}-container"
|
||||
project_src: "{{ remote_tmp_dir }}/{{ pname }}"
|
||||
test_service: |
|
||||
services:
|
||||
{{ cname }}:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "exit 0"'
|
||||
stop_grace_period: 1s
|
||||
|
||||
block:
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [pname ~ '-' ~ cname ~ '-1'] }}"
|
||||
dnetworks: "{{ dnetworks + [pname ~ '_default'] }}"
|
||||
|
||||
- name: Create project directory
|
||||
file:
|
||||
path: '{{ project_src }}'
|
||||
state: directory
|
||||
|
||||
- name: Template default project file
|
||||
copy:
|
||||
dest: '{{ project_src }}/docker-compose.yml'
|
||||
content: '{{ test_service }}'
|
||||
|
||||
- name: Present (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
wait: true
|
||||
check_mode: true
|
||||
register: present_1_check
|
||||
|
||||
- name: Present
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
wait: true
|
||||
register: present_1
|
||||
ignore_errors: true
|
||||
|
||||
- name: Cleanup
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: absent
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- present_1_check is changed
|
||||
- present_1_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_1 is failed
|
||||
- present_1.containers | length == 1
|
||||
- present_1.containers[0].Name == (pname ~ '-' ~ cname ~ '-1')
|
||||
- present_1.containers[0].Image == docker_test_image_alpine
|
||||
- present_1.containers[0].State == 'exited'
|
||||
- present_1.containers[0].ExitCode == 0
|
||||
- present_1.images | length == 1
|
||||
- present_1.images[0].ContainerName == (pname ~ '-' ~ cname ~ '-1')
|
||||
- present_1.images[0].Repository == (docker_test_image_alpine | split(':') | first)
|
||||
- present_1.images[0].Tag == (docker_test_image_alpine | split(':') | last)
|
||||
- present_1.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- >-
|
||||
("container " ~ pname ~ '-' ~ cname ~ "-1 exited (0)") in present_1.msg
|
@ -0,0 +1,288 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- vars:
|
||||
pname: "{{ name_prefix }}-definition"
|
||||
cname: "{{ name_prefix }}-container"
|
||||
test_service: |
|
||||
services:
|
||||
{{ cname }}:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
stop_grace_period: 1s
|
||||
test_service_mod: |
|
||||
services:
|
||||
{{ cname }}:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 15m"'
|
||||
stop_grace_period: 1s
|
||||
|
||||
block:
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [pname ~ '-' ~ cname ~ '-1'] }}"
|
||||
dnetworks: "{{ dnetworks + [pname ~ '_default'] }}"
|
||||
|
||||
####################################################################
|
||||
## Present #########################################################
|
||||
####################################################################
|
||||
|
||||
- name: Present (check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_1_check
|
||||
|
||||
- name: Present
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: present
|
||||
register: present_1
|
||||
|
||||
- name: Present (idempotent check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_2_check
|
||||
|
||||
- name: Present (idempotent)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: present
|
||||
register: present_2
|
||||
|
||||
- name: Present (changed check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service_mod | from_yaml }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_3_check
|
||||
|
||||
- name: Present (changed)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service_mod | from_yaml }}'
|
||||
state: present
|
||||
register: present_3
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- present_1_check is changed
|
||||
- present_1_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_1 is changed
|
||||
- present_1.containers | length == 1
|
||||
- present_1.containers[0].Name == (pname ~ '-' ~ cname ~ '-1')
|
||||
- present_1.containers[0].Image == docker_test_image_alpine
|
||||
- present_1.images | length == 1
|
||||
- present_1.images[0].ContainerName == (pname ~ '-' ~ cname ~ '-1')
|
||||
- present_1.images[0].Repository == (docker_test_image_alpine | split(':') | first)
|
||||
- present_1.images[0].Tag == (docker_test_image_alpine | split(':') | last)
|
||||
- present_1.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2_check is not changed
|
||||
- present_2_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2 is not changed
|
||||
- present_2.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_3_check is changed
|
||||
- present_3_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_3 is changed
|
||||
- present_3.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
|
||||
####################################################################
|
||||
## Absent ##########################################################
|
||||
####################################################################
|
||||
|
||||
- name: Absent (check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service_mod | from_yaml }}'
|
||||
state: absent
|
||||
check_mode: true
|
||||
register: absent_1_check
|
||||
|
||||
- name: Absent
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service_mod | from_yaml }}'
|
||||
state: absent
|
||||
register: absent_1
|
||||
|
||||
- name: Absent (idempotent check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service_mod | from_yaml }}'
|
||||
state: absent
|
||||
check_mode: true
|
||||
register: absent_2_check
|
||||
|
||||
- name: Absent (idempotent)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service_mod | from_yaml }}'
|
||||
state: absent
|
||||
register: absent_2
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- absent_1_check is changed
|
||||
- absent_1_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- absent_1 is changed
|
||||
- absent_1.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- absent_2_check is not changed
|
||||
- absent_2_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- absent_2 is not changed
|
||||
- absent_2.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
|
||||
####################################################################
|
||||
## Stopping and starting ###########################################
|
||||
####################################################################
|
||||
|
||||
- name: Present stopped (check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: stopped
|
||||
check_mode: true
|
||||
register: present_1_check
|
||||
|
||||
- name: Present stopped
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: stopped
|
||||
register: present_1
|
||||
|
||||
- name: Present stopped (idempotent check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: stopped
|
||||
check_mode: true
|
||||
register: present_2_check
|
||||
|
||||
- name: Present stopped (idempotent)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: stopped
|
||||
register: present_2
|
||||
|
||||
- name: Started (check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_3_check
|
||||
|
||||
- name: Started
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: present
|
||||
register: present_3
|
||||
|
||||
- name: Started (idempotent check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_4_check
|
||||
|
||||
- name: Started (idempotent)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: present
|
||||
register: present_4
|
||||
|
||||
- name: Restarted (check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: restarted
|
||||
check_mode: true
|
||||
register: present_5_check
|
||||
|
||||
- name: Restarted
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: restarted
|
||||
register: present_5
|
||||
|
||||
- name: Stopped (check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: stopped
|
||||
check_mode: true
|
||||
register: present_6_check
|
||||
|
||||
- name: Stopped
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: stopped
|
||||
register: present_6
|
||||
|
||||
- name: Restarted (check)
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: restarted
|
||||
check_mode: true
|
||||
register: present_7_check
|
||||
|
||||
- name: Restarted
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: restarted
|
||||
register: present_7
|
||||
|
||||
- name: Cleanup
|
||||
docker_compose_v2:
|
||||
project_name: '{{ pname }}'
|
||||
definition: '{{ test_service | from_yaml }}'
|
||||
state: absent
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- present_1_check is changed
|
||||
- present_1_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_1 is changed
|
||||
- present_1.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2_check is not changed
|
||||
- present_2_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2 is not changed
|
||||
- present_2.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_3_check is changed
|
||||
- present_3_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_3 is changed
|
||||
- present_3.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_4_check is not changed
|
||||
- present_4_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_4 is not changed
|
||||
- present_4.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_5_check is changed
|
||||
- present_5_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_5 is changed
|
||||
- present_5.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_6_check is changed
|
||||
- present_6_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_6 is changed
|
||||
- present_6.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_7_check is changed
|
||||
- present_7_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_7 is changed
|
||||
- present_7.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
@ -0,0 +1,223 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- vars:
|
||||
pname: "{{ name_prefix }}-pull"
|
||||
cname: "{{ name_prefix }}-cont"
|
||||
non_existing_image: does-not-exist:latest
|
||||
project_src: "{{ remote_tmp_dir }}/{{ pname }}"
|
||||
test_service_non_existing: |
|
||||
services:
|
||||
{{ cname }}:
|
||||
image: {{ non_existing_image }}
|
||||
test_service_simple: |
|
||||
services:
|
||||
{{ cname }}:
|
||||
image: {{ docker_test_image_simple_1 }}
|
||||
command: 10m
|
||||
stop_grace_period: 1s
|
||||
|
||||
block:
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [pname ~ '-' ~ cname ~ '-1'] }}"
|
||||
dnetworks: "{{ dnetworks + [pname ~ '_default'] }}"
|
||||
|
||||
- name: Create project directory
|
||||
file:
|
||||
path: '{{ project_src }}'
|
||||
state: directory
|
||||
|
||||
- name: Make sure images are not around
|
||||
docker_image_remove:
|
||||
name: '{{ item }}'
|
||||
loop:
|
||||
- '{{ non_existing_image }}'
|
||||
- '{{ docker_test_image_simple_1 }}'
|
||||
|
||||
####################################################################
|
||||
## Missing image ###################################################
|
||||
####################################################################
|
||||
|
||||
- name: Template project file with non-existing image
|
||||
copy:
|
||||
dest: '{{ project_src }}/docker-compose.yml'
|
||||
content: '{{ test_service_non_existing }}'
|
||||
|
||||
- name: Present with pull=never (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: never
|
||||
check_mode: true
|
||||
register: present_1_check
|
||||
ignore_errors: true
|
||||
|
||||
- name: Present with pull=never
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: never
|
||||
register: present_1
|
||||
ignore_errors: true
|
||||
|
||||
- name: Present without explicit pull (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_2_check
|
||||
ignore_errors: true
|
||||
|
||||
- name: Present without explicit pull
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
register: present_2
|
||||
ignore_errors: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- present_1_check is failed or present_1_check is changed
|
||||
- present_1_check is changed or present_1_check.msg.startswith('General error:')
|
||||
- present_1_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_1 is failed
|
||||
- present_1.msg.startswith('General error:')
|
||||
- present_1.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2_check is failed
|
||||
- present_2_check.msg.startswith('Error when processing ' ~ cname ~ ':')
|
||||
- present_2_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2 is failed
|
||||
- present_2.msg.startswith('Error when processing ' ~ cname ~ ':')
|
||||
- present_2.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
|
||||
####################################################################
|
||||
## Regular image ###################################################
|
||||
####################################################################
|
||||
|
||||
- name: Template project file with simple image
|
||||
copy:
|
||||
dest: '{{ project_src }}/docker-compose.yml'
|
||||
content: '{{ test_service_simple }}'
|
||||
|
||||
- name: Present with pull=missing (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: missing
|
||||
check_mode: true
|
||||
register: present_1_check
|
||||
|
||||
- name: Present with pull=missing
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: missing
|
||||
register: present_1
|
||||
|
||||
- name: Present with pull=missing (idempotent, check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: missing
|
||||
check_mode: true
|
||||
register: present_2_check
|
||||
|
||||
- name: Present with pull=missing (idempotent)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: missing
|
||||
register: present_2
|
||||
|
||||
- name: Present with pull=always (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: always
|
||||
check_mode: true
|
||||
register: present_3_check
|
||||
|
||||
- name: Present with pull=always
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: always
|
||||
register: present_3
|
||||
|
||||
- name: Stopping service
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: absent
|
||||
|
||||
- name: Present with pull=never (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: missing
|
||||
check_mode: true
|
||||
register: present_4_check
|
||||
|
||||
- name: Present with pull=never
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: missing
|
||||
register: present_4
|
||||
|
||||
- name: Present with pull=never (idempotent, check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: missing
|
||||
check_mode: true
|
||||
register: present_5_check
|
||||
|
||||
- name: Present with pull=never (idempotent)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
pull: missing
|
||||
register: present_5
|
||||
|
||||
- name: Cleanup
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: absent
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- present_1_check is changed
|
||||
- (present_1_check.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- (present_1_check.actions | selectattr('status', 'eq', 'Creating') | first) is truthy
|
||||
- present_1_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_1 is changed
|
||||
- (present_1.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- (present_1.actions | selectattr('status', 'eq', 'Creating') | first) is truthy
|
||||
- present_1.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2_check is not changed
|
||||
- present_2_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2 is not changed
|
||||
- present_2.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_3_check is changed
|
||||
- (present_3_check.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- present_3_check.actions | selectattr('status', 'eq', 'Creating') | length == 0
|
||||
- present_3_check.actions | selectattr('status', 'eq', 'Recreating') | length == 0
|
||||
- present_3_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_3 is not changed
|
||||
- (present_3.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- present_3.actions | selectattr('status', 'eq', 'Creating') | length == 0
|
||||
- present_3.actions | selectattr('status', 'eq', 'Recreating') | length == 0
|
||||
- present_3.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_4_check is changed
|
||||
- present_4_check.actions | selectattr('status', 'eq', 'Pulling') | length == 0
|
||||
- present_4_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_4 is changed
|
||||
- present_4.actions | selectattr('status', 'eq', 'Pulling') | length == 0
|
||||
- present_4.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_5_check is not changed
|
||||
- present_5_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_5 is not changed
|
||||
- present_5.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
@ -0,0 +1,291 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- vars:
|
||||
pname: "{{ name_prefix }}-start-stop"
|
||||
cname: "{{ name_prefix }}-container"
|
||||
project_src: "{{ remote_tmp_dir }}/{{ pname }}"
|
||||
test_service: |
|
||||
services:
|
||||
{{ cname }}:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
stop_grace_period: 1s
|
||||
test_service_mod: |
|
||||
services:
|
||||
{{ cname }}:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 15m"'
|
||||
stop_grace_period: 1s
|
||||
|
||||
block:
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [pname ~ '-' ~ cname ~ '-1'] }}"
|
||||
dnetworks: "{{ dnetworks + [pname ~ '_default'] }}"
|
||||
|
||||
- name: Create project directory
|
||||
file:
|
||||
path: '{{ project_src }}'
|
||||
state: directory
|
||||
|
||||
####################################################################
|
||||
## Present #########################################################
|
||||
####################################################################
|
||||
|
||||
- name: Template default project file
|
||||
copy:
|
||||
dest: '{{ project_src }}/docker-compose.yml'
|
||||
content: '{{ test_service }}'
|
||||
|
||||
- name: Present (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_1_check
|
||||
|
||||
- name: Present
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
register: present_1
|
||||
|
||||
- name: Present (idempotent check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_2_check
|
||||
|
||||
- name: Present (idempotent)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
register: present_2
|
||||
|
||||
- name: Template modified project file
|
||||
copy:
|
||||
dest: '{{ project_src }}/docker-compose.yml'
|
||||
content: '{{ test_service_mod }}'
|
||||
|
||||
- name: Present (changed check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_3_check
|
||||
|
||||
- name: Present (changed)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
register: present_3
|
||||
|
||||
- name: Present with --yes
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
assume_yes: true
|
||||
when: docker_compose_version is version('2.32.0', '>=')
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- present_1_check is changed
|
||||
- present_1_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_1 is changed
|
||||
- present_1.containers | length == 1
|
||||
- present_1.containers[0].Name == (pname ~ '-' ~ cname ~ '-1')
|
||||
- present_1.containers[0].Image == docker_test_image_alpine
|
||||
- present_1.images | length == 1
|
||||
- present_1.images[0].ContainerName == (pname ~ '-' ~ cname ~ '-1')
|
||||
- present_1.images[0].Repository == (docker_test_image_alpine | split(':') | first)
|
||||
- present_1.images[0].Tag == (docker_test_image_alpine | split(':') | last)
|
||||
- present_1.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2_check is not changed
|
||||
- present_2_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2 is not changed
|
||||
- present_2.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_3_check is changed
|
||||
- present_3_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_3 is changed
|
||||
- present_3.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
|
||||
####################################################################
|
||||
## Absent ##########################################################
|
||||
####################################################################
|
||||
|
||||
- name: Absent (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: absent
|
||||
check_mode: true
|
||||
register: absent_1_check
|
||||
|
||||
- name: Absent
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: absent
|
||||
register: absent_1
|
||||
|
||||
- name: Absent (idempotent check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: absent
|
||||
check_mode: true
|
||||
register: absent_2_check
|
||||
|
||||
- name: Absent (idempotent)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: absent
|
||||
register: absent_2
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- absent_1_check is changed
|
||||
- absent_1_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- absent_1 is changed
|
||||
- absent_1.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- absent_2_check is not changed
|
||||
- absent_2_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- absent_2 is not changed
|
||||
- absent_2.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
|
||||
####################################################################
|
||||
## Stopping and starting ###########################################
|
||||
####################################################################
|
||||
|
||||
- name: Template default project file
|
||||
copy:
|
||||
dest: '{{ project_src }}/docker-compose.yml'
|
||||
content: '{{ test_service }}'
|
||||
|
||||
- name: Present stopped (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: stopped
|
||||
check_mode: true
|
||||
register: present_1_check
|
||||
|
||||
- name: Present stopped
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: stopped
|
||||
register: present_1
|
||||
|
||||
- name: Present stopped (idempotent check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: stopped
|
||||
check_mode: true
|
||||
register: present_2_check
|
||||
|
||||
- name: Present stopped (idempotent)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: stopped
|
||||
register: present_2
|
||||
|
||||
- name: Started (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_3_check
|
||||
|
||||
- name: Started
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
register: present_3
|
||||
|
||||
- name: Started (idempotent check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_4_check
|
||||
|
||||
- name: Started (idempotent)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
register: present_4
|
||||
|
||||
- name: Restarted (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: restarted
|
||||
check_mode: true
|
||||
register: present_5_check
|
||||
|
||||
- name: Restarted
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: restarted
|
||||
register: present_5
|
||||
|
||||
- name: Stopped (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: stopped
|
||||
check_mode: true
|
||||
register: present_6_check
|
||||
|
||||
- name: Stopped
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: stopped
|
||||
register: present_6
|
||||
|
||||
- name: Restarted (check)
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: restarted
|
||||
check_mode: true
|
||||
register: present_7_check
|
||||
|
||||
- name: Restarted
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: restarted
|
||||
register: present_7
|
||||
|
||||
- name: Cleanup
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: absent
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- present_1_check is changed
|
||||
- present_1_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_1 is changed
|
||||
- present_1.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2_check is not changed
|
||||
- present_2_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_2 is not changed
|
||||
- present_2.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_3_check is changed
|
||||
- present_3_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_3 is changed
|
||||
- present_3.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_4_check is not changed
|
||||
- present_4_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_4 is not changed
|
||||
- present_4.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_5_check is changed
|
||||
- present_5_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_5 is changed
|
||||
- present_5.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_6_check is changed
|
||||
- present_6_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_6 is changed
|
||||
- present_6.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_7_check is changed
|
||||
- present_7_check.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
||||
- present_7 is changed
|
||||
- present_7.warnings | default([]) | select('regex', ' Please report this at ') | length == 0
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/4
|
||||
destructive
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker_cli_compose
|
||||
# The Python dependencies are needed for the other modules
|
||||
- setup_docker_python_deps
|
||||
- setup_remote_tmp_dir
|
@ -0,0 +1,49 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
# Create random name prefix (for services, ...)
|
||||
- name: Create random container name prefix
|
||||
set_fact:
|
||||
name_prefix: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
cnames: []
|
||||
dnetworks: []
|
||||
|
||||
- debug:
|
||||
msg: "Using name prefix {{ name_prefix }}"
|
||||
|
||||
# Run the tests
|
||||
- block:
|
||||
- name: Show docker compose --help output
|
||||
command: docker compose --help
|
||||
|
||||
- include_tasks: run-test.yml
|
||||
with_fileglob:
|
||||
- "tests/*.yml"
|
||||
loop_control:
|
||||
loop_var: test_name
|
||||
|
||||
always:
|
||||
- name: "Make sure all containers are removed"
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
with_items: "{{ cnames }}"
|
||||
diff: false
|
||||
|
||||
- name: "Make sure all networks are removed"
|
||||
docker_network:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force: true
|
||||
with_items: "{{ dnetworks }}"
|
||||
diff: false
|
||||
|
||||
when: docker_has_compose and docker_compose_version is version('2.18.0', '>=')
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: "Loading tasks from {{ test_name }}"
|
||||
include_tasks: "{{ test_name }}"
|
@ -0,0 +1,97 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- vars:
|
||||
pname: "{{ name_prefix }}-start-stop"
|
||||
cname: "{{ name_prefix }}-container"
|
||||
project_src: "{{ remote_tmp_dir }}/{{ pname }}"
|
||||
test_service: |
|
||||
services:
|
||||
{{ cname }}:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
stop_grace_period: 1s
|
||||
|
||||
block:
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [pname ~ '-' ~ cname ~ '-1'] }}"
|
||||
dnetworks: "{{ dnetworks + [pname ~ '_default'] }}"
|
||||
|
||||
- name: Create project directory
|
||||
file:
|
||||
path: '{{ project_src }}'
|
||||
state: directory
|
||||
|
||||
- name: Template default project file
|
||||
copy:
|
||||
dest: '{{ project_src }}/docker-compose.yml'
|
||||
content: '{{ test_service }}'
|
||||
|
||||
- block:
|
||||
- name: Start services
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
|
||||
- name: Run command with command
|
||||
docker_compose_v2_exec:
|
||||
project_src: '{{ project_src }}'
|
||||
service: '{{ cname }}'
|
||||
command: /bin/sh -c "ls /"
|
||||
register: result_1
|
||||
|
||||
- name: Run command with argv
|
||||
docker_compose_v2_exec:
|
||||
project_src: '{{ project_src }}'
|
||||
service: '{{ cname }}'
|
||||
argv:
|
||||
- /bin/sh
|
||||
- "-c"
|
||||
- whoami
|
||||
user: "1234"
|
||||
register: result_2
|
||||
failed_when: result_2.rc != 1
|
||||
|
||||
- name: Run detached command
|
||||
docker_compose_v2_exec:
|
||||
project_src: '{{ project_src }}'
|
||||
service: '{{ cname }}'
|
||||
command: /bin/sh -c "sleep 1"
|
||||
detach: true
|
||||
register: result_3
|
||||
|
||||
- name: Run command with input
|
||||
docker_compose_v2_exec:
|
||||
project_src: '{{ project_src }}'
|
||||
service: '{{ cname }}'
|
||||
command: /bin/sh -c "cat"
|
||||
stdin: This is a test
|
||||
register: result_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result_1.rc == 0
|
||||
- result_1.stderr == ""
|
||||
- >-
|
||||
"usr" in result_1.stdout_lines
|
||||
and
|
||||
"etc" in result_1.stdout_lines
|
||||
- result_2.rc == 1
|
||||
- >-
|
||||
"whoami: unknown uid 1234" in result_2.stderr
|
||||
- result_2.stdout == ""
|
||||
- result_3.rc is not defined
|
||||
- result_3.stdout is not defined
|
||||
- result_3.stderr is not defined
|
||||
- result_4.rc == 0
|
||||
- result_4.stdout == "This is a test"
|
||||
- result_4.stderr == ""
|
||||
|
||||
always:
|
||||
- name: Cleanup
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: absent
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/4
|
||||
destructive
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker_cli_compose
|
||||
# The Python dependencies are needed for the other modules
|
||||
- setup_docker_python_deps
|
||||
- setup_remote_tmp_dir
|
@ -0,0 +1,52 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
# Create random name prefix (for services, ...)
|
||||
- name: Create random container name prefix
|
||||
set_fact:
|
||||
name_prefix: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
cnames: []
|
||||
dnetworks: []
|
||||
|
||||
- debug:
|
||||
msg: "Using name prefix {{ name_prefix }}"
|
||||
|
||||
- name: Show images
|
||||
command: docker images --all --digests
|
||||
|
||||
# Run the tests
|
||||
- block:
|
||||
- name: Show docker compose --help output
|
||||
command: docker compose --help
|
||||
|
||||
- include_tasks: run-test.yml
|
||||
with_fileglob:
|
||||
- "tests/*.yml"
|
||||
loop_control:
|
||||
loop_var: test_name
|
||||
|
||||
always:
|
||||
- name: "Make sure all containers are removed"
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
with_items: "{{ cnames }}"
|
||||
diff: false
|
||||
|
||||
- name: "Make sure all networks are removed"
|
||||
docker_network:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force: true
|
||||
with_items: "{{ dnetworks }}"
|
||||
diff: false
|
||||
|
||||
when: docker_has_compose and docker_compose_version is version('2.18.0', '>=')
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: "Loading tasks from {{ test_name }}"
|
||||
include_tasks: "{{ test_name }}"
|
@ -0,0 +1,206 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- vars:
|
||||
pname: "{{ name_prefix }}-pull"
|
||||
cname: "{{ name_prefix }}-cont"
|
||||
non_existing_image: does-not-exist:latest
|
||||
project_src: "{{ remote_tmp_dir }}/{{ pname }}"
|
||||
test_service_non_existing: |
|
||||
version: '3'
|
||||
services:
|
||||
{{ cname }}:
|
||||
image: {{ non_existing_image }}
|
||||
test_service_simple: |
|
||||
version: '3'
|
||||
services:
|
||||
{{ cname }}:
|
||||
image: {{ docker_test_image_simple_1 }}
|
||||
command: 10m
|
||||
stop_grace_period: 1s
|
||||
|
||||
block:
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [pname ~ '-' ~ cname ~ '-1'] }}"
|
||||
dnetworks: "{{ dnetworks + [pname ~ '_default'] }}"
|
||||
|
||||
- name: Create project directory
|
||||
file:
|
||||
path: '{{ project_src }}'
|
||||
state: directory
|
||||
|
||||
- name: Make sure images are not around
|
||||
docker_image_remove:
|
||||
name: '{{ item }}'
|
||||
loop:
|
||||
- '{{ non_existing_image }}'
|
||||
- '{{ docker_test_image_simple_1 }}'
|
||||
|
||||
####################################################################
|
||||
## Missing image ###################################################
|
||||
####################################################################
|
||||
|
||||
- name: Template project file with non-existing image
|
||||
copy:
|
||||
dest: '{{ project_src }}/docker-compose.yml'
|
||||
content: '{{ test_service_non_existing }}'
|
||||
|
||||
- name: Pull (check)
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
check_mode: true
|
||||
register: pull_1_check
|
||||
ignore_errors: true
|
||||
|
||||
- name: Pull
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
register: pull_1
|
||||
ignore_errors: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- pull_1_check is failed or pull_1_check is changed
|
||||
- pull_1_check is changed or pull_1_check.msg.startswith('Error when processing ')
|
||||
- pull_1_check.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
- pull_1 is failed
|
||||
- pull_1.msg.startswith('Error when processing ')
|
||||
- pull_1.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
|
||||
####################################################################
|
||||
## Regular image ###################################################
|
||||
####################################################################
|
||||
|
||||
- name: Template project file with simple image
|
||||
copy:
|
||||
dest: '{{ project_src }}/docker-compose.yml'
|
||||
content: '{{ test_service_simple }}'
|
||||
|
||||
- when: docker_compose_version is version('2.22.0', '>=')
|
||||
block:
|
||||
- name: Pull with policy=missing (check)
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: missing
|
||||
check_mode: true
|
||||
register: pull_1_check
|
||||
|
||||
- name: Pull with policy=missing
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: missing
|
||||
register: pull_1
|
||||
|
||||
- name: Pull with policy=missing (idempotent, check)
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: missing
|
||||
check_mode: true
|
||||
register: pull_2_check
|
||||
|
||||
- name: Pull with policy=missing (idempotent)
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: missing
|
||||
register: pull_2
|
||||
|
||||
- name: Make sure image is not around
|
||||
docker_image_remove:
|
||||
name: '{{ docker_test_image_simple_1 }}'
|
||||
|
||||
- name: Pull with policy=always (check)
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: always
|
||||
check_mode: true
|
||||
register: pull_3_check
|
||||
|
||||
- name: Pull with policy=always
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: always
|
||||
register: pull_3
|
||||
|
||||
- name: Pull with policy=always (check, idempotent)
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: always
|
||||
check_mode: true
|
||||
register: pull_4_check
|
||||
|
||||
- name: Pull with policy=always (idempotent)
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: always
|
||||
register: pull_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- pull_1_check is changed
|
||||
- (pull_1_check.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- pull_1_check.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
- pull_1 is changed
|
||||
- (pull_1.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- pull_1.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
- pull_2_check is not changed
|
||||
- pull_2_check.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
- pull_2 is not changed
|
||||
- pull_2.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
- pull_3_check is changed
|
||||
- (pull_3_check.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- pull_3_check.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
- pull_3 is changed
|
||||
- (pull_3.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- pull_3.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
- pull_4_check is changed
|
||||
- (pull_4_check.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- pull_4_check.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
- pull_4 is not changed
|
||||
- (pull_4.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- pull_4.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
|
||||
- when: docker_compose_version is version('2.22.0', '<')
|
||||
block:
|
||||
- name: Pull with policy=always (check)
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: always
|
||||
check_mode: true
|
||||
register: pull_1_check
|
||||
|
||||
- name: Pull with policy=always
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: always
|
||||
register: pull_1
|
||||
|
||||
- name: Pull with policy=always (again, check)
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: always
|
||||
check_mode: true
|
||||
register: pull_2_check
|
||||
|
||||
- name: Pull with policy=always (again)
|
||||
docker_compose_v2_pull:
|
||||
project_src: '{{ project_src }}'
|
||||
policy: always
|
||||
register: pull_2
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- pull_1_check is changed
|
||||
- (pull_1_check.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- pull_1_check.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
- pull_1 is changed
|
||||
- (pull_1.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- pull_1.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
- pull_2_check is changed
|
||||
- (pull_2_check.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- pull_2_check.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
||||
- pull_2 is not changed
|
||||
- (pull_2.actions | selectattr('status', 'eq', 'Pulling') | first) is truthy
|
||||
- pull_2.warnings | default([]) | select('regex', 'Cannot parse event from ') | length == 0
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/4
|
||||
destructive
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker_cli_compose
|
||||
# The Python dependencies are needed for the other modules
|
||||
- setup_docker_python_deps
|
||||
- setup_remote_tmp_dir
|
@ -0,0 +1,49 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
# Create random name prefix (for services, ...)
|
||||
- name: Create random container name prefix
|
||||
set_fact:
|
||||
name_prefix: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
cnames: []
|
||||
dnetworks: []
|
||||
|
||||
- debug:
|
||||
msg: "Using name prefix {{ name_prefix }}"
|
||||
|
||||
# Run the tests
|
||||
- block:
|
||||
- name: Show docker compose --help output
|
||||
command: docker compose --help
|
||||
|
||||
- include_tasks: run-test.yml
|
||||
with_fileglob:
|
||||
- "tests/*.yml"
|
||||
loop_control:
|
||||
loop_var: test_name
|
||||
|
||||
always:
|
||||
- name: "Make sure all containers are removed"
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
with_items: "{{ cnames }}"
|
||||
diff: false
|
||||
|
||||
- name: "Make sure all networks are removed"
|
||||
docker_network:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force: true
|
||||
with_items: "{{ dnetworks }}"
|
||||
diff: false
|
||||
|
||||
when: docker_has_compose and docker_compose_version is version('2.18.0', '>=')
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: "Loading tasks from {{ test_name }}"
|
||||
include_tasks: "{{ test_name }}"
|
@ -0,0 +1,104 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- vars:
|
||||
pname: "{{ name_prefix }}-start-stop"
|
||||
cname: "{{ name_prefix }}-container"
|
||||
project_src: "{{ remote_tmp_dir }}/{{ pname }}"
|
||||
test_service: |
|
||||
services:
|
||||
{{ cname }}:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
stop_grace_period: 1s
|
||||
|
||||
block:
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [pname ~ '-' ~ cname ~ '-1'] }}"
|
||||
dnetworks: "{{ dnetworks + [pname ~ '_default'] }}"
|
||||
|
||||
- name: Create project directory
|
||||
file:
|
||||
path: '{{ project_src }}'
|
||||
state: directory
|
||||
|
||||
- name: Template default project file
|
||||
copy:
|
||||
dest: '{{ project_src }}/docker-compose.yml'
|
||||
content: '{{ test_service }}'
|
||||
|
||||
- block:
|
||||
- name: Start services
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: present
|
||||
|
||||
- name: Run command with command
|
||||
docker_compose_v2_run:
|
||||
project_src: '{{ project_src }}'
|
||||
service: '{{ cname }}'
|
||||
command: /bin/sh -c "ls /"
|
||||
cleanup: true
|
||||
register: result_1
|
||||
|
||||
- name: Run command with argv
|
||||
docker_compose_v2_run:
|
||||
project_src: '{{ project_src }}'
|
||||
service: '{{ cname }}'
|
||||
argv:
|
||||
- /bin/sh
|
||||
- "-c"
|
||||
- whoami
|
||||
user: "1234"
|
||||
cleanup: true
|
||||
register: result_2
|
||||
failed_when: result_2.rc != 1
|
||||
|
||||
- name: Run detached command
|
||||
docker_compose_v2_run:
|
||||
project_src: '{{ project_src }}'
|
||||
service: '{{ cname }}'
|
||||
command: /bin/sh -c "sleep 1"
|
||||
detach: true
|
||||
cleanup: true
|
||||
register: result_3
|
||||
|
||||
- name: Run command with input
|
||||
docker_compose_v2_run:
|
||||
project_src: '{{ project_src }}'
|
||||
service: '{{ cname }}'
|
||||
command: /bin/sh -c "cat"
|
||||
stdin: This is a test
|
||||
register: result_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result_1.rc == 0
|
||||
- result_1.stderr == ""
|
||||
- >-
|
||||
"usr" in result_1.stdout_lines
|
||||
and
|
||||
"etc" in result_1.stdout_lines
|
||||
- result_1.container_id is not defined
|
||||
- result_2.rc == 1
|
||||
- >-
|
||||
"whoami: unknown uid 1234" in result_2.stderr
|
||||
- result_2.stdout == ""
|
||||
- result_2.container_id is not defined
|
||||
- result_3.rc is not defined
|
||||
- result_3.stdout is not defined
|
||||
- result_3.stderr is not defined
|
||||
- result_3.container_id is string
|
||||
- result_4.rc == 0
|
||||
- result_4.stdout == "This is a test"
|
||||
- result_4.stderr is string
|
||||
- result_4.container_id is not defined
|
||||
|
||||
always:
|
||||
- name: Cleanup
|
||||
docker_compose_v2:
|
||||
project_src: '{{ project_src }}'
|
||||
state: absent
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/3
|
||||
destructive
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker
|
||||
- setup_docker_sdk_for_python
|
||||
- setup_remote_tmp_dir
|
@ -0,0 +1,15 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- include_tasks: test_docker_config.yml
|
||||
when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.30', '>=')
|
||||
|
||||
- fail: msg="Too old docker / docker-py version to run docker_config tests!"
|
||||
when: not(docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.30', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)
|
@ -0,0 +1,334 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- block:
|
||||
- shell: "docker info --format '{% raw %}{{json .}}{% endraw %}' | python -m json.tool"
|
||||
|
||||
- name: Make sure we're not already using Docker swarm
|
||||
docker_swarm:
|
||||
state: absent
|
||||
force: true
|
||||
|
||||
- shell: "docker info --format '{% raw %}{{json .}}{% endraw %}' | python -m json.tool"
|
||||
|
||||
- name: Create a Swarm cluster
|
||||
docker_swarm:
|
||||
name: default
|
||||
state: present
|
||||
advertise_addr: "{{ ansible_default_ipv4.address | default('127.0.0.1') }}"
|
||||
|
||||
- name: Parameter name should be required
|
||||
docker_config:
|
||||
state: present
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Assert failure when called with no name
|
||||
assert:
|
||||
that:
|
||||
- 'output is failed'
|
||||
- 'output.msg == "missing required arguments: name"'
|
||||
|
||||
- name: Test parameters
|
||||
docker_config:
|
||||
name: foo
|
||||
state: present
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Assert failure when called with no data
|
||||
assert:
|
||||
that:
|
||||
- 'output is failed'
|
||||
- 'output.msg == "state is present but any of the following are missing: data, data_src"'
|
||||
|
||||
- name: Create config
|
||||
docker_config:
|
||||
name: db_password
|
||||
data: opensesame!
|
||||
state: present
|
||||
register: output
|
||||
|
||||
- name: Create variable config_id
|
||||
set_fact:
|
||||
config_id: "{{ output.config_id }}"
|
||||
|
||||
- name: Inspect config
|
||||
command: "docker config inspect {{ config_id }}"
|
||||
register: inspect
|
||||
ignore_errors: true
|
||||
|
||||
- debug:
|
||||
var: inspect
|
||||
|
||||
- name: Assert config creation succeeded
|
||||
assert:
|
||||
that:
|
||||
- "'db_password' in inspect.stdout"
|
||||
- "'ansible_key' in inspect.stdout"
|
||||
when: inspect is not failed
|
||||
- assert:
|
||||
that:
|
||||
- "'is too new. Maximum supported API version is' in inspect.stderr"
|
||||
when: inspect is failed
|
||||
|
||||
- name: Create config again
|
||||
docker_config:
|
||||
name: db_password
|
||||
data: opensesame!
|
||||
state: present
|
||||
register: output
|
||||
|
||||
- name: Assert create config is idempotent
|
||||
assert:
|
||||
that:
|
||||
- output is not changed
|
||||
|
||||
- name: Write config into file
|
||||
copy:
|
||||
dest: "{{ remote_tmp_dir }}/data"
|
||||
content: |-
|
||||
opensesame!
|
||||
|
||||
- name: Create config again (from file)
|
||||
docker_config:
|
||||
name: db_password
|
||||
data_src: "{{ remote_tmp_dir }}/data"
|
||||
state: present
|
||||
register: output
|
||||
|
||||
- name: Assert create config is idempotent
|
||||
assert:
|
||||
that:
|
||||
- output is not changed
|
||||
|
||||
- name: Create config again (base64)
|
||||
docker_config:
|
||||
name: db_password
|
||||
data: b3BlbnNlc2FtZSE=
|
||||
data_is_b64: true
|
||||
state: present
|
||||
register: output
|
||||
|
||||
- name: Assert create config (base64) is idempotent
|
||||
assert:
|
||||
that:
|
||||
- output is not changed
|
||||
|
||||
- name: Update config
|
||||
docker_config:
|
||||
name: db_password
|
||||
data: newpassword!
|
||||
state: present
|
||||
register: output
|
||||
|
||||
- name: Assert config was updated
|
||||
assert:
|
||||
that:
|
||||
- output is changed
|
||||
- output.config_id != config_id
|
||||
|
||||
- name: Remove config
|
||||
docker_config:
|
||||
name: db_password
|
||||
state: absent
|
||||
|
||||
- name: Check that config is removed
|
||||
command: "docker config inspect {{ config_id }}"
|
||||
register: output
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert config was removed
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
|
||||
- name: Remove config
|
||||
docker_config:
|
||||
name: db_password
|
||||
state: absent
|
||||
register: output
|
||||
|
||||
- name: Assert remove config is idempotent
|
||||
assert:
|
||||
that:
|
||||
- output is not changed
|
||||
|
||||
# Rolling update
|
||||
|
||||
- name: Create rolling config
|
||||
docker_config:
|
||||
name: rolling_password
|
||||
data: opensesame!
|
||||
rolling_versions: true
|
||||
state: present
|
||||
register: original_output
|
||||
|
||||
- name: Create variable config_id
|
||||
set_fact:
|
||||
config_id: "{{ original_output.config_id }}"
|
||||
|
||||
- name: Inspect config
|
||||
command: "docker config inspect {{ config_id }}"
|
||||
register: inspect
|
||||
ignore_errors: true
|
||||
|
||||
- debug:
|
||||
var: inspect
|
||||
|
||||
- name: Assert config creation succeeded
|
||||
assert:
|
||||
that:
|
||||
- "'rolling_password' in inspect.stdout"
|
||||
- "'ansible_key' in inspect.stdout"
|
||||
- "'ansible_version' in inspect.stdout"
|
||||
- original_output.config_name == 'rolling_password_v1'
|
||||
when: inspect is not failed
|
||||
- assert:
|
||||
that:
|
||||
- "'is too new. Maximum supported API version is' in inspect.stderr"
|
||||
when: inspect is failed
|
||||
|
||||
- name: Create config again
|
||||
docker_config:
|
||||
name: rolling_password
|
||||
data: newpassword!
|
||||
rolling_versions: true
|
||||
state: present
|
||||
register: new_output
|
||||
|
||||
- name: Assert that new version is created
|
||||
assert:
|
||||
that:
|
||||
- new_output is changed
|
||||
- new_output.config_id != original_output.config_id
|
||||
- new_output.config_name != original_output.config_name
|
||||
- new_output.config_name == 'rolling_password_v2'
|
||||
|
||||
- name: Remove rolling configs
|
||||
docker_config:
|
||||
name: rolling_password
|
||||
rolling_versions: true
|
||||
state: absent
|
||||
|
||||
- name: Check that config is removed
|
||||
command: "docker config inspect {{ original_output.config_id }}"
|
||||
register: output
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert config was removed
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
|
||||
- name: Check that config is removed
|
||||
command: "docker config inspect {{ new_output.config_id }}"
|
||||
register: output
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert config was removed
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
|
||||
# template_driver tests
|
||||
|
||||
- when: docker_py_version is version('5.0.3', '>=') and docker_api_version is version('1.37', '>=')
|
||||
block:
|
||||
|
||||
- name: Create regular config
|
||||
docker_config:
|
||||
name: db_password
|
||||
data: opensesame!
|
||||
state: present
|
||||
|
||||
- name: Update config with template_driver
|
||||
docker_config:
|
||||
name: db_password
|
||||
data: opensesame!
|
||||
template_driver: golang
|
||||
state: present
|
||||
register: output
|
||||
|
||||
- name: Assert config was updated
|
||||
assert:
|
||||
that:
|
||||
- output is changed
|
||||
|
||||
- name: Invalid template_driver
|
||||
docker_config:
|
||||
name: db_password
|
||||
data: opensesame!
|
||||
template_driver: "not a template driver"
|
||||
state: present
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Assert failure when called with invalid template_driver
|
||||
assert:
|
||||
that:
|
||||
- 'output is failed'
|
||||
- 'output.msg == "value of template_driver must be one of: golang, got: not a template driver"'
|
||||
|
||||
- name: Create config again
|
||||
docker_config:
|
||||
name: db_password
|
||||
data: opensesame!
|
||||
template_driver: golang
|
||||
state: present
|
||||
register: output
|
||||
|
||||
- name: Assert create config is idempotent
|
||||
assert:
|
||||
that:
|
||||
- output is not changed
|
||||
|
||||
# data is the docker swarm's name
|
||||
- name: Update config with template data
|
||||
docker_config:
|
||||
name: db_password
|
||||
data: "{{ '{{' }} .Service.Name {{ '}}' }}"
|
||||
template_driver: golang
|
||||
state: present
|
||||
register: output
|
||||
|
||||
- name: Inspect config
|
||||
command: "docker config inspect {{ output.config_id }}"
|
||||
register: inspect
|
||||
|
||||
- name: Show inspection result
|
||||
debug:
|
||||
var: inspect
|
||||
|
||||
- name: Assert config creation succeeded
|
||||
assert:
|
||||
that:
|
||||
- "'db_password' in inspect.stdout"
|
||||
- "'ansible_key' in inspect.stdout"
|
||||
# According to the API docs, 'Data' is "Base64-url-safe-encoded (RFC 4648) config data."
|
||||
- "'\"Data\": \"e3sgLlNlcnZpY2UuTmFtZSB9fQ==\"' in inspect.stdout"
|
||||
- "'Templating' in inspect.stdout"
|
||||
- "'\"Name\": \"golang\"' in inspect.stdout"
|
||||
|
||||
- name: Remove config
|
||||
docker_config:
|
||||
name: db_password
|
||||
state: absent
|
||||
|
||||
- name: Check that config is removed
|
||||
command: "docker config inspect {{ output.config_id }}"
|
||||
register: output
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert config was removed
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
|
||||
always:
|
||||
- name: Remove a Swarm cluster
|
||||
docker_swarm:
|
||||
state: absent
|
||||
force: true
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/5
|
||||
destructive
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
TEST3=val3
|
||||
TEST4=val4
|
@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2020, Felix Fontein <felix@fontein.de>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
def _normalize_ipaddr(ipaddr):
|
||||
# Import when needed, to allow installation of that module in the test setup
|
||||
import ipaddress
|
||||
return ipaddress.ip_address(ipaddr).compressed
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
""" IP address and network manipulation filters """
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
'normalize_ipaddr': _normalize_ipaddr,
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker
|
||||
- setup_docker_python_deps
|
@ -0,0 +1,70 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- name: Gather facts on controller
|
||||
setup:
|
||||
gather_subset: '!all'
|
||||
delegate_to: localhost
|
||||
delegate_facts: true
|
||||
run_once: true
|
||||
|
||||
- name: Make sure ipaddress is available on controller
|
||||
pip:
|
||||
name: ipaddress
|
||||
delegate_to: localhost
|
||||
when: hostvars['localhost'].ansible_facts.python.version.major < 3
|
||||
|
||||
# Create random name prefix (for containers, networks, ...)
|
||||
- name: Create random container name prefix
|
||||
set_fact:
|
||||
cname_prefix: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
cnames: []
|
||||
inames: []
|
||||
dnetworks: []
|
||||
|
||||
- debug:
|
||||
msg: "Using container name prefix {{ cname_prefix }}"
|
||||
|
||||
- name: Retrieve docker host info
|
||||
docker_host_info:
|
||||
register: docker_host_info
|
||||
|
||||
# Run the tests
|
||||
- block:
|
||||
- include_tasks: run-test.yml
|
||||
with_fileglob:
|
||||
- "tests/*.yml"
|
||||
loop_control:
|
||||
loop_var: test_name
|
||||
|
||||
always:
|
||||
- name: "Make sure all containers are removed"
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
with_items: "{{ cnames }}"
|
||||
diff: false
|
||||
- name: "Make sure all images are removed"
|
||||
docker_image_remove:
|
||||
name: "{{ item }}"
|
||||
with_items: "{{ inames }}"
|
||||
- name: "Make sure all networks are removed"
|
||||
docker_network:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force: true
|
||||
with_items: "{{ dnetworks }}"
|
||||
diff: false
|
||||
|
||||
when: docker_api_version is version('1.25', '>=')
|
||||
|
||||
- fail: msg="Too old docker / docker-py version to run all docker_container tests!"
|
||||
when: not(docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: "Loading tasks from {{ test_name }}"
|
||||
include_tasks: "{{ test_name }}"
|
@ -0,0 +1,466 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cname: "{{ cname_prefix ~ '-comparisons' }}"
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [cname] }}"
|
||||
|
||||
####################################################################
|
||||
## value ###########################################################
|
||||
####################################################################
|
||||
|
||||
- name: value
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
hostname: example.com
|
||||
register: value_1
|
||||
|
||||
- name: value (change, ignore)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
hostname: example.org
|
||||
force_kill: true
|
||||
comparisons:
|
||||
hostname: ignore
|
||||
register: value_2
|
||||
|
||||
- name: value (change, strict)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
hostname: example.org
|
||||
force_kill: true
|
||||
comparisons:
|
||||
hostname: strict
|
||||
register: value_3
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- value_1 is changed
|
||||
- value_2 is not changed
|
||||
- value_3 is changed
|
||||
|
||||
####################################################################
|
||||
## list ############################################################
|
||||
####################################################################
|
||||
|
||||
- name: list
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
dns_servers:
|
||||
- 1.1.1.1
|
||||
- 8.8.8.8
|
||||
register: list_1
|
||||
|
||||
- name: list (change, ignore)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
dns_servers:
|
||||
- 9.9.9.9
|
||||
force_kill: true
|
||||
comparisons:
|
||||
dns_servers: ignore
|
||||
register: list_2
|
||||
|
||||
- name: list (change, strict)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
dns_servers:
|
||||
- 9.9.9.9
|
||||
force_kill: true
|
||||
comparisons:
|
||||
dns_servers: strict
|
||||
register: list_3
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- list_1 is changed
|
||||
- list_2 is not changed
|
||||
- list_3 is changed
|
||||
|
||||
####################################################################
|
||||
## set #############################################################
|
||||
####################################################################
|
||||
|
||||
- name: set
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
groups:
|
||||
- "1010"
|
||||
- "1011"
|
||||
register: set_1
|
||||
|
||||
- name: set (change, ignore)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
groups:
|
||||
- "1010"
|
||||
- "1011"
|
||||
- "1012"
|
||||
force_kill: true
|
||||
comparisons:
|
||||
groups: ignore
|
||||
register: set_2
|
||||
|
||||
- name: set (change, allow_more_present)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
groups:
|
||||
- "1010"
|
||||
- "1011"
|
||||
- "1012"
|
||||
force_kill: true
|
||||
comparisons:
|
||||
groups: allow_more_present
|
||||
register: set_3
|
||||
|
||||
- name: set (change, allow_more_present)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
groups:
|
||||
- "1010"
|
||||
- "1012"
|
||||
force_kill: true
|
||||
comparisons:
|
||||
groups: allow_more_present
|
||||
register: set_4
|
||||
|
||||
- name: set (change, strict)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
groups:
|
||||
- "1010"
|
||||
- "1012"
|
||||
force_kill: true
|
||||
comparisons:
|
||||
groups: strict
|
||||
register: set_5
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- set_1 is changed
|
||||
- set_2 is not changed
|
||||
- set_3 is changed
|
||||
- set_4 is not changed
|
||||
- set_5 is changed
|
||||
|
||||
####################################################################
|
||||
## set(dict) #######################################################
|
||||
####################################################################
|
||||
|
||||
- name: set(dict)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
devices:
|
||||
- "/dev/random:/dev/virt-random:rwm"
|
||||
- "/dev/urandom:/dev/virt-urandom:rwm"
|
||||
register: set_dict_1
|
||||
|
||||
- name: set(dict) (change, ignore)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
devices:
|
||||
- "/dev/random:/dev/virt-random:rwm"
|
||||
- "/dev/urandom:/dev/virt-urandom:rwm"
|
||||
- "/dev/null:/dev/virt-null:rwm"
|
||||
force_kill: true
|
||||
comparisons:
|
||||
devices: ignore
|
||||
register: set_dict_2
|
||||
|
||||
- name: set(dict) (change, allow_more_present)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
devices:
|
||||
- "/dev/random:/dev/virt-random:rwm"
|
||||
- "/dev/urandom:/dev/virt-urandom:rwm"
|
||||
- "/dev/null:/dev/virt-null:rwm"
|
||||
force_kill: true
|
||||
comparisons:
|
||||
devices: allow_more_present
|
||||
register: set_dict_3
|
||||
|
||||
- name: set(dict) (change, allow_more_present)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
devices:
|
||||
- "/dev/random:/dev/virt-random:rwm"
|
||||
- "/dev/null:/dev/virt-null:rwm"
|
||||
force_kill: true
|
||||
comparisons:
|
||||
devices: allow_more_present
|
||||
register: set_dict_4
|
||||
|
||||
- name: set(dict) (change, strict)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
devices:
|
||||
- "/dev/random:/dev/virt-random:rwm"
|
||||
- "/dev/null:/dev/virt-null:rwm"
|
||||
force_kill: true
|
||||
comparisons:
|
||||
devices: strict
|
||||
register: set_dict_5
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- set_dict_1 is changed
|
||||
- set_dict_2 is not changed
|
||||
- set_dict_3 is changed
|
||||
- set_dict_4 is not changed
|
||||
- set_dict_5 is changed
|
||||
|
||||
####################################################################
|
||||
## dict ############################################################
|
||||
####################################################################
|
||||
|
||||
- name: dict
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
labels:
|
||||
ansible.test.1: hello
|
||||
ansible.test.2: world
|
||||
register: dict_1
|
||||
|
||||
- name: dict (change, ignore)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
labels:
|
||||
ansible.test.1: hello
|
||||
ansible.test.2: world
|
||||
ansible.test.3: ansible
|
||||
force_kill: true
|
||||
comparisons:
|
||||
labels: ignore
|
||||
register: dict_2
|
||||
|
||||
- name: dict (change, allow_more_present)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
labels:
|
||||
ansible.test.1: hello
|
||||
ansible.test.2: world
|
||||
ansible.test.3: ansible
|
||||
force_kill: true
|
||||
comparisons:
|
||||
labels: allow_more_present
|
||||
register: dict_3
|
||||
|
||||
- name: dict (change, allow_more_present)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
labels:
|
||||
ansible.test.1: hello
|
||||
ansible.test.3: ansible
|
||||
force_kill: true
|
||||
comparisons:
|
||||
labels: allow_more_present
|
||||
register: dict_4
|
||||
|
||||
- name: dict (change, strict)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
labels:
|
||||
ansible.test.1: hello
|
||||
ansible.test.3: ansible
|
||||
force_kill: true
|
||||
comparisons:
|
||||
labels: strict
|
||||
register: dict_5
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- dict_1 is changed
|
||||
- dict_2 is not changed
|
||||
- dict_3 is changed
|
||||
- dict_4 is not changed
|
||||
- dict_5 is changed
|
||||
|
||||
####################################################################
|
||||
## wildcard ########################################################
|
||||
####################################################################
|
||||
|
||||
- name: Pull {{ docker_test_image_hello_world }} image to make sure wildcard_2 test succeeds
|
||||
# If the image isn't there, it will pull it and return 'changed'.
|
||||
docker_image_pull:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
|
||||
- name: wildcard
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
hostname: example.com
|
||||
stop_timeout: 1
|
||||
labels:
|
||||
ansible.test.1: hello
|
||||
ansible.test.2: world
|
||||
ansible.test.3: ansible
|
||||
register: wildcard_1
|
||||
|
||||
- name: wildcard (change, ignore)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_hello_world }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
hostname: example.org
|
||||
stop_timeout: 2
|
||||
labels:
|
||||
ansible.test.1: hello
|
||||
ansible.test.4: ignore
|
||||
force_kill: true
|
||||
comparisons:
|
||||
'*': ignore
|
||||
register: wildcard_2
|
||||
|
||||
- name: wildcard (change, strict)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
hostname: example.org
|
||||
stop_timeout: 1
|
||||
labels:
|
||||
ansible.test.1: hello
|
||||
ansible.test.2: world
|
||||
ansible.test.3: ansible
|
||||
force_kill: true
|
||||
comparisons:
|
||||
'*': strict
|
||||
register: wildcard_3
|
||||
|
||||
- name: wildcard (no change, strict)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
hostname: example.org
|
||||
stop_timeout: 1
|
||||
labels:
|
||||
ansible.test.1: hello
|
||||
ansible.test.2: world
|
||||
ansible.test.3: ansible
|
||||
force_kill: true
|
||||
comparisons:
|
||||
'*': strict
|
||||
register: wildcard_4
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- wildcard_1 is changed
|
||||
- wildcard_2 is not changed
|
||||
- wildcard_3 is changed
|
||||
- wildcard_4 is not changed
|
@ -0,0 +1,122 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cname: "{{ cname_prefix ~ '-hi' }}"
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [cname] }}"
|
||||
|
||||
####################################################################
|
||||
## container_default_behavior: compatibility #######################
|
||||
####################################################################
|
||||
|
||||
- name: Start container (check)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
state: started
|
||||
container_default_behavior: compatibility
|
||||
check_mode: true
|
||||
register: start_1
|
||||
|
||||
- name: Start container
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
state: started
|
||||
container_default_behavior: compatibility
|
||||
register: start_2
|
||||
|
||||
- name: Start container (idempotent)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
state: started
|
||||
container_default_behavior: compatibility
|
||||
register: start_3
|
||||
|
||||
- name: Start container (idempotent check)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
state: started
|
||||
container_default_behavior: compatibility
|
||||
check_mode: true
|
||||
register: start_4
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- start_1 is changed
|
||||
- start_2 is changed
|
||||
- start_3 is not changed
|
||||
- start_4 is not changed
|
||||
|
||||
####################################################################
|
||||
## container_default_behavior: no_defaults #########################
|
||||
####################################################################
|
||||
|
||||
- name: Start container (check)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
state: started
|
||||
container_default_behavior: no_defaults
|
||||
check_mode: true
|
||||
register: start_1
|
||||
|
||||
- name: Start container
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
state: started
|
||||
container_default_behavior: no_defaults
|
||||
register: start_2
|
||||
|
||||
- name: Start container (idempotent)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
state: started
|
||||
container_default_behavior: no_defaults
|
||||
register: start_3
|
||||
|
||||
- name: Start container (idempotent check)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
state: started
|
||||
container_default_behavior: no_defaults
|
||||
check_mode: true
|
||||
register: start_4
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- start_1 is changed
|
||||
- start_2 is changed
|
||||
- start_3 is not changed
|
||||
- start_4 is not changed
|
@ -0,0 +1,64 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cname: "{{ cname_prefix ~ '-hi' }}"
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [cname] }}"
|
||||
|
||||
- name: Prepare container
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_healthcheck }}"
|
||||
command: '10m'
|
||||
state: stopped
|
||||
register: healthy_1
|
||||
|
||||
- debug: var=healthy_1.container.State
|
||||
|
||||
- name: Start container (not healthy in time)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: healthy
|
||||
healthy_wait_timeout: 1
|
||||
register: healthy_2
|
||||
ignore_errors: true
|
||||
|
||||
- debug: var=healthy_2.container.State
|
||||
|
||||
- name: Prepare container
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_healthcheck }}"
|
||||
command: '10m 5s'
|
||||
state: stopped
|
||||
force_kill: true
|
||||
register: healthy_3
|
||||
|
||||
- debug: var=healthy_3.container.State
|
||||
|
||||
- name: Start container (healthy in time)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: healthy
|
||||
healthy_wait_timeout: 10
|
||||
register: healthy_4
|
||||
|
||||
- debug: var=healthy_4.container.State
|
||||
|
||||
- name: Cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
- assert:
|
||||
that:
|
||||
- healthy_2 is failed
|
||||
- healthy_2.container.State.Health.Status == "starting"
|
||||
- healthy_2.msg.startswith("Timeout of 1.0 seconds exceeded while waiting for container ")
|
||||
- healthy_4 is changed
|
||||
- healthy_4.container.State.Health.Status == "healthy"
|
@ -0,0 +1,155 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cname: "{{ cname_prefix ~ '-iid' }}"
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [cname] }}"
|
||||
|
||||
- name: Pull images
|
||||
docker_image_pull:
|
||||
name: "{{ image }}"
|
||||
loop:
|
||||
- "{{ docker_test_image_hello_world }}"
|
||||
- "{{ docker_test_image_alpine }}"
|
||||
loop_control:
|
||||
loop_var: image
|
||||
|
||||
- name: Get image ID of {{ docker_test_image_hello_world }} and {{ docker_test_image_alpine }} images
|
||||
docker_image_info:
|
||||
name:
|
||||
- "{{ docker_test_image_hello_world }}"
|
||||
- "{{ docker_test_image_alpine }}"
|
||||
register: image_info
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- image_info.images | length == 2
|
||||
|
||||
- name: Print image IDs
|
||||
debug:
|
||||
msg: "{{ docker_test_image_hello_world }}: {{ image_info.images[0].Id }}; {{ docker_test_image_alpine }}: {{ image_info.images[1].Id }}"
|
||||
|
||||
- name: Create container with {{ docker_test_image_hello_world }} image via ID
|
||||
docker_container:
|
||||
image: "{{ image_info.images[0].Id }}"
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
force_kill: true
|
||||
register: create_1
|
||||
|
||||
- name: Create container with {{ docker_test_image_hello_world }} image via ID (idempotent)
|
||||
docker_container:
|
||||
image: "{{ image_info.images[0].Id }}"
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
force_kill: true
|
||||
register: create_2
|
||||
|
||||
- name: Create container with {{ docker_test_image_alpine }} image via ID
|
||||
docker_container:
|
||||
image: "{{ image_info.images[1].Id }}"
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
force_kill: true
|
||||
register: create_3
|
||||
|
||||
- name: Create container with {{ docker_test_image_alpine }} image via ID (idempotent)
|
||||
docker_container:
|
||||
image: "{{ image_info.images[1].Id }}"
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
force_kill: true
|
||||
register: create_4
|
||||
|
||||
- name: Untag image
|
||||
# Image will not be deleted since the container still uses it
|
||||
docker_image_remove:
|
||||
name: "{{ docker_test_image_alpine }}"
|
||||
force: true
|
||||
|
||||
- name: Create container with {{ docker_test_image_alpine }} image via name (check mode, will pull, same image)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
image_name_mismatch: ignore
|
||||
register: create_5
|
||||
check_mode: true
|
||||
|
||||
- name: Create container with {{ docker_test_image_alpine }} image via name (will pull, same image)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
image_name_mismatch: ignore
|
||||
register: create_6
|
||||
|
||||
- name: Cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_1 is changed
|
||||
- create_2 is not changed
|
||||
- create_3 is changed
|
||||
- create_4 is not changed
|
||||
- create_5 is changed
|
||||
- create_6 is changed
|
||||
- create_6.container.Image == image_info.images[1].Id
|
||||
- create_6.container.Id == create_4.container.Id # make sure container wasn't recreated
|
||||
|
||||
- name: Create container with {{ docker_test_image_digest_base }} image via old digest
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_digest_base }}@sha256:{{ docker_test_image_digest_v1 }}"
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
force_kill: true
|
||||
register: digest_1
|
||||
|
||||
- name: Create container with {{ docker_test_image_digest_base }} image via old digest (idempotent)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_digest_base }}@sha256:{{ docker_test_image_digest_v1 }}"
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
force_kill: true
|
||||
register: digest_2
|
||||
|
||||
- name: Create container with {{ docker_test_image_digest_base }} image via old digest (idempotent, pull)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_digest_base }}@sha256:{{ docker_test_image_digest_v1 }}"
|
||||
name: "{{ cname }}"
|
||||
pull: true
|
||||
state: present
|
||||
force_kill: true
|
||||
register: digest_3
|
||||
|
||||
- name: Update container with {{ docker_test_image_digest_base }} image via new digest
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_digest_base }}@sha256:{{ docker_test_image_digest_v2 }}"
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
force_kill: true
|
||||
register: digest_4
|
||||
|
||||
- name: Cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- digest_1 is changed
|
||||
- digest_2 is not changed
|
||||
- digest_3 is not changed
|
||||
- digest_4 is changed
|
@ -0,0 +1,558 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cname: "{{ cname_prefix ~ '-mounts' }}"
|
||||
cname_h1: "{{ cname_prefix ~ '-mounts-h1' }}"
|
||||
cname_h2: "{{ cname_prefix ~ '-mounts-h2' }}"
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [cname, cname_h1, cname_h2] }}"
|
||||
|
||||
####################################################################
|
||||
## keep_volumes ####################################################
|
||||
####################################################################
|
||||
|
||||
# TODO: - keep_volumes
|
||||
|
||||
####################################################################
|
||||
## mounts ##########################################################
|
||||
####################################################################
|
||||
|
||||
- name: mounts
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- source: /tmp
|
||||
target: /tmp
|
||||
type: bind
|
||||
- source: /
|
||||
target: /whatever
|
||||
type: bind
|
||||
read_only: false
|
||||
register: mounts_1
|
||||
|
||||
- name: mounts (idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- source: /
|
||||
target: /whatever
|
||||
type: bind
|
||||
read_only: false
|
||||
- source: /tmp
|
||||
target: /tmp
|
||||
type: bind
|
||||
register: mounts_2
|
||||
|
||||
- name: mounts (less mounts)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- source: /tmp
|
||||
target: /tmp
|
||||
type: bind
|
||||
register: mounts_3
|
||||
|
||||
- name: mounts (more mounts)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- source: /tmp
|
||||
target: /tmp
|
||||
type: bind
|
||||
- source: /tmp
|
||||
target: /somewhereelse
|
||||
type: bind
|
||||
read_only: true
|
||||
force_kill: true
|
||||
register: mounts_4
|
||||
|
||||
- name: mounts (different modes)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- source: /tmp
|
||||
target: /tmp
|
||||
type: bind
|
||||
- source: /tmp
|
||||
target: /somewhereelse
|
||||
type: bind
|
||||
read_only: false
|
||||
force_kill: true
|
||||
register: mounts_5
|
||||
|
||||
- name: mounts (endpoint collision)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- source: /home
|
||||
target: /x
|
||||
type: bind
|
||||
- source: /etc
|
||||
target: /x
|
||||
type: bind
|
||||
read_only: false
|
||||
force_kill: true
|
||||
register: mounts_6
|
||||
ignore_errors: true
|
||||
|
||||
- name: mounts (anonymous volume)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- target: /tmp
|
||||
type: volume
|
||||
force_kill: true
|
||||
register: mounts_7
|
||||
|
||||
- name: mounts (anonymous volume idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- target: /tmp
|
||||
type: volume
|
||||
force_kill: true
|
||||
register: mounts_8
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mounts_1 is changed
|
||||
- mounts_2 is not changed
|
||||
- mounts_3 is not changed
|
||||
- mounts_4 is changed
|
||||
- mounts_5 is changed
|
||||
- mounts_6 is failed
|
||||
- "'The mount point \"/x\" appears twice in the mounts option' == mounts_6.msg"
|
||||
- mounts_7 is changed
|
||||
- mounts_8 is not changed
|
||||
|
||||
####################################################################
|
||||
## tmpfs ###########################################################
|
||||
####################################################################
|
||||
|
||||
- name: tmpfs
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- target: /cache1
|
||||
type: tmpfs
|
||||
tmpfs_mode: "1777"
|
||||
tmpfs_size: "1GB"
|
||||
- target: /cache2
|
||||
type: tmpfs
|
||||
tmpfs_mode: "1777"
|
||||
tmpfs_size: "1GB"
|
||||
force_kill: true
|
||||
register: tmpfs_1
|
||||
|
||||
- name: tmpfs (idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- target: /cache2
|
||||
type: tmpfs
|
||||
tmpfs_mode: "1777"
|
||||
tmpfs_size: "1GB"
|
||||
- target: /cache1
|
||||
type: tmpfs
|
||||
tmpfs_mode: "1777"
|
||||
tmpfs_size: "1GB"
|
||||
force_kill: true
|
||||
register: tmpfs_2
|
||||
|
||||
- name: tmpfs (more mounts)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- target: /cache1
|
||||
type: tmpfs
|
||||
tmpfs_mode: "1777"
|
||||
tmpfs_size: "1GB"
|
||||
- target: /cache2
|
||||
type: tmpfs
|
||||
tmpfs_mode: "1777"
|
||||
tmpfs_size: "1GB"
|
||||
- target: /cache3
|
||||
type: tmpfs
|
||||
tmpfs_mode: "1777"
|
||||
tmpfs_size: "1GB"
|
||||
force_kill: true
|
||||
register: tmpfs_3
|
||||
|
||||
- name: tmpfs (change mode)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- target: /cache1
|
||||
type: tmpfs
|
||||
tmpfs_mode: "1700"
|
||||
tmpfs_size: "1GB"
|
||||
force_kill: true
|
||||
register: tmpfs_4
|
||||
|
||||
- name: tmpfs (change size)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- target: /cache1
|
||||
type: tmpfs
|
||||
tmpfs_mode: "1700"
|
||||
tmpfs_size: "2GB"
|
||||
force_kill: true
|
||||
register: tmpfs_5
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- tmpfs_1 is changed
|
||||
- tmpfs_2 is not changed
|
||||
- tmpfs_3 is changed
|
||||
- tmpfs_4 is changed
|
||||
- tmpfs_5 is changed
|
||||
|
||||
####################################################################
|
||||
## mounts + volumes ################################################
|
||||
####################################################################
|
||||
|
||||
- name: mounts + volumes
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- source: /
|
||||
target: /whatever
|
||||
type: bind
|
||||
read_only: true
|
||||
volumes:
|
||||
- /tmp:/tmp
|
||||
register: mounts_volumes_1
|
||||
|
||||
- name: mounts + volumes (idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- source: /
|
||||
target: /whatever
|
||||
type: bind
|
||||
read_only: true
|
||||
volumes:
|
||||
- /tmp:/tmp
|
||||
register: mounts_volumes_2
|
||||
|
||||
- name: mounts + volumes (switching)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- source: /tmp
|
||||
target: /tmp
|
||||
type: bind
|
||||
read_only: false
|
||||
volumes:
|
||||
- /:/whatever:ro
|
||||
force_kill: true
|
||||
register: mounts_volumes_3
|
||||
|
||||
- name: mounts + volumes (collision, should fail)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
mounts:
|
||||
- source: /tmp
|
||||
target: /tmp
|
||||
type: bind
|
||||
read_only: false
|
||||
volumes:
|
||||
- /tmp:/tmp
|
||||
force_kill: true
|
||||
register: mounts_volumes_4
|
||||
ignore_errors: true
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mounts_volumes_1 is changed
|
||||
- mounts_volumes_2 is not changed
|
||||
- mounts_volumes_3 is changed
|
||||
- mounts_volumes_4 is failed
|
||||
- "'The mount point \"/tmp\" appears both in the volumes and mounts option' in mounts_volumes_4.msg"
|
||||
|
||||
####################################################################
|
||||
## volume_driver ###################################################
|
||||
####################################################################
|
||||
|
||||
- name: volume_driver
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
volume_driver: local
|
||||
state: started
|
||||
register: volume_driver_1
|
||||
|
||||
- name: volume_driver (idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
volume_driver: local
|
||||
state: started
|
||||
register: volume_driver_2
|
||||
|
||||
- name: volume_driver (change)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
volume_driver: /
|
||||
state: started
|
||||
force_kill: true
|
||||
register: volume_driver_3
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- volume_driver_1 is changed
|
||||
- volume_driver_2 is not changed
|
||||
- volume_driver_3 is changed
|
||||
|
||||
####################################################################
|
||||
## volumes #########################################################
|
||||
####################################################################
|
||||
|
||||
- name: volumes
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
volumes:
|
||||
- "/tmp:/tmp"
|
||||
- "/:/whatever:rw,z"
|
||||
- "/anon:rw"
|
||||
register: volumes_1
|
||||
|
||||
- name: volumes (idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
volumes:
|
||||
- "/:/whatever:rw,z"
|
||||
- "/tmp:/tmp"
|
||||
- "/anon:rw"
|
||||
register: volumes_2
|
||||
|
||||
- name: volumes (less volumes)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
volumes:
|
||||
- "/tmp:/tmp"
|
||||
register: volumes_3
|
||||
|
||||
- name: volumes (more volumes)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
volumes:
|
||||
- "/tmp:/tmp"
|
||||
- "/tmp:/somewhereelse:ro,Z"
|
||||
force_kill: true
|
||||
register: volumes_4
|
||||
|
||||
- name: volumes (different modes)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
volumes:
|
||||
- "/tmp:/tmp"
|
||||
- "/tmp:/somewhereelse:ro"
|
||||
force_kill: true
|
||||
register: volumes_5
|
||||
|
||||
- name: volumes (collision)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
volumes:
|
||||
- "/etc:/tmp"
|
||||
- "/home:/tmp:ro"
|
||||
force_kill: true
|
||||
register: volumes_6
|
||||
ignore_errors: true
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- volumes_1 is changed
|
||||
- volumes_1.container.Config.Volumes | length == 1
|
||||
- volumes_1.container.Config.Volumes['/anon:rw'] | length == 0
|
||||
- volumes_2 is not changed
|
||||
- volumes_3 is not changed
|
||||
- volumes_4 is changed
|
||||
- not volumes_4.container.Config.Volumes
|
||||
- volumes_5 is changed
|
||||
- volumes_6 is failed
|
||||
- "'The mount point \"/tmp\" appears twice in the volumes option' in volumes_6.msg"
|
||||
|
||||
####################################################################
|
||||
## volumes_from ####################################################
|
||||
####################################################################
|
||||
|
||||
- name: start helpers
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ container_name }}"
|
||||
state: started
|
||||
volumes:
|
||||
- "{{ '/tmp:/tmp' if container_name == cname_h1 else '/:/whatever:ro' }}"
|
||||
loop:
|
||||
- "{{ cname_h1 }}"
|
||||
- "{{ cname_h2 }}"
|
||||
loop_control:
|
||||
loop_var: container_name
|
||||
|
||||
- name: volumes_from
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
volumes_from: "{{ cname_h1 }}"
|
||||
register: volumes_from_1
|
||||
|
||||
- name: volumes_from (idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
volumes_from: "{{ cname_h1 }}"
|
||||
register: volumes_from_2
|
||||
|
||||
- name: volumes_from (change)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
volumes_from: "{{ cname_h2 }}"
|
||||
force_kill: true
|
||||
register: volumes_from_3
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ container_name }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
loop:
|
||||
- "{{ cname }}"
|
||||
- "{{ cname_h1 }}"
|
||||
- "{{ cname_h2 }}"
|
||||
loop_control:
|
||||
loop_var: container_name
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- volumes_from_1 is changed
|
||||
- volumes_from_2 is not changed
|
||||
- volumes_from_3 is changed
|
||||
|
||||
####################################################################
|
||||
####################################################################
|
||||
####################################################################
|
@ -0,0 +1,745 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cname: "{{ cname_prefix ~ '-network' }}"
|
||||
cname_h1: "{{ cname_prefix ~ '-network-h1' }}"
|
||||
nname_1: "{{ cname_prefix ~ '-network-1' }}"
|
||||
nname_2: "{{ cname_prefix ~ '-network-2' }}"
|
||||
nname_3: "{{ cname_prefix ~ '-network-3' }}"
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [cname, cname_h1] }}"
|
||||
dnetworks: "{{ dnetworks + [nname_1, nname_2, nname_3] }}"
|
||||
|
||||
- name: Create networks
|
||||
docker_network:
|
||||
name: "{{ network_name }}"
|
||||
state: present
|
||||
loop:
|
||||
- "{{ nname_1 }}"
|
||||
- "{{ nname_2 }}"
|
||||
loop_control:
|
||||
loop_var: network_name
|
||||
|
||||
- set_fact:
|
||||
subnet_ipv4_base: 10.{{ 16 + (240 | random) }}.{{ 16 + (240 | random) }}
|
||||
subnet_ipv6_base: fdb6:feea:{{ '%0.4x:%0.4x' | format(65536 | random, 65536 | random) }}
|
||||
# If netaddr would be installed on the controller, one could do:
|
||||
# subnet_ipv4: "10.{{ 16 + (240 | random) }}.{{ 16 + (240 | random) }}.0/24"
|
||||
# subnet_ipv6: "fdb6:feea:{{ '%0.4x:%0.4x' | format(65536 | random, 65536 | random) }}::/64"
|
||||
|
||||
- set_fact:
|
||||
subnet_ipv4: "{{ subnet_ipv4_base }}.0/24"
|
||||
subnet_ipv6: "{{ subnet_ipv6_base }}::/64"
|
||||
nname_3_ipv4_2: "{{ subnet_ipv4_base }}.2"
|
||||
nname_3_ipv4_3: "{{ subnet_ipv4_base }}.3"
|
||||
nname_3_ipv4_4: "{{ subnet_ipv4_base }}.4"
|
||||
nname_3_ipv6_2: "{{ subnet_ipv6_base }}::2"
|
||||
nname_3_ipv6_3: "{{ subnet_ipv6_base }}::3"
|
||||
nname_3_ipv6_4: "{{ subnet_ipv6_base }}::4"
|
||||
# If netaddr would be installed on the controller, one could do:
|
||||
# nname_3_ipv4_2: "{{ subnet_ipv4 | ansible.netcommon.next_nth_usable(2) }}"
|
||||
# nname_3_ipv4_3: "{{ subnet_ipv4 | ansible.netcommon.next_nth_usable(3) }}"
|
||||
# nname_3_ipv4_4: "{{ subnet_ipv4 | ansible.netcommon.next_nth_usable(4) }}"
|
||||
# nname_3_ipv6_2: "{{ subnet_ipv6 | ansible.netcommon.next_nth_usable(2) }}"
|
||||
# nname_3_ipv6_3: "{{ subnet_ipv6 | ansible.netcommon.next_nth_usable(3) }}"
|
||||
# nname_3_ipv6_4: "{{ subnet_ipv6 | ansible.netcommon.next_nth_usable(4) }}"
|
||||
|
||||
- debug:
|
||||
msg: "Chose random IPv4 subnet {{ subnet_ipv4 }} and random IPv6 subnet {{ subnet_ipv6 }}"
|
||||
|
||||
- name: Create network with fixed IPv4 and IPv6 subnets
|
||||
docker_network:
|
||||
name: "{{ nname_3 }}"
|
||||
enable_ipv6: true
|
||||
ipam_config:
|
||||
- subnet: "{{ subnet_ipv4 }}"
|
||||
- subnet: "{{ subnet_ipv6 }}"
|
||||
state: present
|
||||
|
||||
####################################################################
|
||||
## network_mode ####################################################
|
||||
####################################################################
|
||||
|
||||
- name: network_mode
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
network_mode: host
|
||||
register: network_mode_1
|
||||
|
||||
- name: network_mode (idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
network_mode: host
|
||||
register: network_mode_2
|
||||
|
||||
- name: network_mode (change)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
network_mode: none
|
||||
force_kill: true
|
||||
register: network_mode_3
|
||||
|
||||
- name: network_mode (container mode setup)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname_h1 }}"
|
||||
state: started
|
||||
register: cname_h1_id
|
||||
|
||||
- name: network_mode (container mode)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
network_mode: "container:{{ cname_h1_id.container.Id }}"
|
||||
force_kill: true
|
||||
register: network_mode_4
|
||||
|
||||
- name: network_mode (container mode idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
network_mode: "container:{{ cname_h1 }}"
|
||||
register: network_mode_5
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ container_name }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
loop:
|
||||
- "{{ cname }}"
|
||||
- "{{ cname_h1 }}"
|
||||
loop_control:
|
||||
loop_var: container_name
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- network_mode_1 is changed
|
||||
- network_mode_1.container.HostConfig.NetworkMode == 'host'
|
||||
- network_mode_2 is not changed
|
||||
- network_mode_2.container.HostConfig.NetworkMode == 'host'
|
||||
- network_mode_3 is changed
|
||||
- network_mode_3.container.HostConfig.NetworkMode == 'none'
|
||||
- network_mode_4 is changed
|
||||
- network_mode_4.container.HostConfig.NetworkMode == ('container:' ~ cname_h1_id.container.Id)
|
||||
- network_mode_5 is not changed
|
||||
- network_mode_5.container.HostConfig.NetworkMode == ('container:' ~ cname_h1_id.container.Id)
|
||||
|
||||
####################################################################
|
||||
## networks, purge_networks for networks_cli_compatible=no #########
|
||||
####################################################################
|
||||
|
||||
- name: networks_cli_compatible=no, networks w/o purge_networks
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: "{{ nname_1 }}"
|
||||
- name: "{{ nname_2 }}"
|
||||
networks_cli_compatible: false
|
||||
register: networks_1
|
||||
|
||||
- name: networks_cli_compatible=no, networks w/o purge_networks
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: "{{ nname_1 }}"
|
||||
- name: "{{ nname_2 }}"
|
||||
networks_cli_compatible: false
|
||||
register: networks_2
|
||||
|
||||
- name: networks_cli_compatible=no, networks, purge_networks
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
comparisons:
|
||||
networks: strict
|
||||
networks:
|
||||
- name: bridge
|
||||
- name: "{{ nname_1 }}"
|
||||
networks_cli_compatible: false
|
||||
force_kill: true
|
||||
register: networks_3
|
||||
|
||||
- name: networks_cli_compatible=no, networks, purge_networks (idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
comparisons:
|
||||
networks: strict
|
||||
networks:
|
||||
- name: "{{ nname_1 }}"
|
||||
- name: bridge
|
||||
networks_cli_compatible: false
|
||||
register: networks_4
|
||||
|
||||
- name: networks_cli_compatible=no, networks (less networks)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: bridge
|
||||
networks_cli_compatible: false
|
||||
register: networks_5
|
||||
|
||||
- name: networks_cli_compatible=no, networks, purge_networks (less networks)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
comparisons:
|
||||
networks: strict
|
||||
networks:
|
||||
- name: bridge
|
||||
networks_cli_compatible: false
|
||||
force_kill: true
|
||||
register: networks_6
|
||||
|
||||
- name: networks_cli_compatible=no, networks, purge_networks (more networks)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
comparisons:
|
||||
networks: strict
|
||||
networks:
|
||||
- name: bridge
|
||||
- name: "{{ nname_2 }}"
|
||||
networks_cli_compatible: false
|
||||
force_kill: true
|
||||
register: networks_7
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
# networks_1 has networks default, 'bridge', nname_1
|
||||
- networks_1 is changed
|
||||
- networks_1.container.NetworkSettings.Networks | length == 3
|
||||
- nname_1 in networks_1.container.NetworkSettings.Networks
|
||||
- nname_2 in networks_1.container.NetworkSettings.Networks
|
||||
- "'default' in networks_1.container.NetworkSettings.Networks or 'bridge' in networks_1.container.NetworkSettings.Networks"
|
||||
# networks_2 has networks default, 'bridge', nname_1
|
||||
- networks_2 is not changed
|
||||
- networks_2.container.NetworkSettings.Networks | length == 3
|
||||
- nname_1 in networks_2.container.NetworkSettings.Networks
|
||||
- nname_2 in networks_1.container.NetworkSettings.Networks
|
||||
- "'default' in networks_1.container.NetworkSettings.Networks or 'bridge' in networks_1.container.NetworkSettings.Networks"
|
||||
# networks_3 has networks 'bridge', nname_1
|
||||
- networks_3 is changed
|
||||
- networks_3.container.NetworkSettings.Networks | length == 2
|
||||
- nname_1 in networks_3.container.NetworkSettings.Networks
|
||||
- "'default' in networks_3.container.NetworkSettings.Networks or 'bridge' in networks_3.container.NetworkSettings.Networks"
|
||||
# networks_4 has networks 'bridge', nname_1
|
||||
- networks_4 is not changed
|
||||
- networks_4.container.NetworkSettings.Networks | length == 2
|
||||
- nname_1 in networks_4.container.NetworkSettings.Networks
|
||||
- "'default' in networks_4.container.NetworkSettings.Networks or 'bridge' in networks_4.container.NetworkSettings.Networks"
|
||||
# networks_5 has networks 'bridge', nname_1
|
||||
- networks_5 is not changed
|
||||
- networks_5.container.NetworkSettings.Networks | length == 2
|
||||
- nname_1 in networks_5.container.NetworkSettings.Networks
|
||||
- "'default' in networks_5.container.NetworkSettings.Networks or 'bridge' in networks_5.container.NetworkSettings.Networks"
|
||||
# networks_6 has networks 'bridge'
|
||||
- networks_6 is changed
|
||||
- networks_6.container.NetworkSettings.Networks | length == 1
|
||||
- "'default' in networks_6.container.NetworkSettings.Networks or 'bridge' in networks_6.container.NetworkSettings.Networks"
|
||||
# networks_7 has networks 'bridge', nname_2
|
||||
- networks_7 is changed
|
||||
- networks_7.container.NetworkSettings.Networks | length == 2
|
||||
- nname_2 in networks_7.container.NetworkSettings.Networks
|
||||
- "'default' in networks_7.container.NetworkSettings.Networks or 'bridge' in networks_7.container.NetworkSettings.Networks"
|
||||
|
||||
####################################################################
|
||||
## networks for networks_cli_compatible=yes ########################
|
||||
####################################################################
|
||||
|
||||
- name: networks_cli_compatible=yes, networks specified
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: "{{ nname_1 }}"
|
||||
aliases:
|
||||
- alias1
|
||||
- alias2
|
||||
- name: "{{ nname_2 }}"
|
||||
networks_cli_compatible: true
|
||||
register: networks_1
|
||||
|
||||
- name: networks_cli_compatible=yes, networks specified
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: "{{ nname_1 }}"
|
||||
- name: "{{ nname_2 }}"
|
||||
networks_cli_compatible: true
|
||||
register: networks_2
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- name: networks_cli_compatible=yes, empty networks list specified
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks: []
|
||||
networks_cli_compatible: true
|
||||
register: networks_3
|
||||
|
||||
- name: networks_cli_compatible=yes, empty networks list specified
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks: []
|
||||
networks_cli_compatible: true
|
||||
register: networks_4
|
||||
|
||||
- name: networks_cli_compatible=yes, empty networks list specified, purge_networks
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks: []
|
||||
networks_cli_compatible: true
|
||||
comparisons:
|
||||
networks: strict
|
||||
force_kill: true
|
||||
register: networks_5
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- name: networks_cli_compatible=yes, networks not specified
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks_cli_compatible: true
|
||||
force_kill: true
|
||||
register: networks_6
|
||||
|
||||
- name: networks_cli_compatible=yes, networks not specified
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks_cli_compatible: true
|
||||
register: networks_7
|
||||
|
||||
- name: networks_cli_compatible=yes, networks empty, purge_networks
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks_cli_compatible: true
|
||||
comparisons:
|
||||
networks: strict
|
||||
networks: []
|
||||
force_kill: true
|
||||
register: networks_8
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- debug: var=networks_3
|
||||
|
||||
- assert:
|
||||
that:
|
||||
# networks_1 has networks nname_1, nname_2
|
||||
- networks_1 is changed
|
||||
- networks_1.container.NetworkSettings.Networks | length == 2
|
||||
- nname_1 in networks_1.container.NetworkSettings.Networks
|
||||
- nname_2 in networks_1.container.NetworkSettings.Networks
|
||||
# networks_2 has networks nname_1, nname_2
|
||||
- networks_2 is not changed
|
||||
- networks_2.container.NetworkSettings.Networks | length == 2
|
||||
- nname_1 in networks_2.container.NetworkSettings.Networks
|
||||
- nname_2 in networks_1.container.NetworkSettings.Networks
|
||||
# networks_3 has networks 'bridge'
|
||||
- networks_3 is changed
|
||||
- networks_3.container.NetworkSettings.Networks | length == 1
|
||||
- "'default' in networks_3.container.NetworkSettings.Networks or 'bridge' in networks_3.container.NetworkSettings.Networks"
|
||||
# networks_4 has networks 'bridge'
|
||||
- networks_4 is not changed
|
||||
- networks_4.container.NetworkSettings.Networks | length == 1
|
||||
- "'default' in networks_4.container.NetworkSettings.Networks or 'bridge' in networks_4.container.NetworkSettings.Networks"
|
||||
# networks_5 has no networks
|
||||
- networks_5 is changed
|
||||
- networks_5.container.NetworkSettings.Networks | length == 0
|
||||
# networks_6 has networks 'bridge'
|
||||
- networks_6 is changed
|
||||
- networks_6.container.NetworkSettings.Networks | length == 1
|
||||
- "'default' in networks_6.container.NetworkSettings.Networks or 'bridge' in networks_6.container.NetworkSettings.Networks"
|
||||
# networks_7 has networks 'bridge'
|
||||
- networks_7 is not changed
|
||||
- networks_7.container.NetworkSettings.Networks | length == 1
|
||||
- "'default' in networks_7.container.NetworkSettings.Networks or 'bridge' in networks_7.container.NetworkSettings.Networks"
|
||||
# networks_8 has no networks
|
||||
- networks_8 is changed
|
||||
- networks_8.container.NetworkSettings.Networks | length == 0
|
||||
|
||||
####################################################################
|
||||
## networks with comparisons #######################################
|
||||
####################################################################
|
||||
|
||||
- name: create container with one network
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: "{{ nname_1 }}"
|
||||
networks_cli_compatible: true
|
||||
register: networks_1
|
||||
|
||||
- name: different networks, comparisons=ignore
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: "{{ nname_2 }}"
|
||||
networks_cli_compatible: true
|
||||
comparisons:
|
||||
network_mode: ignore # otherwise we'd have to set network_mode to nname_1
|
||||
networks: ignore
|
||||
register: networks_2
|
||||
|
||||
- name: less networks, comparisons=ignore
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks: []
|
||||
networks_cli_compatible: true
|
||||
comparisons:
|
||||
networks: ignore
|
||||
register: networks_3
|
||||
|
||||
- name: less networks, comparisons=allow_more_present
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks: []
|
||||
networks_cli_compatible: true
|
||||
comparisons:
|
||||
networks: allow_more_present
|
||||
register: networks_4
|
||||
|
||||
- name: different networks, comparisons=allow_more_present
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: "{{ nname_2 }}"
|
||||
networks_cli_compatible: true
|
||||
comparisons:
|
||||
network_mode: ignore # otherwise we'd have to set network_mode to nname_1
|
||||
networks: allow_more_present
|
||||
force_kill: true
|
||||
register: networks_5
|
||||
|
||||
- name: different networks, comparisons=strict
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: "{{ nname_2 }}"
|
||||
networks_cli_compatible: true
|
||||
comparisons:
|
||||
networks: strict
|
||||
force_kill: true
|
||||
register: networks_6
|
||||
|
||||
- name: less networks, comparisons=strict
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks: []
|
||||
networks_cli_compatible: true
|
||||
comparisons:
|
||||
networks: strict
|
||||
force_kill: true
|
||||
register: networks_7
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
# networks_1 has networks nname_1
|
||||
- networks_1 is changed
|
||||
- networks_1.container.NetworkSettings.Networks | length == 1
|
||||
- nname_1 in networks_1.container.NetworkSettings.Networks
|
||||
# networks_2 has networks nname_1
|
||||
- networks_2 is not changed
|
||||
- networks_2.container.NetworkSettings.Networks | length == 1
|
||||
- nname_1 in networks_2.container.NetworkSettings.Networks
|
||||
# networks_3 has networks nname_1
|
||||
- networks_3 is not changed
|
||||
- networks_3.container.NetworkSettings.Networks | length == 1
|
||||
- nname_1 in networks_3.container.NetworkSettings.Networks
|
||||
# networks_4 has networks nname_1
|
||||
- networks_4 is not changed
|
||||
- networks_4.container.NetworkSettings.Networks | length == 1
|
||||
- nname_1 in networks_4.container.NetworkSettings.Networks
|
||||
# networks_5 has networks nname_1, nname_2
|
||||
- networks_5 is changed
|
||||
- networks_5.container.NetworkSettings.Networks | length == 2
|
||||
- nname_1 in networks_5.container.NetworkSettings.Networks
|
||||
- nname_2 in networks_5.container.NetworkSettings.Networks
|
||||
# networks_6 has networks nname_2
|
||||
- networks_6 is changed
|
||||
- networks_6.container.NetworkSettings.Networks | length == 1
|
||||
- nname_2 in networks_6.container.NetworkSettings.Networks
|
||||
# networks_7 has no networks
|
||||
- networks_7 is changed
|
||||
- networks_7.container.NetworkSettings.Networks | length == 0
|
||||
|
||||
####################################################################
|
||||
## networks with IP address ########################################
|
||||
####################################################################
|
||||
|
||||
- name: create container (stopped) with one network and fixed IP
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: stopped
|
||||
networks:
|
||||
- name: "{{ nname_3 }}"
|
||||
ipv4_address: "{{ nname_3_ipv4_2 }}"
|
||||
ipv6_address: "{{ nname_3_ipv6_2 }}"
|
||||
networks_cli_compatible: true
|
||||
register: networks_1
|
||||
|
||||
- name: create container (stopped) with one network and fixed IP (idempotent)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: stopped
|
||||
networks:
|
||||
- name: "{{ nname_3 }}"
|
||||
ipv4_address: "{{ nname_3_ipv4_2 }}"
|
||||
ipv6_address: "{{ nname_3_ipv6_2 }}"
|
||||
networks_cli_compatible: true
|
||||
register: networks_2
|
||||
|
||||
- name: create container (stopped) with one network and fixed IP (different IPv4)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: stopped
|
||||
networks:
|
||||
- name: "{{ nname_3 }}"
|
||||
ipv4_address: "{{ nname_3_ipv4_3 }}"
|
||||
ipv6_address: "{{ nname_3_ipv6_2 }}"
|
||||
networks_cli_compatible: true
|
||||
register: networks_3
|
||||
|
||||
- name: create container (stopped) with one network and fixed IP (different IPv6)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: stopped
|
||||
networks:
|
||||
- name: "{{ nname_3 }}"
|
||||
ipv4_address: "{{ nname_3_ipv4_3 }}"
|
||||
ipv6_address: "{{ nname_3_ipv6_3 }}"
|
||||
networks_cli_compatible: true
|
||||
register: networks_4
|
||||
|
||||
- name: create container (started) with one network and fixed IP
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
register: networks_5
|
||||
|
||||
- name: create container (started) with one network and fixed IP (different IPv4)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: "{{ nname_3 }}"
|
||||
ipv4_address: "{{ nname_3_ipv4_4 }}"
|
||||
ipv6_address: "{{ nname_3_ipv6_3 }}"
|
||||
networks_cli_compatible: true
|
||||
force_kill: true
|
||||
register: networks_6
|
||||
|
||||
- name: create container (started) with one network and fixed IP (different IPv6)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: "{{ nname_3 }}"
|
||||
ipv4_address: "{{ nname_3_ipv4_4 }}"
|
||||
ipv6_address: "{{ nname_3_ipv6_4 }}"
|
||||
networks_cli_compatible: true
|
||||
force_kill: true
|
||||
register: networks_7
|
||||
|
||||
- name: create container (started) with one network and fixed IP (idempotent)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
networks:
|
||||
- name: "{{ nname_3 }}"
|
||||
ipv4_address: "{{ nname_3_ipv4_4 }}"
|
||||
ipv6_address: "{{ nname_3_ipv6_4 }}"
|
||||
networks_cli_compatible: true
|
||||
register: networks_8
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- networks_1 is changed
|
||||
- networks_1.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv4Address == nname_3_ipv4_2
|
||||
- networks_1.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv6Address | normalize_ipaddr == nname_3_ipv6_2 | normalize_ipaddr
|
||||
- networks_1.container.NetworkSettings.Networks[nname_3].IPAddress == ""
|
||||
- networks_1.container.NetworkSettings.Networks[nname_3].GlobalIPv6Address == ""
|
||||
- networks_2 is not changed
|
||||
- networks_2.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv4Address == nname_3_ipv4_2
|
||||
- networks_2.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv6Address | normalize_ipaddr == nname_3_ipv6_2 | normalize_ipaddr
|
||||
- networks_2.container.NetworkSettings.Networks[nname_3].IPAddress == ""
|
||||
- networks_2.container.NetworkSettings.Networks[nname_3].GlobalIPv6Address == ""
|
||||
- networks_3 is changed
|
||||
- networks_3.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv4Address == nname_3_ipv4_3
|
||||
- networks_3.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv6Address | normalize_ipaddr == nname_3_ipv6_2 | normalize_ipaddr
|
||||
- networks_3.container.NetworkSettings.Networks[nname_3].IPAddress == ""
|
||||
- networks_3.container.NetworkSettings.Networks[nname_3].GlobalIPv6Address == ""
|
||||
- networks_4 is changed
|
||||
- networks_4.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv4Address == nname_3_ipv4_3
|
||||
- networks_4.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv6Address | normalize_ipaddr == nname_3_ipv6_3 | normalize_ipaddr
|
||||
- networks_4.container.NetworkSettings.Networks[nname_3].IPAddress == ""
|
||||
- networks_4.container.NetworkSettings.Networks[nname_3].GlobalIPv6Address == ""
|
||||
- networks_5 is changed
|
||||
- networks_5.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv4Address == nname_3_ipv4_3
|
||||
- networks_5.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv6Address | normalize_ipaddr == nname_3_ipv6_3 | normalize_ipaddr
|
||||
- networks_5.container.NetworkSettings.Networks[nname_3].IPAddress == nname_3_ipv4_3
|
||||
- networks_5.container.NetworkSettings.Networks[nname_3].GlobalIPv6Address | normalize_ipaddr == nname_3_ipv6_3 | normalize_ipaddr
|
||||
- networks_6 is changed
|
||||
- networks_6.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv4Address == nname_3_ipv4_4
|
||||
- networks_6.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv6Address | normalize_ipaddr == nname_3_ipv6_3 | normalize_ipaddr
|
||||
- networks_6.container.NetworkSettings.Networks[nname_3].IPAddress == nname_3_ipv4_4
|
||||
- networks_6.container.NetworkSettings.Networks[nname_3].GlobalIPv6Address | normalize_ipaddr == nname_3_ipv6_3 | normalize_ipaddr
|
||||
- networks_7 is changed
|
||||
- networks_7.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv4Address == nname_3_ipv4_4
|
||||
- networks_7.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv6Address | normalize_ipaddr == nname_3_ipv6_4 | normalize_ipaddr
|
||||
- networks_7.container.NetworkSettings.Networks[nname_3].IPAddress == nname_3_ipv4_4
|
||||
- networks_7.container.NetworkSettings.Networks[nname_3].GlobalIPv6Address | normalize_ipaddr == nname_3_ipv6_4 | normalize_ipaddr
|
||||
- networks_8 is not changed
|
||||
- networks_8.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv4Address == nname_3_ipv4_4
|
||||
- networks_8.container.NetworkSettings.Networks[nname_3].IPAMConfig.IPv6Address | normalize_ipaddr == nname_3_ipv6_4 | normalize_ipaddr
|
||||
- networks_8.container.NetworkSettings.Networks[nname_3].IPAddress == nname_3_ipv4_4
|
||||
- networks_8.container.NetworkSettings.Networks[nname_3].GlobalIPv6Address | normalize_ipaddr == nname_3_ipv6_4 | normalize_ipaddr
|
||||
|
||||
####################################################################
|
||||
####################################################################
|
||||
####################################################################
|
||||
|
||||
- name: Delete networks
|
||||
docker_network:
|
||||
name: "{{ network_name }}"
|
||||
state: absent
|
||||
force: true
|
||||
loop:
|
||||
- "{{ nname_1 }}"
|
||||
- "{{ nname_2 }}"
|
||||
- "{{ nname_3 }}"
|
||||
loop_control:
|
||||
loop_var: network_name
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,328 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cname: "{{ cname_prefix ~ '-options' }}"
|
||||
cname2: "{{ cname_prefix ~ '-options-h1' }}"
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [cname, cname2] }}"
|
||||
|
||||
####################################################################
|
||||
## published_ports: error handling #################################
|
||||
####################################################################
|
||||
|
||||
- name: published_ports -- non-closing square bracket
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
published_ports:
|
||||
- "[::1:2000:3000"
|
||||
register: published_ports_1
|
||||
ignore_errors: true
|
||||
|
||||
- name: published_ports -- forgot square brackets for IPv6
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
published_ports:
|
||||
- "::1:2000:3000"
|
||||
register: published_ports_2
|
||||
ignore_errors: true
|
||||
|
||||
- name: published_ports -- disallow hostnames
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
published_ports:
|
||||
- "foo:2000:3000"
|
||||
register: published_ports_3
|
||||
ignore_errors: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- published_ports_1 is failed
|
||||
- published_ports_1.msg == 'Cannot find closing "]" in input "[::1:2000:3000" for opening "[" at index 1!'
|
||||
- published_ports_2 is failed
|
||||
- published_ports_2.msg == 'Invalid port description "::1:2000:3000" - expected 1 to 3 colon-separated parts, but got 5. Maybe you forgot to use square brackets ([...]) around an IPv6 address?'
|
||||
- published_ports_3 is failed
|
||||
- "published_ports_3.msg == 'Bind addresses for published ports must be IPv4 or IPv6 addresses, not hostnames. Use the dig lookup to resolve hostnames. (Found hostname: foo)'"
|
||||
|
||||
####################################################################
|
||||
## published_ports: port range #####################################
|
||||
####################################################################
|
||||
|
||||
- name: published_ports -- port range
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
exposed_ports:
|
||||
- "9001"
|
||||
- "9010-9050"
|
||||
published_ports:
|
||||
- "9001:9001"
|
||||
- "9010-9050:9010-9050"
|
||||
force_kill: true
|
||||
register: published_ports_1
|
||||
|
||||
- name: published_ports -- port range (idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
exposed_ports:
|
||||
- "9001"
|
||||
- "9010-9050"
|
||||
published_ports:
|
||||
- "9001:9001"
|
||||
- "9010-9050:9010-9050"
|
||||
force_kill: true
|
||||
register: published_ports_2
|
||||
|
||||
- name: published_ports -- port range (different range)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
exposed_ports:
|
||||
- "9001"
|
||||
- "9010-9050"
|
||||
published_ports:
|
||||
- "9001:9001"
|
||||
- "9020-9060:9020-9060"
|
||||
force_kill: true
|
||||
register: published_ports_3
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- published_ports_1 is changed
|
||||
- published_ports_2 is not changed
|
||||
- published_ports_3 is changed
|
||||
|
||||
####################################################################
|
||||
## published_ports: one-element container port range ###############
|
||||
####################################################################
|
||||
|
||||
- name: published_ports -- one-element container port range
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ item }}"
|
||||
state: started
|
||||
published_ports:
|
||||
- "9010-9050:9010"
|
||||
force_kill: true
|
||||
loop:
|
||||
- '{{ cname }}'
|
||||
- '{{ cname2 }}'
|
||||
register: published_ports_1
|
||||
|
||||
- name: published_ports -- one-element container port range (idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ item }}"
|
||||
state: started
|
||||
published_ports:
|
||||
- "9010-9050:9010"
|
||||
force_kill: true
|
||||
loop:
|
||||
- '{{ cname }}'
|
||||
- '{{ cname2 }}'
|
||||
register: published_ports_2
|
||||
|
||||
- name: published_ports -- one-element container port range (different range)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ item }}"
|
||||
state: started
|
||||
published_ports:
|
||||
- "9010-9051:9010"
|
||||
force_kill: true
|
||||
loop:
|
||||
- '{{ cname }}'
|
||||
- '{{ cname2 }}'
|
||||
register: published_ports_3
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
loop:
|
||||
- '{{ cname }}'
|
||||
- '{{ cname2 }}'
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- published_ports_1 is changed
|
||||
- published_ports_2 is not changed
|
||||
- published_ports_3 is changed
|
||||
|
||||
####################################################################
|
||||
## published_ports: IPv6 addresses #################################
|
||||
####################################################################
|
||||
|
||||
- when: docker_host_info.host_info.ServerVersion is version('27.0.0', '<')
|
||||
block:
|
||||
- name: published_ports -- IPv6
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
published_ports:
|
||||
- "[::1]:9001:9001"
|
||||
force_kill: true
|
||||
register: published_ports_1
|
||||
|
||||
- name: published_ports -- IPv6 (idempotency)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
published_ports:
|
||||
- "[::1]:9001:9001"
|
||||
force_kill: true
|
||||
register: published_ports_2
|
||||
|
||||
- name: published_ports -- IPv6 (different IP)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
published_ports:
|
||||
- "127.0.0.1:9001:9001"
|
||||
force_kill: true
|
||||
register: published_ports_3
|
||||
|
||||
- name: published_ports -- IPv6 (hostname)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
published_ports:
|
||||
- "localhost:9001:9001"
|
||||
force_kill: true
|
||||
register: published_ports_4
|
||||
ignore_errors: true
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- published_ports_1 is changed
|
||||
- published_ports_2 is not changed
|
||||
- published_ports_3 is changed
|
||||
- published_ports_4 is failed
|
||||
|
||||
####################################################################
|
||||
## publish_all_ports ###############################################
|
||||
####################################################################
|
||||
|
||||
- set_fact:
|
||||
publish_all_ports_test_cases:
|
||||
- test_name: no_options
|
||||
changed: true
|
||||
- test_name: null_to_true
|
||||
publish_all_ports_value: true
|
||||
changed: true
|
||||
- test_name: true_idempotency
|
||||
publish_all_ports_value: true
|
||||
changed: false
|
||||
- test_name: true_to_null
|
||||
changed: false
|
||||
- test_name: null_to_true_2
|
||||
publish_all_ports_value: true
|
||||
changed: false
|
||||
- test_name: true_to_false
|
||||
publish_all_ports_value: false
|
||||
changed: true
|
||||
- test_name: false_idempotency
|
||||
publish_all_ports_value: false
|
||||
changed: false
|
||||
- test_name: false_to_null
|
||||
changed: false
|
||||
- test_name: null_with_published_ports
|
||||
published_ports_value: &ports
|
||||
- "9001:9001"
|
||||
- "9010-9050:9010-9050"
|
||||
changed: true
|
||||
- test_name: null_to_true_with_published_ports
|
||||
publish_all_ports_value: true
|
||||
published_ports_value: *ports
|
||||
changed: true
|
||||
- test_name: true_idempotency_with_published_ports
|
||||
publish_all_ports_value: true
|
||||
published_ports_value: *ports
|
||||
changed: false
|
||||
- test_name: true_to_null_with_published_ports
|
||||
published_ports_value: *ports
|
||||
changed: false
|
||||
- test_name: null_to_true_2_with_published_ports
|
||||
publish_all_ports_value: true
|
||||
published_ports_value: *ports
|
||||
changed: false
|
||||
- test_name: true_to_false_with_published_ports
|
||||
publish_all_ports_value: false
|
||||
published_ports_value: *ports
|
||||
changed: true
|
||||
- test_name: false_idempotency_with_published_ports
|
||||
publish_all_ports_value: false
|
||||
published_ports_value: *ports
|
||||
changed: false
|
||||
- test_name: false_to_null_with_published_ports
|
||||
published_ports_value: *ports
|
||||
changed: false
|
||||
|
||||
- name: publish_all_ports ({{ test_case.test_name }})
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
publish_all_ports: "{{ test_case.publish_all_ports_value | default(omit) }}"
|
||||
published_ports: "{{ test_case.published_ports_value | default(omit) }}"
|
||||
force_kill: true
|
||||
register: publish_all_ports
|
||||
loop_control:
|
||||
loop_var: test_case
|
||||
loop: "{{ publish_all_ports_test_cases }}"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- publish_all_ports.results[index].changed == test_case.changed
|
||||
loop: "{{ publish_all_ports_test_cases }}"
|
||||
loop_control:
|
||||
index_var: index
|
||||
loop_var: test_case
|
@ -0,0 +1,38 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Regression test for https://github.com/ansible/ansible/pull/45700
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cname: "{{ cname_prefix ~ '-45700' }}"
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [cname] }}"
|
||||
|
||||
- name: Start container
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
|
||||
- name: Stop container with a lot of invalid options
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
force_kill: true
|
||||
# Some options with "invalid" values, which would
|
||||
# have to be parsed. The values are "invalid" because
|
||||
# the containers and networks listed here do not exist.
|
||||
# This can happen because the networks are removed
|
||||
# before the container is stopped (see
|
||||
# https://github.com/ansible/ansible/issues/45486).
|
||||
networks:
|
||||
- name: "nonexistant-network-{{ (2**32) | random }}"
|
||||
published_ports:
|
||||
- '1:2'
|
||||
- '3'
|
||||
links:
|
||||
- "nonexistant-container-{{ (2**32) | random }}:test"
|
||||
state: absent
|
@ -0,0 +1,459 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cname: "{{ cname_prefix ~ '-hi' }}"
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [cname] }}"
|
||||
|
||||
####################################################################
|
||||
## Creation ########################################################
|
||||
####################################################################
|
||||
|
||||
- name: Create container (check)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
check_mode: true
|
||||
register: create_1
|
||||
|
||||
- name: Create container
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
register: create_2
|
||||
|
||||
- name: Create container (idempotent)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
register: create_3
|
||||
|
||||
- name: Create container (idempotent check)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
check_mode: true
|
||||
register: create_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_1 is changed
|
||||
- create_2 is changed
|
||||
- create_3 is not changed
|
||||
- create_4 is not changed
|
||||
|
||||
####################################################################
|
||||
## Starting (after creation) #######################################
|
||||
####################################################################
|
||||
|
||||
- name: Start container (check)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
check_mode: true
|
||||
register: start_1
|
||||
|
||||
- name: Start container
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
register: start_2
|
||||
|
||||
- name: Start container (idempotent)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
register: start_3
|
||||
|
||||
- name: Start container (idempotent check)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
check_mode: true
|
||||
register: start_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- start_1 is changed
|
||||
- start_2 is changed
|
||||
- start_3 is not changed
|
||||
- start_4 is not changed
|
||||
|
||||
####################################################################
|
||||
## Present check for running container #############################
|
||||
####################################################################
|
||||
|
||||
- name: Present check for running container (check)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
check_mode: true
|
||||
register: present_check_1
|
||||
|
||||
- name: Present check for running container
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
register: present_check_2
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- present_check_1 is not changed
|
||||
- present_check_2 is not changed
|
||||
|
||||
####################################################################
|
||||
## Starting (from scratch) #########################################
|
||||
####################################################################
|
||||
|
||||
- name: Remove container (setup for starting from scratch)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
|
||||
- name: Start container from scratch (check)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
stop_timeout: 1
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
check_mode: true
|
||||
register: start_scratch_1
|
||||
|
||||
- name: Start container from scratch
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
stop_timeout: 1
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
register: start_scratch_2
|
||||
|
||||
- name: Start container from scratch (idempotent)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
stop_timeout: 1
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
register: start_scratch_3
|
||||
|
||||
- name: Start container from scratch (idempotent check)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
stop_timeout: 1
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
check_mode: true
|
||||
register: start_scratch_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- start_scratch_1 is changed
|
||||
- start_scratch_2 is changed
|
||||
- start_scratch_3 is not changed
|
||||
- start_scratch_4 is not changed
|
||||
|
||||
####################################################################
|
||||
## Recreating ######################################################
|
||||
####################################################################
|
||||
|
||||
- name: Recreating container (created)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
force_kill: true
|
||||
register: recreate_1
|
||||
|
||||
- name: Recreating container (created, recreate, check mode)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
recreate: true
|
||||
state: present
|
||||
force_kill: true
|
||||
register: recreate_2
|
||||
check_mode: true
|
||||
|
||||
- name: Recreating container (created, recreate)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
recreate: true
|
||||
state: present
|
||||
force_kill: true
|
||||
register: recreate_3
|
||||
|
||||
- name: Recreating container (started)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
force_kill: true
|
||||
register: recreate_4
|
||||
|
||||
- name: Recreating container (started, recreate, check mode)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
recreate: true
|
||||
removal_wait_timeout: 10
|
||||
state: started
|
||||
force_kill: true
|
||||
register: recreate_5
|
||||
check_mode: true
|
||||
|
||||
- name: Recreating container (started, recreate)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
recreate: true
|
||||
removal_wait_timeout: 10
|
||||
state: started
|
||||
force_kill: true
|
||||
register: recreate_6
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- debug: var=recreate_1
|
||||
- debug: var=recreate_3
|
||||
- debug: var=recreate_4
|
||||
- debug: var=recreate_6
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- recreate_2 is changed
|
||||
- recreate_3 is changed
|
||||
- recreate_4 is changed
|
||||
- recreate_5 is changed
|
||||
- recreate_6 is changed
|
||||
- recreate_1.container.Id == recreate_2.container.Id
|
||||
- recreate_1.container.Id != recreate_3.container.Id
|
||||
- recreate_3.container.Id == recreate_4.container.Id
|
||||
- recreate_4.container.Id == recreate_5.container.Id
|
||||
- recreate_4.container.Id != recreate_6.container.Id
|
||||
|
||||
####################################################################
|
||||
## Restarting ######################################################
|
||||
####################################################################
|
||||
|
||||
- name: Restarting
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
stop_timeout: 1
|
||||
volumes:
|
||||
- /tmp/tmp
|
||||
register: restart_1
|
||||
|
||||
- name: Restarting (restart, check mode)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
restart: true
|
||||
state: started
|
||||
stop_timeout: 1
|
||||
force_kill: true
|
||||
register: restart_2
|
||||
check_mode: true
|
||||
|
||||
- name: Restarting (restart)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
restart: true
|
||||
state: started
|
||||
stop_timeout: 1
|
||||
force_kill: true
|
||||
register: restart_3
|
||||
|
||||
- name: Restarting (verify volumes)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
stop_timeout: 1
|
||||
volumes:
|
||||
- /tmp/tmp
|
||||
register: restart_4
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- restart_1 is changed
|
||||
- restart_2 is changed
|
||||
- restart_3 is changed
|
||||
- restart_1.container.Id == restart_3.container.Id
|
||||
- restart_4 is not changed
|
||||
|
||||
####################################################################
|
||||
## Stopping ########################################################
|
||||
####################################################################
|
||||
|
||||
- name: Stop container (check)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
name: "{{ cname }}"
|
||||
state: stopped
|
||||
stop_timeout: 1
|
||||
check_mode: true
|
||||
register: stop_1
|
||||
|
||||
- name: Stop container
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
name: "{{ cname }}"
|
||||
state: stopped
|
||||
stop_timeout: 1
|
||||
register: stop_2
|
||||
|
||||
- name: Stop container (idempotent)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
name: "{{ cname }}"
|
||||
state: stopped
|
||||
stop_timeout: 1
|
||||
register: stop_3
|
||||
|
||||
- name: Stop container (idempotent check)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
name: "{{ cname }}"
|
||||
state: stopped
|
||||
stop_timeout: 1
|
||||
check_mode: true
|
||||
register: stop_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- stop_1 is changed
|
||||
- stop_2 is changed
|
||||
- stop_3 is not changed
|
||||
- stop_4 is not changed
|
||||
|
||||
####################################################################
|
||||
## Removing ########################################################
|
||||
####################################################################
|
||||
|
||||
- name: Remove container (check)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
check_mode: true
|
||||
register: remove_1
|
||||
|
||||
- name: Remove container
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
register: remove_2
|
||||
|
||||
- name: Remove container (idempotent)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
register: remove_3
|
||||
|
||||
- name: Remove container (idempotent check)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
check_mode: true
|
||||
register: remove_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- remove_1 is changed
|
||||
- remove_2 is changed
|
||||
- remove_3 is not changed
|
||||
- remove_4 is not changed
|
||||
|
||||
####################################################################
|
||||
## Removing (from running) #########################################
|
||||
####################################################################
|
||||
|
||||
- name: Start container (setup for removing from running)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
|
||||
- name: Remove container from running (check)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
check_mode: true
|
||||
register: remove_from_running_1
|
||||
|
||||
- name: Remove container from running
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
register: remove_from_running_2
|
||||
|
||||
- name: Remove container from running (idempotent)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
register: remove_from_running_3
|
||||
|
||||
- name: Remove container from running (idempotent check)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
check_mode: true
|
||||
register: remove_from_running_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- remove_from_running_1 is changed
|
||||
- remove_from_running_2 is changed
|
||||
- remove_from_running_3 is not changed
|
||||
- remove_from_running_4 is not changed
|
@ -0,0 +1,221 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cname: "{{ cname_prefix ~ '-update' }}"
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [cname] }}"
|
||||
|
||||
# We do not test cpuset_cpus and cpuset_mems since changing it fails if the system does
|
||||
# not have 'enough' CPUs. We do not test kernel_memory since it is deprecated and fails.
|
||||
|
||||
- set_fact:
|
||||
has_blkio_weight: true
|
||||
|
||||
- name: Create container
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
blkio_weight: "{{ 123 if has_blkio_weight else omit }}"
|
||||
cpu_period: 90000
|
||||
cpu_quota: 150000
|
||||
cpu_shares: 900
|
||||
memory: 64M
|
||||
memory_reservation: 64M
|
||||
memory_swap: 64M
|
||||
restart_policy: on-failure
|
||||
restart_retries: 5
|
||||
register: create
|
||||
ignore_errors: true
|
||||
|
||||
- when: create is failed
|
||||
block:
|
||||
- name: Make sure container is not there
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
|
||||
- when: "'setting cgroup config for procHooks process caused: failed to write' in create.msg and 'io.bfq.weight' in create.msg"
|
||||
set_fact:
|
||||
has_blkio_weight: false
|
||||
|
||||
- name: Create container again
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
blkio_weight: "{{ 123 if has_blkio_weight else omit }}"
|
||||
cpu_period: 90000
|
||||
cpu_quota: 150000
|
||||
cpu_shares: 900
|
||||
memory: 64M
|
||||
memory_reservation: 64M
|
||||
memory_swap: 64M
|
||||
restart_policy: on-failure
|
||||
restart_retries: 5
|
||||
register: create_2
|
||||
|
||||
- when: "'setting cgroup config for procHooks process caused: failed to write' in create.msg and 'io.bfq.weight' in create.msg"
|
||||
set_fact:
|
||||
create: "{{ create_2 }}"
|
||||
|
||||
- name: Update values
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
blkio_weight: "{{ 234 if has_blkio_weight else omit }}"
|
||||
cpu_period: 50000
|
||||
cpu_quota: 50000
|
||||
cpu_shares: 1100
|
||||
memory: 48M
|
||||
memory_reservation: 48M
|
||||
memory_swap: unlimited
|
||||
restart_policy: on-failure # only on-failure can have restart_retries, so don't change it here
|
||||
restart_retries: 2
|
||||
register: update
|
||||
diff: true
|
||||
|
||||
- name: Update values again
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
blkio_weight: "{{ 135 if has_blkio_weight else omit }}"
|
||||
cpu_period: 30000
|
||||
cpu_quota: 40000
|
||||
cpu_shares: 1000
|
||||
memory: 32M
|
||||
memory_reservation: 30M
|
||||
memory_swap: 128M
|
||||
restart_policy: always
|
||||
restart_retries: 0
|
||||
register: update2
|
||||
diff: true
|
||||
|
||||
- name: Recreate container
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 20m"' # this will force re-creation
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
blkio_weight: "{{ 234 if has_blkio_weight else omit }}"
|
||||
cpu_period: 50000
|
||||
cpu_quota: 50000
|
||||
cpu_shares: 1100
|
||||
memory: 48M
|
||||
memory_reservation: 48M
|
||||
memory_swap: unlimited
|
||||
restart_policy: on-failure
|
||||
restart_retries: 2
|
||||
force_kill: true
|
||||
register: recreate
|
||||
diff: true
|
||||
|
||||
- name: cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
diff: false
|
||||
|
||||
- name: Check general things
|
||||
assert:
|
||||
that:
|
||||
- create is changed
|
||||
- update is changed
|
||||
- update2 is changed
|
||||
- recreate is changed
|
||||
|
||||
# Make sure the container was *not* recreated when it should not be
|
||||
- create.container.Id == update.container.Id
|
||||
- create.container.Id == update2.container.Id
|
||||
|
||||
# Make sure that the container was recreated when it should be
|
||||
- create.container.Id != recreate.container.Id
|
||||
|
||||
- name: Check diff for first update
|
||||
assert:
|
||||
that:
|
||||
# blkio_weight sometimes cannot be set, then we end up with 0 instead of the value we had
|
||||
- >-
|
||||
not has_blkio_weight or update.diff.before.blkio_weight == 123 or ('Docker warning: Your kernel does not support Block I/O weight or the cgroup is not mounted. Weight discarded.' in (create.warnings | default([])))
|
||||
- not has_blkio_weight or update.diff.after.blkio_weight == 234
|
||||
- update.diff.before.cpu_period == 90000
|
||||
- update.diff.after.cpu_period == 50000
|
||||
- update.diff.before.cpu_quota == 150000
|
||||
- update.diff.after.cpu_quota == 50000
|
||||
- update.diff.before.cpu_shares == 900
|
||||
- update.diff.after.cpu_shares == 1100
|
||||
- update.diff.before.memory == 67108864
|
||||
- update.diff.after.memory == 50331648
|
||||
- update.diff.before.memory_reservation == 67108864
|
||||
- update.diff.after.memory_reservation == 50331648
|
||||
- >-
|
||||
(update.diff.before.memory_swap | default(0)) == 67108864 or ('Docker warning: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.' in (create.warnings | default([])))
|
||||
- >-
|
||||
(update.diff.after.memory_swap | default(0)) == -1 or ('Docker warning: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.' in (create.warnings | default([])))
|
||||
- "'restart_policy' not in update.diff.before"
|
||||
- update.diff.before.restart_retries == 5
|
||||
- update.diff.after.restart_retries == 2
|
||||
|
||||
- name: Check diff for second update
|
||||
assert:
|
||||
that:
|
||||
- >-
|
||||
not has_blkio_weight or update2.diff.before.blkio_weight == 234 or ('Docker warning: Your kernel does not support Block I/O weight or the cgroup is not mounted. Weight discarded.' in (create.warnings | default([])))
|
||||
- not has_blkio_weight or update2.diff.after.blkio_weight == 135
|
||||
- update2.diff.before.cpu_period == 50000
|
||||
- update2.diff.after.cpu_period == 30000
|
||||
- update2.diff.before.cpu_quota == 50000
|
||||
- update2.diff.after.cpu_quota == 40000
|
||||
- update2.diff.before.cpu_shares == 1100
|
||||
- update2.diff.after.cpu_shares == 1000
|
||||
- update2.diff.before.memory == 50331648
|
||||
- update2.diff.after.memory == 33554432
|
||||
- update2.diff.before.memory_reservation == 50331648
|
||||
- update2.diff.after.memory_reservation == 31457280
|
||||
- >-
|
||||
(update2.diff.before.memory_swap | default(0)) == -1 or ('Docker warning: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.' in (create.warnings | default([])))
|
||||
- >-
|
||||
(update2.diff.after.memory_swap | default(0)) == 134217728 or ('Docker warning: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.' in (create.warnings | default([])))
|
||||
- update2.diff.before.restart_policy == 'on-failure'
|
||||
- update2.diff.after.restart_policy == 'always'
|
||||
- update2.diff.before.restart_retries == 2
|
||||
- update2.diff.after.restart_retries == 0
|
||||
|
||||
- name: Check diff for recreation
|
||||
assert:
|
||||
that:
|
||||
- >-
|
||||
not has_blkio_weight or recreate.diff.before.blkio_weight == 135 or ('Docker warning: Your kernel does not support Block I/O weight or the cgroup is not mounted. Weight discarded.' in (create.warnings | default([])))
|
||||
- not has_blkio_weight or recreate.diff.after.blkio_weight == 234
|
||||
- recreate.diff.before.cpu_period == 30000
|
||||
- recreate.diff.after.cpu_period == 50000
|
||||
- recreate.diff.before.cpu_quota == 40000
|
||||
- recreate.diff.after.cpu_quota == 50000
|
||||
- recreate.diff.before.cpu_shares == 1000
|
||||
- recreate.diff.after.cpu_shares == 1100
|
||||
- recreate.diff.before.memory == 33554432
|
||||
- recreate.diff.after.memory == 50331648
|
||||
- recreate.diff.before.memory_reservation == 31457280
|
||||
- recreate.diff.after.memory_reservation == 50331648
|
||||
- >-
|
||||
(recreate.diff.before.memory_swap | default(0)) == 134217728 or ('Docker warning: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.' in (create.warnings | default([])))
|
||||
- >-
|
||||
(recreate.diff.after.memory_swap | default(0)) == -1 or ('Docker warning: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.' in (create.warnings | default([])))
|
||||
- recreate.diff.before.restart_policy == 'always'
|
||||
- recreate.diff.after.restart_policy == 'on-failure'
|
||||
- recreate.diff.before.restart_retries == 0
|
||||
- recreate.diff.after.restart_retries == 2
|
||||
- recreate.diff.before.command == ['/bin/sh', '-c', 'sleep 10m']
|
||||
- recreate.diff.after.command == ['/bin/sh', '-c', 'sleep 20m']
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/4
|
||||
destructive
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker
|
||||
- setup_docker_python_deps
|
||||
- setup_remote_tmp_dir
|
@ -0,0 +1,47 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- name: Gather facts on controller
|
||||
setup:
|
||||
gather_subset: '!all'
|
||||
delegate_to: localhost
|
||||
delegate_facts: true
|
||||
run_once: true
|
||||
|
||||
# Create random name prefix (for containers)
|
||||
- name: Create random container name prefix
|
||||
set_fact:
|
||||
cname_prefix: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
cnames: []
|
||||
|
||||
- debug:
|
||||
msg: "Using container name prefix {{ cname_prefix }}"
|
||||
|
||||
# Run the tests
|
||||
- block:
|
||||
- include_tasks: run-test.yml
|
||||
with_fileglob:
|
||||
- "tests/*.yml"
|
||||
loop_control:
|
||||
loop_var: test_name
|
||||
|
||||
always:
|
||||
- name: "Make sure all containers are removed"
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
with_items: "{{ cnames }}"
|
||||
diff: false
|
||||
|
||||
when: docker_api_version is version('1.25', '>=')
|
||||
|
||||
- fail: msg="Too old Docker API version to run all docker_container_copy_into tests!"
|
||||
when: not(docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: "Loading tasks from {{ test_name }}"
|
||||
include_tasks: "{{ test_name }}"
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/4
|
||||
destructive
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker
|
||||
- setup_docker_python_deps
|
@ -0,0 +1,228 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- block:
|
||||
- name: Create random container name
|
||||
set_fact:
|
||||
cname: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
|
||||
- name: Make sure container is not there
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
|
||||
- name: Execute in a non-present container
|
||||
docker_container_exec:
|
||||
container: "{{ cname }}"
|
||||
command: "/bin/bash -c 'ls -a'"
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is failed
|
||||
- "'Could not find container' in result.msg"
|
||||
|
||||
- name: Make sure container exists
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
state: started
|
||||
force_kill: true
|
||||
|
||||
- name: Execute in a present container (command)
|
||||
docker_container_exec:
|
||||
container: "{{ cname }}"
|
||||
command: "/bin/sh -c 'ls -a'"
|
||||
register: result_cmd
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result_cmd.rc == 0
|
||||
- "'stdout' in result_cmd"
|
||||
- "'stdout_lines' in result_cmd"
|
||||
- "'stderr' in result_cmd"
|
||||
- "'stderr_lines' in result_cmd"
|
||||
|
||||
- name: Execute in a present container (argv)
|
||||
docker_container_exec:
|
||||
container: "{{ cname }}"
|
||||
argv:
|
||||
- /bin/sh
|
||||
- '-c'
|
||||
- ls -a
|
||||
register: result_argv
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result_argv.rc == 0
|
||||
- "'stdout' in result_argv"
|
||||
- "'stdout_lines' in result_argv"
|
||||
- "'stderr' in result_argv"
|
||||
- "'stderr_lines' in result_argv"
|
||||
- result_cmd.stdout == result_argv.stdout
|
||||
|
||||
- name: Execute in a present container (cat without stdin)
|
||||
docker_container_exec:
|
||||
container: "{{ cname }}"
|
||||
argv:
|
||||
- /bin/sh
|
||||
- '-c'
|
||||
- cat
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rc == 0
|
||||
- result.stdout == ''
|
||||
- result.stdout_lines == []
|
||||
- result.stderr == ''
|
||||
- result.stderr_lines == []
|
||||
|
||||
- name: Execute in a present container (cat with stdin)
|
||||
docker_container_exec:
|
||||
container: "{{ cname }}"
|
||||
argv:
|
||||
- /bin/sh
|
||||
- '-c'
|
||||
- cat
|
||||
stdin: Hello world!
|
||||
strip_empty_ends: false
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rc == 0
|
||||
- result.stdout == 'Hello world!\n'
|
||||
- result.stdout_lines == ['Hello world!']
|
||||
- result.stderr == ''
|
||||
- result.stderr_lines == []
|
||||
|
||||
- name: Execute in a present container (cat with stdin, no newline)
|
||||
docker_container_exec:
|
||||
container: "{{ cname }}"
|
||||
argv:
|
||||
- /bin/sh
|
||||
- '-c'
|
||||
- cat
|
||||
stdin: Hello world!
|
||||
stdin_add_newline: false
|
||||
strip_empty_ends: false
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rc == 0
|
||||
- result.stdout == 'Hello world!'
|
||||
- result.stdout_lines == ['Hello world!']
|
||||
- result.stderr == ''
|
||||
- result.stderr_lines == []
|
||||
|
||||
- name: Execute in a present container (cat with stdin, newline but stripping)
|
||||
docker_container_exec:
|
||||
container: "{{ cname }}"
|
||||
argv:
|
||||
- /bin/sh
|
||||
- '-c'
|
||||
- cat
|
||||
stdin: Hello world!
|
||||
stdin_add_newline: true
|
||||
strip_empty_ends: true
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rc == 0
|
||||
- result.stdout == 'Hello world!'
|
||||
- result.stdout_lines == ['Hello world!']
|
||||
- result.stderr == ''
|
||||
- result.stderr_lines == []
|
||||
|
||||
- name: Prepare long string
|
||||
set_fact:
|
||||
very_long_string: "{{ 'something long ' * 10000 }}"
|
||||
very_long_string2: "{{ 'something else ' * 5000 }}"
|
||||
|
||||
- name: Execute in a present container (long stdin)
|
||||
docker_container_exec:
|
||||
container: "{{ cname }}"
|
||||
argv:
|
||||
- /bin/sh
|
||||
- '-c'
|
||||
- cat
|
||||
stdin: |-
|
||||
{{ very_long_string }}
|
||||
{{ very_long_string2 }}
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.rc == 0
|
||||
- result.stdout == (very_long_string ~ '\n' ~ very_long_string2)
|
||||
- result.stdout_lines == [very_long_string, very_long_string2]
|
||||
- result.stderr == ''
|
||||
- result.stderr_lines == []
|
||||
- "'exec_id' not in result"
|
||||
|
||||
- name: Execute in a present container (detached)
|
||||
docker_container_exec:
|
||||
container: "{{ cname }}"
|
||||
argv:
|
||||
- /bin/sh
|
||||
- '-c'
|
||||
- sleep 1m
|
||||
detach: true
|
||||
register: result
|
||||
|
||||
- debug: var=result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- "'rc' not in result"
|
||||
- "'stdout' not in result"
|
||||
- "'stderr' not in result"
|
||||
- result.exec_id is string
|
||||
|
||||
- name: Execute in a present container (environment variable)
|
||||
docker_container_exec:
|
||||
container: "{{ cname }}"
|
||||
argv:
|
||||
- /bin/sh
|
||||
- '-c'
|
||||
- 'echo "$FOO" ; echo $FOO > /dev/stderr'
|
||||
env:
|
||||
FOO: |-
|
||||
bar
|
||||
baz
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rc == 0
|
||||
- result.stdout == 'bar\nbaz'
|
||||
- result.stdout_lines == ['bar', 'baz']
|
||||
- result.stderr == 'bar baz'
|
||||
- result.stderr_lines == ['bar baz']
|
||||
|
||||
always:
|
||||
- name: Cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
|
||||
when: docker_api_version is version('1.25', '>=')
|
||||
|
||||
- fail: msg="Too old docker / docker-py version to run docker_container_exec tests!"
|
||||
when: not(docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/5
|
||||
destructive
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker
|
||||
- setup_docker_python_deps
|
@ -0,0 +1,84 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- block:
|
||||
- name: Create random container name
|
||||
set_fact:
|
||||
cname: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
|
||||
- name: Make sure container is not there
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
|
||||
- name: Inspect a non-present container
|
||||
docker_container_info:
|
||||
name: "{{ cname }}"
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "not result.exists"
|
||||
- "'container' in result"
|
||||
- "result.container is none"
|
||||
|
||||
- name: Make sure container exists
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
state: started
|
||||
force_kill: true
|
||||
|
||||
- name: Inspect a present container
|
||||
docker_container_info:
|
||||
name: "{{ cname }}"
|
||||
register: result
|
||||
- name: Dump docker_container_info result
|
||||
debug: var=result
|
||||
|
||||
- name: "Comparison: use 'docker inspect'"
|
||||
command: docker inspect "{{ cname }}"
|
||||
register: docker_inspect
|
||||
ignore_errors: true
|
||||
- block:
|
||||
- set_fact:
|
||||
docker_inspect_result: "{{ docker_inspect.stdout | from_json }}"
|
||||
- name: Dump docker inspect result
|
||||
debug: var=docker_inspect_result
|
||||
when: docker_inspect is not failed
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.exists
|
||||
- "'container' in result"
|
||||
- "result.container is truthy"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.container == docker_inspect_result[0]"
|
||||
when: docker_inspect is not failed
|
||||
- assert:
|
||||
that:
|
||||
- "'is too new. Maximum supported API version is' in docker_inspect.stderr"
|
||||
when: docker_inspect is failed
|
||||
|
||||
always:
|
||||
- name: Cleanup
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
|
||||
when: docker_api_version is version('1.25', '>=')
|
||||
|
||||
- fail: msg="Too old docker / docker-py version to run docker_container_info tests!"
|
||||
when: not(docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/5
|
||||
destructive
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker
|
||||
- setup_docker_python_deps
|
||||
- setup_podman
|
@ -0,0 +1,40 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
# Create random name prefix (for containers, networks, ...)
|
||||
- name: Create random container name prefix
|
||||
set_fact:
|
||||
cname_prefix: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
cnames: []
|
||||
|
||||
- debug:
|
||||
msg: "Using container name prefix {{ cname_prefix }}"
|
||||
|
||||
# Run the tests
|
||||
- block:
|
||||
- include_tasks: run-test.yml
|
||||
with_fileglob:
|
||||
- "tests/*.yml"
|
||||
loop_control:
|
||||
loop_var: test_name
|
||||
|
||||
always:
|
||||
- name: "Make sure all containers are removed"
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
with_items: "{{ cnames }}"
|
||||
diff: false
|
||||
|
||||
when: docker_api_version is version('1.25', '>=')
|
||||
|
||||
- fail: msg="Too old docker / docker-py version to run all docker_container tests!"
|
||||
when: not(docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: "Loading tasks from {{ test_name }}"
|
||||
include_tasks: "{{ test_name }}"
|
@ -0,0 +1,121 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cname: "{{ cname_prefix ~ '-hi' }}"
|
||||
- name: Registering container name
|
||||
set_fact:
|
||||
cnames: "{{ cnames + [cname] }}"
|
||||
|
||||
- name: Get current context
|
||||
community.docker.docker_context_info:
|
||||
only_current: true
|
||||
register: docker_current_context
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- docker_current_context is not changed
|
||||
# Some of the following tests will not be true on all machines, but they should be in CI:
|
||||
- docker_current_context.current_context_name == 'default'
|
||||
- docker_current_context.contexts | length == 1
|
||||
- docker_current_context.contexts[0].name == 'default'
|
||||
- docker_current_context.contexts[0].current == true
|
||||
- docker_current_context.contexts[0].description == 'Current DOCKER_HOST based configuration'
|
||||
- docker_current_context.contexts[0].meta_path is none
|
||||
- docker_current_context.contexts[0].tls_path is none
|
||||
- docker_current_context.contexts[0].config.docker_host == 'unix:///var/run/docker.sock'
|
||||
- docker_current_context.contexts[0].config.tls == false
|
||||
|
||||
- name: Run community.docker modules with current context
|
||||
module_defaults:
|
||||
group/community.docker.docker: "{{ docker_current_context.contexts[0].config }}"
|
||||
block:
|
||||
- name: Create container
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
register: create_1
|
||||
|
||||
- name: Create container (idempotent)
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
state: present
|
||||
register: create_2
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_1 is changed
|
||||
- create_2 is not changed
|
||||
|
||||
- name: Inspect container with CLI tool
|
||||
ansible.builtin.command:
|
||||
cmd: docker inspect {{ cname }}
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- (result.stdout | from_json) | length == 1
|
||||
- (result.stdout | from_json)[0].State.Status == "created"
|
||||
|
||||
- name: Start container
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
register: start_1
|
||||
|
||||
- name: Start container (idempotent)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: started
|
||||
register: start_2
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- start_1 is changed
|
||||
- start_2 is not changed
|
||||
|
||||
- name: Inspect container with CLI tool
|
||||
ansible.builtin.command:
|
||||
cmd: docker inspect {{ cname }}
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- (result.stdout | from_json) | length == 1
|
||||
- (result.stdout | from_json)[0].State.Status == "running"
|
||||
|
||||
- name: Remove container
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
register: remove_1
|
||||
|
||||
- name: Remove container (idempotent)
|
||||
docker_container:
|
||||
name: "{{ cname }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
register: remove_2
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- remove_1 is changed
|
||||
- remove_2 is not changed
|
||||
|
||||
- name: Inspect container with CLI tool
|
||||
ansible.builtin.command:
|
||||
cmd: docker inspect {{ cname }}
|
||||
register: result
|
||||
failed_when: result.rc != 1
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- (result.stdout | from_json) | length == 0
|
@ -0,0 +1,49 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- when: podman_cli_version is version('1.0.0', '>=')
|
||||
block:
|
||||
# The setup_podman role created a 'podman' context that we can use here.
|
||||
|
||||
- name: Get all contexts
|
||||
community.docker.docker_context_info:
|
||||
register: docker_contexts
|
||||
|
||||
- name: Ensure that there are at least two contexts
|
||||
assert:
|
||||
that:
|
||||
- docker_contexts.contexts | length >= 2
|
||||
|
||||
- name: Get Podman context
|
||||
community.docker.docker_context_info:
|
||||
name: podman
|
||||
register: docker_podman_context
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- docker_podman_context.contexts | length == 1
|
||||
- docker_podman_context.contexts[0].name == 'podman'
|
||||
- docker_podman_context.contexts[0].current == false
|
||||
- docker_podman_context.contexts[0].description == 'Podman'
|
||||
- docker_podman_context.contexts[0].meta_path is string
|
||||
- docker_podman_context.contexts[0].tls_path is string
|
||||
- docker_podman_context.contexts[0].config.docker_host is string
|
||||
- docker_podman_context.contexts[0].config.tls == false
|
||||
|
||||
- name: Run basic test with Podman context
|
||||
module_defaults:
|
||||
group/community.docker.docker: "{{ docker_podman_context.contexts[0].config }}"
|
||||
block:
|
||||
|
||||
- name: Get info on Podman host
|
||||
docker_host_info:
|
||||
register: output
|
||||
|
||||
- name: Check for some Podman specific values
|
||||
assert:
|
||||
that:
|
||||
- output.host_info.ProductLicense == 'Apache-2.0'
|
||||
- >-
|
||||
"Rootless" in output.host_info
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/4
|
||||
destructive
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker
|
||||
- setup_docker_python_deps
|
||||
- setup_podman
|
@ -0,0 +1,38 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- include_tasks: test_host_info.yml
|
||||
when: docker_api_version is version('1.25', '>=')
|
||||
|
||||
- fail: msg="Too old docker / docker-py version to run docker_host_info tests!"
|
||||
when: not(docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)
|
||||
|
||||
- when: podman_cli_version is version('1.0.0', '>=')
|
||||
block:
|
||||
- name: Get Podman context
|
||||
community.docker.docker_context_info:
|
||||
name: podman
|
||||
register: docker_podman_context
|
||||
|
||||
- name: Run tests with Podman context
|
||||
module_defaults:
|
||||
group/community.docker.docker: "{{ docker_podman_context.contexts[0].config }}"
|
||||
block:
|
||||
|
||||
- name: Get info on Podman host
|
||||
docker_host_info:
|
||||
register: output
|
||||
|
||||
- name: Check for some Podman specific values
|
||||
assert:
|
||||
that:
|
||||
- output.host_info.ProductLicense == 'Apache-2.0'
|
||||
- >-
|
||||
"Rootless" in output.host_info
|
@ -0,0 +1,391 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Create random container/volume name
|
||||
set_fact:
|
||||
cname: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
cname2: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
vname: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
|
||||
- debug:
|
||||
msg: "Using container names '{{ cname }}' and '{{ cname2 }}', and volume name '{{ vname }}'"
|
||||
|
||||
- block:
|
||||
- name: Get info on Docker host
|
||||
docker_host_info:
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running
|
||||
assert:
|
||||
that:
|
||||
- output.host_info.Name is string
|
||||
- output.containers is not defined
|
||||
- output.networks is not defined
|
||||
- output.volumes is not defined
|
||||
- output.images is not defined
|
||||
- output.disk_usage is not defined
|
||||
- output.can_talk_to_docker is true
|
||||
|
||||
- block:
|
||||
- name: Get info on Docker host with invalid api_version
|
||||
docker_host_info:
|
||||
api_version: 1.999.999
|
||||
register: output
|
||||
ignore_errors: true
|
||||
|
||||
- name: assert can_talk_is_docker is false
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.can_talk_to_docker is false
|
||||
|
||||
- block:
|
||||
- name: Get info on Docker host with invalid docker_host
|
||||
docker_host_info:
|
||||
docker_host: tcp://127.0.0.1:80
|
||||
register: output
|
||||
ignore_errors: true
|
||||
|
||||
- name: assert can_talk_is_docker is false
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.can_talk_to_docker is false
|
||||
|
||||
# Container and volume are created so that all lists are non-empty:
|
||||
# * container and volume lists are non-emtpy because of the created objects;
|
||||
# * image list is non-empty because the image of the container is there;
|
||||
# * network list is always non-empty (default networks).
|
||||
- name: Create running container
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
command: '/bin/sh -c "sleep 10m"'
|
||||
name: "{{ cname }}"
|
||||
labels:
|
||||
key1: value1
|
||||
key2: value2
|
||||
state: started
|
||||
register: container_output
|
||||
|
||||
- name: Create running container
|
||||
docker_container:
|
||||
image: "{{ docker_test_image_alpine }}"
|
||||
name: "{{ cname2 }}"
|
||||
labels:
|
||||
key2: value2
|
||||
key3: value3
|
||||
state: stopped
|
||||
register: container2_output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- container_output is changed
|
||||
- container2_output is changed
|
||||
|
||||
- name: Create a volume
|
||||
docker_volume:
|
||||
name: "{{ vname }}"
|
||||
register: volume_output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- volume_output is changed
|
||||
|
||||
- name: Get info on Docker host and list containers
|
||||
docker_host_info:
|
||||
containers: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running and list containers
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.networks is not defined'
|
||||
- 'output.volumes is not defined'
|
||||
- 'output.images is not defined'
|
||||
- 'output.disk_usage is not defined'
|
||||
- 'output.containers[0].Image is string'
|
||||
- 'output.containers[0].ImageID is not defined'
|
||||
|
||||
- name: Get info on Docker host and list containers matching filters (single label)
|
||||
docker_host_info:
|
||||
containers: true
|
||||
containers_filters:
|
||||
label: key1=value1
|
||||
register: output
|
||||
|
||||
- name: assert container is returned when filters are matched (single label)
|
||||
assert:
|
||||
that: "output.containers | length == 1"
|
||||
|
||||
- name: Get info on Docker host and list containers matching filters (multiple labels)
|
||||
docker_host_info:
|
||||
containers: true
|
||||
containers_filters:
|
||||
label:
|
||||
- key1=value1
|
||||
- key2=value2
|
||||
register: output
|
||||
|
||||
- name: assert container is returned when filters are matched (multiple labels)
|
||||
assert:
|
||||
that: "output.containers | length == 1"
|
||||
|
||||
- name: Get info on Docker host and do not list containers which do not match filters
|
||||
docker_host_info:
|
||||
containers: true
|
||||
containers_filters:
|
||||
label:
|
||||
- key1=value1
|
||||
- key2=value2
|
||||
- key3=value3
|
||||
register: output
|
||||
|
||||
- name: assert no container is returned when filters are not matched
|
||||
assert:
|
||||
that: "output.containers | length == 0"
|
||||
|
||||
- name: Get info on Docker host and list containers matching filters (single label, not all containers)
|
||||
docker_host_info:
|
||||
containers: true
|
||||
containers_all: false
|
||||
containers_filters:
|
||||
label: key2=value2
|
||||
register: output
|
||||
|
||||
- name: Get info on Docker host and list containers matching filters (single label, all containers)
|
||||
docker_host_info:
|
||||
containers: true
|
||||
containers_all: true
|
||||
containers_filters:
|
||||
label: key2=value2
|
||||
register: output_all
|
||||
|
||||
- name: assert one resp. two container is returned
|
||||
assert:
|
||||
that:
|
||||
- "output.containers | length == 1"
|
||||
- "output_all.containers | length == 2"
|
||||
|
||||
- name: Get info on Docker host and list containers with verbose output
|
||||
docker_host_info:
|
||||
containers: true
|
||||
verbose_output: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running and list containers with verbose output
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.networks is not defined'
|
||||
- 'output.volumes is not defined'
|
||||
- 'output.images is not defined'
|
||||
- 'output.disk_usage is not defined'
|
||||
- 'output.containers[0].Image is string'
|
||||
- 'output.containers[0].ImageID is string'
|
||||
|
||||
- name: Get info on Docker host and list images
|
||||
docker_host_info:
|
||||
images: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running and list images
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.containers is not defined'
|
||||
- 'output.networks is not defined'
|
||||
- 'output.volumes is not defined'
|
||||
- 'output.images[0].Id is string'
|
||||
- 'output.images[0].ParentId is not defined'
|
||||
- 'output.disk_usage is not defined'
|
||||
|
||||
- name: Get info on Docker host and list images with verbose output
|
||||
docker_host_info:
|
||||
images: true
|
||||
verbose_output: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running and list images with verbose output
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.containers is not defined'
|
||||
- 'output.networks is not defined'
|
||||
- 'output.volumes is not defined'
|
||||
- 'output.images[0].Id is string'
|
||||
- 'output.images[0].ParentId is string'
|
||||
- 'output.disk_usage is not defined'
|
||||
|
||||
- name: Get info on Docker host and list networks
|
||||
docker_host_info:
|
||||
networks: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running and list networks
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.containers is not defined'
|
||||
- 'output.networks[0].Id is string'
|
||||
- 'output.networks[0].Created is not defined'
|
||||
- 'output.volumes is not defined'
|
||||
- 'output.images is not defined'
|
||||
- 'output.disk_usage is not defined'
|
||||
|
||||
- name: Get info on Docker host and list networks with verbose output
|
||||
docker_host_info:
|
||||
networks: true
|
||||
verbose_output: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running and list networks with verbose output
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.containers is not defined'
|
||||
- 'output.networks[0].Id is string'
|
||||
- 'output.networks[0].Created is string'
|
||||
- 'output.volumes is not defined'
|
||||
- 'output.images is not defined'
|
||||
- 'output.disk_usage is not defined'
|
||||
|
||||
- name: Get info on Docker host and list volumes
|
||||
docker_host_info:
|
||||
volumes: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running and list volumes
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.containers is not defined'
|
||||
- 'output.networks is not defined'
|
||||
- 'output.volumes[0].Name is string'
|
||||
- 'output.volumes[0].Mountpoint is not defined'
|
||||
- 'output.images is not defined'
|
||||
- 'output.disk_usage is not defined'
|
||||
|
||||
- name: Get info on Docker host and list volumes with verbose output
|
||||
docker_host_info:
|
||||
volumes: true
|
||||
verbose_output: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running and list volumes with verbose output
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.containers is not defined'
|
||||
- 'output.networks is not defined'
|
||||
- 'output.volumes[0].Name is string'
|
||||
- 'output.volumes[0].Mountpoint is string'
|
||||
- 'output.images is not defined'
|
||||
- 'output.disk_usage is not defined'
|
||||
|
||||
- name: Get info on Docker host and get disk usage
|
||||
docker_host_info:
|
||||
disk_usage: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running and get disk usage
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.containers is not defined'
|
||||
- 'output.networks is not defined'
|
||||
- 'output.volumes is not defined'
|
||||
- 'output.images is not defined'
|
||||
- 'output.disk_usage.LayersSize is number'
|
||||
- 'output.disk_usage.Images is not defined'
|
||||
- 'output.disk_usage.Containers is not defined'
|
||||
- 'output.disk_usage.Volumes is not defined'
|
||||
|
||||
- name: Get info on Docker host and get disk usage with verbose output
|
||||
docker_host_info:
|
||||
disk_usage: true
|
||||
verbose_output: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running and get disk usage with verbose output
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.containers is not defined'
|
||||
- 'output.networks is not defined'
|
||||
- 'output.volumes is not defined'
|
||||
- 'output.images is not defined'
|
||||
- 'output.disk_usage.LayersSize is number'
|
||||
- 'output.disk_usage.Images is sequence'
|
||||
- 'output.disk_usage.Containers is sequence'
|
||||
- 'output.disk_usage.Volumes is sequence'
|
||||
|
||||
- name: Get info on Docker host, disk usage and get all lists together
|
||||
docker_host_info:
|
||||
volumes: true
|
||||
containers: true
|
||||
networks: true
|
||||
images: true
|
||||
disk_usage: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running, disk usage and get lists together
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.containers[0].Image is string'
|
||||
- 'output.containers[0].ImageID is not defined'
|
||||
- 'output.networks[0].Id is string'
|
||||
- 'output.networks[0].Created is not defined'
|
||||
- 'output.volumes[0].Name is string'
|
||||
- 'output.volumes[0].Mountpoint is not defined'
|
||||
- 'output.images[0].Id is string'
|
||||
- 'output.images[0].ParentId is not defined'
|
||||
- 'output.disk_usage.LayersSize is number'
|
||||
- 'output.disk_usage.Images is not defined'
|
||||
- 'output.disk_usage.Containers is not defined'
|
||||
- 'output.disk_usage.Volumes is not defined'
|
||||
|
||||
- name: Get info on Docker host, disk usage and get all lists together with verbose output
|
||||
docker_host_info:
|
||||
volumes: true
|
||||
containers: true
|
||||
networks: true
|
||||
images: true
|
||||
disk_usage: true
|
||||
verbose_output: true
|
||||
register: output
|
||||
|
||||
- name: assert reading docker host facts when docker is running and get disk usage with verbose output
|
||||
assert:
|
||||
that:
|
||||
- 'output.host_info.Name is string'
|
||||
- 'output.containers[0].Image is string'
|
||||
- 'output.containers[0].ImageID is string'
|
||||
- 'output.networks[0].Id is string'
|
||||
- 'output.networks[0].Created is string'
|
||||
- 'output.volumes[0].Name is string'
|
||||
- 'output.volumes[0].Mountpoint is string'
|
||||
- 'output.images[0].Id is string'
|
||||
- 'output.images[0].ParentId is string'
|
||||
- 'output.disk_usage.LayersSize is number'
|
||||
- 'output.disk_usage.Images is sequence'
|
||||
- 'output.disk_usage.Containers is sequence'
|
||||
- 'output.disk_usage.Volumes is sequence'
|
||||
|
||||
always:
|
||||
- name: Delete containers
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
loop:
|
||||
- "{{ cname }}"
|
||||
- "{{ cname2 }}"
|
||||
|
||||
- name: Delete volume
|
||||
docker_volume:
|
||||
name: "{{ vname }}"
|
||||
state: absent
|
@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/4
|
||||
destructive
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_docker_registry
|
||||
- setup_docker_python_deps
|
||||
- setup_remote_tmp_dir
|
@ -0,0 +1,13 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- when: ansible_facts.distribution ~ ansible_facts.distribution_major_version not in ['CentOS6', 'RedHat6']
|
||||
include_tasks:
|
||||
file: test.yml
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: "Loading tasks from {{ test_name }}"
|
||||
include_tasks: "{{ test_name }}"
|
@ -0,0 +1,56 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Create random name prefix
|
||||
set_fact:
|
||||
name_prefix: "{{ 'ansible-docker-test-%0x' % ((2**32) | random) }}"
|
||||
- name: Create image and container list
|
||||
set_fact:
|
||||
inames: []
|
||||
cnames: []
|
||||
|
||||
- debug:
|
||||
msg: "Using name prefix {{ name_prefix }}"
|
||||
|
||||
- name: Create files directory
|
||||
file:
|
||||
path: '{{ remote_tmp_dir }}/files'
|
||||
state: directory
|
||||
|
||||
- name: Template files
|
||||
template:
|
||||
src: '{{ item }}'
|
||||
dest: '{{ remote_tmp_dir }}/files/{{ item }}'
|
||||
loop:
|
||||
- ArgsDockerfile
|
||||
- Dockerfile
|
||||
- EtcHostsDockerfile
|
||||
- MyDockerfile
|
||||
- StagedDockerfile
|
||||
|
||||
- block:
|
||||
- include_tasks: run-test.yml
|
||||
with_fileglob:
|
||||
- "tests/*.yml"
|
||||
loop_control:
|
||||
loop_var: test_name
|
||||
|
||||
always:
|
||||
- name: "Make sure all images are removed"
|
||||
docker_image:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
with_items: "{{ inames }}"
|
||||
- name: "Make sure all containers are removed"
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
force_kill: true
|
||||
with_items: "{{ cnames }}"
|
||||
|
||||
when: docker_api_version is version('1.25', '>=')
|
||||
|
||||
- fail: msg="Too old docker / docker-py version to run docker_image tests!"
|
||||
when: not(docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)
|
@ -0,0 +1,139 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
## basic ###########################################################
|
||||
####################################################################
|
||||
|
||||
- name: Make sure image is not there
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
register: absent_1
|
||||
|
||||
- name: Make sure image is not there (idempotency)
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
state: absent
|
||||
register: absent_2
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- absent_2 is not changed
|
||||
|
||||
- name: Make sure image is there
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
state: present
|
||||
source: pull
|
||||
pull:
|
||||
platform: amd64
|
||||
register: present_1
|
||||
|
||||
- name: Make sure image is there (idempotent)
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
state: present
|
||||
source: pull
|
||||
pull:
|
||||
platform: amd64
|
||||
register: present_2
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- present_1 is changed
|
||||
- present_2 is not changed
|
||||
|
||||
- name: Make sure tag is not there
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world_base }}:alias"
|
||||
state: absent
|
||||
|
||||
- name: Tag image with alias
|
||||
docker_image:
|
||||
source: local
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
repository: "{{ docker_test_image_hello_world_base }}:alias"
|
||||
register: tag_1
|
||||
|
||||
- name: Tag image with alias (idempotent)
|
||||
docker_image:
|
||||
source: local
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
repository: "{{ docker_test_image_hello_world_base }}:alias"
|
||||
register: tag_2
|
||||
|
||||
- name: Tag image with alias (force, still idempotent)
|
||||
docker_image:
|
||||
source: local
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
repository: "{{ docker_test_image_hello_world_base }}:alias"
|
||||
force_tag: true
|
||||
register: tag_3
|
||||
|
||||
- name: Tag image with ID instead of name
|
||||
docker_image:
|
||||
source: local
|
||||
name: "{{ present_1.image.Id }}"
|
||||
repository: "{{ docker_test_image_hello_world_base }}:alias"
|
||||
register: tag_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- tag_1 is changed
|
||||
- tag_2 is not changed
|
||||
- tag_3 is not changed
|
||||
- tag_4 is not changed
|
||||
|
||||
- name: Cleanup alias tag
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world_base }}:alias"
|
||||
state: absent
|
||||
|
||||
- name: Tag image with ID instead of name (use ID for repository, must fail)
|
||||
docker_image:
|
||||
source: local
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
repository: "{{ present_1.image.Id }}"
|
||||
register: fail_1
|
||||
ignore_errors: true
|
||||
|
||||
- name: Push image with ID (must fail)
|
||||
docker_image:
|
||||
source: local
|
||||
name: "{{ present_1.image.Id }}"
|
||||
push: true
|
||||
register: fail_2
|
||||
ignore_errors: true
|
||||
|
||||
- name: Pull image ID (must fail)
|
||||
docker_image:
|
||||
source: pull
|
||||
name: "{{ present_1.image.Id }}"
|
||||
force_source: true
|
||||
register: fail_3
|
||||
ignore_errors: true
|
||||
|
||||
- name: Build image ID (must fail)
|
||||
docker_image:
|
||||
source: build
|
||||
name: "{{ present_1.image.Id }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
force_source: true
|
||||
register: fail_4
|
||||
ignore_errors: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- fail_1 is failed
|
||||
- "'`repository` must not be an image ID' in fail_1.msg"
|
||||
- fail_2 is failed
|
||||
- "'Cannot push an image by ID' in fail_2.msg"
|
||||
- fail_3 is failed
|
||||
- "'Image name must not be an image ID for source=pull' in fail_3.msg"
|
||||
- fail_4 is failed
|
||||
- "'Image name must not be an image ID for source=build' in fail_4.msg"
|
@ -0,0 +1,262 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering image name
|
||||
set_fact:
|
||||
iname: "{{ name_prefix ~ '-options' }}"
|
||||
|
||||
- name: Determining pushed image names
|
||||
set_fact:
|
||||
hello_world_image_base: "{{ registry_address | default('localhost') }}/test/hello-world"
|
||||
test_image_base: "{{ registry_address | default('localhost') }}/test/{{ iname }}"
|
||||
|
||||
- name: Registering image name
|
||||
set_fact:
|
||||
inames: "{{ inames + [iname, test_image_base ~ ':latest', test_image_base ~ ':other', hello_world_image_base ~ ':latest', hello_world_image_base ~ ':newtag', hello_world_image_base ~ ':newtag2'] }}"
|
||||
|
||||
####################################################################
|
||||
## interact with test registry #####################################
|
||||
####################################################################
|
||||
|
||||
- name: Run registry tests only when registry is present
|
||||
when: registry_address is defined
|
||||
block:
|
||||
- name: Make sure image is not there
|
||||
docker_image:
|
||||
name: "{{ hello_world_image_base }}:latest"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- name: Make sure we have {{ docker_test_image_hello_world }}
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
source: pull
|
||||
|
||||
- name: Push image to test registry
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
repository: "{{ hello_world_image_base }}:latest"
|
||||
push: true
|
||||
source: local
|
||||
register: push_1
|
||||
|
||||
- name: Push image to test registry (idempotent)
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
repository: "{{ hello_world_image_base }}:latest"
|
||||
push: true
|
||||
source: local
|
||||
register: push_2
|
||||
|
||||
- name: Push image to test registry (force, still idempotent)
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
repository: "{{ hello_world_image_base }}:latest"
|
||||
push: true
|
||||
source: local
|
||||
force_tag: true
|
||||
register: push_3
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- push_1 is changed
|
||||
- push_2 is not changed
|
||||
- push_3 is not changed
|
||||
|
||||
- name: Get facts of local image
|
||||
docker_image_info:
|
||||
name: "{{ hello_world_image_base }}:latest"
|
||||
register: facts_1
|
||||
|
||||
- name: Make sure image is not there
|
||||
docker_image:
|
||||
name: "{{ hello_world_image_base }}:latest"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- name: Get facts of local image (absent)
|
||||
docker_image_info:
|
||||
name: "{{ hello_world_image_base }}:latest"
|
||||
register: facts_2
|
||||
|
||||
- name: Pull image from test registry
|
||||
docker_image:
|
||||
name: "{{ hello_world_image_base }}:latest"
|
||||
state: present
|
||||
source: pull
|
||||
register: pull_1
|
||||
|
||||
- name: Pull image from test registry (idempotency)
|
||||
docker_image:
|
||||
name: "{{ hello_world_image_base }}:latest"
|
||||
state: present
|
||||
source: pull
|
||||
register: pull_2
|
||||
|
||||
- name: Get facts of local image (present)
|
||||
docker_image_info:
|
||||
name: "{{ hello_world_image_base }}:latest"
|
||||
register: facts_3
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- pull_1 is changed
|
||||
- pull_2 is not changed
|
||||
- facts_1.images | length == 1
|
||||
- facts_2.images | length == 0
|
||||
- facts_3.images | length == 1
|
||||
|
||||
- name: Pull image from test registry (with digest)
|
||||
docker_image:
|
||||
name: "{{ hello_world_image_base }}@{{ facts_3.images[0].RepoDigests[0] | regex_replace('.*@', '') }}"
|
||||
state: present
|
||||
source: pull
|
||||
force_source: true
|
||||
register: pull_digest
|
||||
|
||||
- name: Make sure that changed is still false
|
||||
assert:
|
||||
that:
|
||||
- pull_digest is not changed
|
||||
|
||||
- name: Tag different image with new tag
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_alpine_different }}"
|
||||
repository: "{{ hello_world_image_base }}:newtag"
|
||||
push: false
|
||||
source: pull
|
||||
|
||||
- name: Push different image with new tag
|
||||
docker_image:
|
||||
name: "{{ hello_world_image_base }}"
|
||||
repository: "{{ hello_world_image_base }}"
|
||||
tag: newtag
|
||||
push: true
|
||||
source: local
|
||||
register: push_1_different
|
||||
|
||||
- name: Push different image with new tag (idempotent)
|
||||
docker_image:
|
||||
name: "{{ hello_world_image_base }}"
|
||||
repository: "{{ hello_world_image_base }}"
|
||||
tag: newtag
|
||||
push: true
|
||||
source: local
|
||||
register: push_2_different
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- push_1_different is changed
|
||||
- push_2_different is not changed
|
||||
|
||||
- name: Tag same image with new tag
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_alpine_different }}"
|
||||
repository: "{{ hello_world_image_base }}:newtag2"
|
||||
push: false
|
||||
source: pull
|
||||
|
||||
- name: Push same image with new tag
|
||||
docker_image:
|
||||
name: "{{ hello_world_image_base }}"
|
||||
repository: "{{ hello_world_image_base }}"
|
||||
tag: newtag2
|
||||
push: true
|
||||
source: local
|
||||
register: push_1_same
|
||||
|
||||
- name: Push same image with new tag (idempotent)
|
||||
docker_image:
|
||||
name: "{{ hello_world_image_base }}"
|
||||
repository: "{{ hello_world_image_base }}"
|
||||
tag: newtag2
|
||||
push: true
|
||||
source: local
|
||||
register: push_2_same
|
||||
|
||||
- assert:
|
||||
that:
|
||||
# NOTE: This should be:
|
||||
# - push_1_same is changed
|
||||
# Unfortunately docker does *NOT* report whether the tag already existed or not.
|
||||
# Here are the logs returned by client.push() for both tasks (which are exactly the same):
|
||||
# push_1_same:
|
||||
# {"status": "The push refers to repository [localhost:32796/test/hello-world]"},
|
||||
# {"id": "3fc64803ca2d", "progressDetail": {}, "status": "Preparing"},
|
||||
# {"id": "3fc64803ca2d", "progressDetail": {}, "status": "Layer already exists"},
|
||||
# {"status": "newtag2: digest: sha256:92251458088c638061cda8fd8b403b76d661a4dc6b7ee71b6affcf1872557b2b size: 528"},
|
||||
# {"aux": {"Digest": "sha256:92251458088c638061cda8fd8b403b76d661a4dc6b7ee71b6affcf1872557b2b", "Size": 528, "Tag": "newtag2"}, "progressDetail": {}}
|
||||
# push_2_same:
|
||||
# {"status": "The push refers to repository [localhost:32796/test/hello-world]"},
|
||||
# {"id": "3fc64803ca2d", "progressDetail": {}, "status": "Preparing"},
|
||||
# {"id": "3fc64803ca2d", "progressDetail": {}, "status": "Layer already exists"},
|
||||
# {"status": "newtag2: digest: sha256:92251458088c638061cda8fd8b403b76d661a4dc6b7ee71b6affcf1872557b2b size: 528"},
|
||||
# {"aux": {"Digest": "sha256:92251458088c638061cda8fd8b403b76d661a4dc6b7ee71b6affcf1872557b2b", "Size": 528, "Tag": "newtag2"}, "progressDetail": {}}
|
||||
- push_1_same is not changed
|
||||
- push_2_same is not changed
|
||||
|
||||
####################################################################
|
||||
## repository ######################################################
|
||||
####################################################################
|
||||
|
||||
- name: Make sure image is not there
|
||||
docker_image:
|
||||
name: "{{ test_image_base }}:latest"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- name: repository
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
pull: false
|
||||
repository: "{{ test_image_base }}"
|
||||
source: build
|
||||
register: repository_1
|
||||
|
||||
- name: repository (idempotent)
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
repository: "{{ test_image_base }}"
|
||||
source: local
|
||||
register: repository_2
|
||||
|
||||
- name: repository, tag with ID
|
||||
docker_image:
|
||||
name: "{{ repository_1.image.Id }}"
|
||||
repository: "{{ test_image_base }}:other"
|
||||
source: local
|
||||
register: repository_3
|
||||
|
||||
- name: repository, tag with ID (idempotent)
|
||||
docker_image:
|
||||
name: "{{ repository_1.image.Id }}"
|
||||
repository: "{{ test_image_base }}:other"
|
||||
source: local
|
||||
force_tag: true
|
||||
register: repository_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- repository_1 is changed
|
||||
- repository_2 is not changed
|
||||
- repository_3 is changed
|
||||
- repository_4 is not changed
|
||||
|
||||
- name: Get facts of image
|
||||
docker_image_info:
|
||||
name: "{{ test_image_base }}:latest"
|
||||
register: facts_1
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ test_image_base }}:latest"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- facts_1.images | length == 1
|
@ -0,0 +1,504 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Registering image name
|
||||
set_fact:
|
||||
iname: "{{ name_prefix ~ '-options' }}"
|
||||
iname_1: "{{ name_prefix ~ '-options-1' }}"
|
||||
hello_world_alt: "{{ name_prefix }}-hello-world-alt:v1.2.3-foo"
|
||||
|
||||
- name: Registering image name
|
||||
set_fact:
|
||||
inames: "{{ inames + [iname, iname_1, hello_world_alt] }}"
|
||||
|
||||
####################################################################
|
||||
## build.args ######################################################
|
||||
####################################################################
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- name: buildargs
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
dockerfile: "ArgsDockerfile"
|
||||
args:
|
||||
IMAGE: "{{ docker_test_image_busybox }}"
|
||||
TEST1: val1
|
||||
TEST2: val2
|
||||
TEST3: "True"
|
||||
pull: false
|
||||
source: build
|
||||
register: buildargs_1
|
||||
ignore_errors: true
|
||||
|
||||
- name: buildargs (idempotency)
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
dockerfile: "ArgsDockerfile"
|
||||
args:
|
||||
IMAGE: "{{ docker_test_image_busybox }}"
|
||||
TEST1: val1
|
||||
TEST2: val2
|
||||
TEST3: "True"
|
||||
pull: false
|
||||
source: build
|
||||
register: buildargs_2
|
||||
ignore_errors: true
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- buildargs_1 is changed
|
||||
- buildargs_2 is not failed and buildargs_2 is not changed
|
||||
|
||||
####################################################################
|
||||
## build.container_limits ##########################################
|
||||
####################################################################
|
||||
|
||||
- name: container_limits (Failed due to min memory limit)
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
container_limits:
|
||||
memory: 4KB
|
||||
pull: false
|
||||
source: build
|
||||
ignore_errors: true
|
||||
register: container_limits_1
|
||||
|
||||
- name: container_limits
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
container_limits:
|
||||
memory: 7MB
|
||||
memswap: 8MB
|
||||
pull: false
|
||||
source: build
|
||||
register: container_limits_2
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
# It *sometimes* happens that the first task does not fail.
|
||||
# For now, we work around this by
|
||||
# a) requiring that if it fails, the message must
|
||||
# contain 'Minimum memory limit allowed is (4|6)MB', and
|
||||
# b) requiring that either the first task, or the second
|
||||
# task is changed, but not both.
|
||||
- "not container_limits_1 is failed or ('Minimum memory limit allowed is ') in container_limits_1.msg"
|
||||
- "container_limits_1 is changed or container_limits_2 is changed and not (container_limits_1 is changed and container_limits_2 is changed)"
|
||||
|
||||
####################################################################
|
||||
## build.dockerfile ################################################
|
||||
####################################################################
|
||||
|
||||
- name: dockerfile
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
dockerfile: "MyDockerfile"
|
||||
pull: false
|
||||
source: build
|
||||
register: dockerfile_1
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- dockerfile_1 is changed
|
||||
- "('FROM ' ~ docker_test_image_alpine) in dockerfile_1.stdout"
|
||||
- dockerfile_1['image']['Config']['WorkingDir'] == '/newdata'
|
||||
|
||||
####################################################################
|
||||
## build.platform ##################################################
|
||||
####################################################################
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- name: build.platform
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
platform: linux
|
||||
pull: false
|
||||
source: build
|
||||
register: platform_1
|
||||
ignore_errors: true
|
||||
|
||||
- name: build.platform (idempotency)
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
platform: linux
|
||||
pull: false
|
||||
source: build
|
||||
register: platform_2
|
||||
ignore_errors: true
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- platform_1 is changed
|
||||
- platform_2 is not failed and platform_2 is not changed
|
||||
|
||||
####################################################################
|
||||
## force ###########################################################
|
||||
####################################################################
|
||||
|
||||
- name: Build an image
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
pull: false
|
||||
source: build
|
||||
|
||||
- name: force (changed)
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
dockerfile: "MyDockerfile"
|
||||
pull: false
|
||||
source: build
|
||||
force_source: true
|
||||
register: force_1
|
||||
|
||||
- name: force (unchanged)
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
dockerfile: "MyDockerfile"
|
||||
pull: false
|
||||
source: build
|
||||
force_source: true
|
||||
register: force_2
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- force_1 is changed
|
||||
- force_2 is not changed
|
||||
|
||||
####################################################################
|
||||
## load path #######################################################
|
||||
####################################################################
|
||||
|
||||
- name: Archive image
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
archive_path: "{{ remote_tmp_dir }}/image.tar"
|
||||
source: pull
|
||||
register: archive_image
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- archive_image is changed
|
||||
|
||||
- name: Copy archive because we will mutate it but other tests need the original
|
||||
copy:
|
||||
remote_src: true
|
||||
src: "{{ remote_tmp_dir }}/image.tar"
|
||||
dest: "{{ remote_tmp_dir }}/image_mutated.tar"
|
||||
|
||||
- name: Archive image again (idempotent)
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
archive_path: "{{ remote_tmp_dir }}/image_mutated.tar"
|
||||
source: local
|
||||
register: archive_image_2
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- archive_image_2 is not changed
|
||||
|
||||
- name: Archive image 3rd time, should overwrite due to different id
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_alpine_different }}"
|
||||
archive_path: "{{ remote_tmp_dir }}/image_mutated.tar"
|
||||
source: pull
|
||||
register: archive_image_3
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- archive_image_3 is changed
|
||||
|
||||
- name: Reset archive
|
||||
copy:
|
||||
remote_src: true
|
||||
src: "{{ remote_tmp_dir }}/image.tar"
|
||||
dest: "{{ remote_tmp_dir }}/image_mutated.tar"
|
||||
|
||||
- name: Tag image with different name
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
repository: "{{ hello_world_alt }}"
|
||||
source: local
|
||||
|
||||
- name: Archive image 4th time, should overwrite due to different name even when ID is same
|
||||
docker_image:
|
||||
name: "{{ hello_world_alt }}"
|
||||
# Tagged as docker_test_image_hello_world but has same hash/id (before this task overwrites it)
|
||||
archive_path: "{{ remote_tmp_dir }}/image_mutated.tar"
|
||||
source: local
|
||||
register: archive_image_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- archive_image_4 is changed
|
||||
|
||||
# This is the test that needs the original, non-mutated archive
|
||||
- name: Archive image by ID
|
||||
docker_image:
|
||||
name: "{{ archive_image.image.Id }}"
|
||||
archive_path: "{{ remote_tmp_dir }}/image_id.tar"
|
||||
source: local
|
||||
register: archive_image_id
|
||||
|
||||
- name: Create invalid archive
|
||||
copy:
|
||||
dest: "{{ remote_tmp_dir }}/image-invalid.tar"
|
||||
content: "this is not a valid image"
|
||||
|
||||
- name: remove image
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- name: load image (changed)
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
load_path: "{{ remote_tmp_dir }}/image.tar"
|
||||
source: load
|
||||
register: load_image
|
||||
|
||||
- name: load image (idempotency)
|
||||
docker_image:
|
||||
name: "{{ docker_test_image_hello_world }}"
|
||||
load_path: "{{ remote_tmp_dir }}/image.tar"
|
||||
source: load
|
||||
register: load_image_1
|
||||
|
||||
- name: load image (wrong name)
|
||||
docker_image:
|
||||
name: foo:bar
|
||||
load_path: "{{ remote_tmp_dir }}/image.tar"
|
||||
source: load
|
||||
register: load_image_2
|
||||
ignore_errors: true
|
||||
|
||||
- name: load image (invalid image)
|
||||
docker_image:
|
||||
name: foo:bar
|
||||
load_path: "{{ remote_tmp_dir }}/image-invalid.tar"
|
||||
source: load
|
||||
register: load_image_3
|
||||
ignore_errors: true
|
||||
|
||||
- name: load image (ID, idempotency)
|
||||
docker_image:
|
||||
name: "{{ archive_image.image.Id }}"
|
||||
load_path: "{{ remote_tmp_dir }}/image_id.tar"
|
||||
source: load
|
||||
register: load_image_4
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- load_image is changed
|
||||
- archive_image['image']['Id'] == load_image['image']['Id']
|
||||
- load_image_1 is not changed
|
||||
- load_image_2 is failed
|
||||
- >-
|
||||
("The archive did not contain image 'foo:bar'. Instead, found '" ~ docker_test_image_hello_world ~ "'.") == load_image_2.msg
|
||||
- load_image_3 is failed
|
||||
- '"Detected no loaded images. Archive potentially corrupt?" == load_image_3.msg'
|
||||
- load_image_4 is not changed
|
||||
|
||||
####################################################################
|
||||
## build.path ######################################################
|
||||
####################################################################
|
||||
|
||||
- name: Build image
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
pull: false
|
||||
source: build
|
||||
register: path_1
|
||||
|
||||
- name: Build image (idempotency)
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
pull: false
|
||||
source: build
|
||||
register: path_2
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- path_1 is changed
|
||||
- path_2 is not changed
|
||||
|
||||
####################################################################
|
||||
## build.target ####################################################
|
||||
####################################################################
|
||||
|
||||
- name: Build multi-stage image
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
dockerfile: "StagedDockerfile"
|
||||
target: first
|
||||
pull: false
|
||||
source: build
|
||||
register: dockerfile_2
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- dockerfile_2 is changed
|
||||
- dockerfile_2.image.Config.WorkingDir == '/first'
|
||||
|
||||
####################################################################
|
||||
## build.etc_hosts #################################################
|
||||
####################################################################
|
||||
|
||||
- name: Build image with custom etc_hosts
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
dockerfile: "EtcHostsDockerfile"
|
||||
pull: false
|
||||
etc_hosts:
|
||||
some-custom-host: "127.0.0.1"
|
||||
source: build
|
||||
register: path_1
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- path_1 is changed
|
||||
|
||||
####################################################################
|
||||
## build.shm_size ##################################################
|
||||
####################################################################
|
||||
|
||||
- name: Build image with custom shm_size
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
dockerfile: "MyDockerfile"
|
||||
pull: false
|
||||
shm_size: 128MB
|
||||
source: build
|
||||
register: path_1
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- path_1 is changed
|
||||
|
||||
####################################################################
|
||||
## build.labels ####################################################
|
||||
####################################################################
|
||||
|
||||
- name: Build image with labels
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
build:
|
||||
path: "{{ remote_tmp_dir }}/files"
|
||||
dockerfile: "MyDockerfile"
|
||||
pull: false
|
||||
labels:
|
||||
FOO: BAR
|
||||
this is a label: this is the label's value
|
||||
source: build
|
||||
register: labels_1
|
||||
|
||||
- name: cleanup
|
||||
docker_image:
|
||||
name: "{{ iname }}"
|
||||
state: absent
|
||||
force_absent: true
|
||||
|
||||
- name: Show image information
|
||||
debug:
|
||||
var: labels_1.image
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- labels_1 is changed
|
||||
- labels_1.image.Config.Labels.FOO == 'BAR'
|
||||
- labels_1.image.Config.Labels["this is a label"] == "this is the label's value"
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user