summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/libvirt/tests
diff options
context:
space:
mode:
Diffstat (limited to 'ansible_collections/community/libvirt/tests')
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/aliases1
-rwxr-xr-xansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/runme.sh18
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/test_connection.inventory6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/aliases1
-rwxr-xr-xansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/runme.sh18
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/test_connection.inventory6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/aliases1
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/libvirt_lxc.yml2
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/libvirt_qemu.yml2
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/playbooks/test-inventory.yml7
-rwxr-xr-xansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/runme.sh13
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/aliases6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/files/foobar.xml9
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/tasks/main.yml90
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Debian.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Fedora-29.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-7.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-8.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-9.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-16.04.yml5
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-18.04.yml5
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-18.10.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/default.yml5
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/aliases6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/defaults/main.yml4
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/tasks/directory_based_pool.yml139
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/tasks/main.yml31
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/templates/test_pool.xml.j211
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/CentOS-7.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/CentOS-8.yml8
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Debian.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Fedora-34.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-7.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-8.yml9
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-9.yml9
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-18.04.yml5
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-18.10.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-20.04.yml6
-rw-r--r--ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/default.yml5
-rw-r--r--ansible_collections/community/libvirt/tests/sanity/ignore-2.10.txt10
-rw-r--r--ansible_collections/community/libvirt/tests/sanity/ignore-2.11.txt10
-rw-r--r--ansible_collections/community/libvirt/tests/sanity/ignore-2.12.txt2
-rw-r--r--ansible_collections/community/libvirt/tests/sanity/ignore-2.13.txt2
-rw-r--r--ansible_collections/community/libvirt/tests/sanity/ignore-2.14.txt2
-rw-r--r--ansible_collections/community/libvirt/tests/sanity/ignore-2.9.txt10
-rw-r--r--ansible_collections/community/libvirt/tests/unit/compat/__init__.py0
-rw-r--r--ansible_collections/community/libvirt/tests/unit/compat/builtins.py33
-rw-r--r--ansible_collections/community/libvirt/tests/unit/compat/mock.py122
-rw-r--r--ansible_collections/community/libvirt/tests/unit/compat/unittest.py38
-rw-r--r--ansible_collections/community/libvirt/tests/unit/mock/__init__.py0
-rw-r--r--ansible_collections/community/libvirt/tests/unit/mock/loader.py116
-rw-r--r--ansible_collections/community/libvirt/tests/unit/mock/path.py5
-rw-r--r--ansible_collections/community/libvirt/tests/unit/mock/procenv.py90
-rw-r--r--ansible_collections/community/libvirt/tests/unit/mock/vault_helper.py39
-rw-r--r--ansible_collections/community/libvirt/tests/unit/mock/yaml_helper.py121
-rw-r--r--ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/__init__.py0
-rw-r--r--ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/conftest.py69
-rw-r--r--ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/test_virt_net.py30
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/check_matrix.py122
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/cloud.sh19
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/freebsd.sh22
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/linux.sh18
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/osx.sh22
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/remote.sh22
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/rhel.sh22
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/sanity.sh7
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/shippable.sh206
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/timing.py16
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/timing.sh5
-rwxr-xr-xansible_collections/community/libvirt/tests/utils/shippable/units.sh14
70 files changed, 1688 insertions, 0 deletions
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/aliases b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/aliases
new file mode 100644
index 00000000..ad7ccf7a
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/aliases
@@ -0,0 +1 @@
+unsupported
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/runme.sh b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/runme.sh
new file mode 100755
index 00000000..d3976ff3
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/runme.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+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.
+
+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 \
+ "$@"
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/test_connection.inventory b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/test_connection.inventory
new file mode 100644
index 00000000..45e06058
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_lxc/test_connection.inventory
@@ -0,0 +1,6 @@
+[libvirt_lxc]
+libvirt_lxc-pipelining ansible_ssh_pipelining=true
+libvirt_lxc-no-pipelining ansible_ssh_pipelining=false
+[libvirt_lxc:vars]
+ansible_host=lv-ubuntu-wily-amd64
+ansible_connection=community.libvirt.libvirt_lxc
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/aliases b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/aliases
new file mode 100644
index 00000000..ad7ccf7a
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/aliases
@@ -0,0 +1 @@
+unsupported
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/runme.sh b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/runme.sh
new file mode 100755
index 00000000..d3976ff3
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/runme.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+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.
+
+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 \
+ "$@"
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/test_connection.inventory b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/test_connection.inventory
new file mode 100644
index 00000000..27bb6b2f
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/connection_libvirt_qemu/test_connection.inventory
@@ -0,0 +1,6 @@
+[libvirt]
+libvirt-pipelining ansible_ssh_pipelining=true
+libvirt-no-pipelining ansible_ssh_pipelining=false
+[libvirt:vars]
+ansible_host=lv-ubuntu-wily-amd64
+ansible_connection=community.libvirt.libvirt_qemu
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/aliases b/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/aliases
new file mode 100644
index 00000000..ad7ccf7a
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/aliases
@@ -0,0 +1 @@
+unsupported
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/libvirt_lxc.yml b/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/libvirt_lxc.yml
new file mode 100644
index 00000000..36b74a4e
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/libvirt_lxc.yml
@@ -0,0 +1,2 @@
+plugin: community.libvirt.libvirt
+uri: 'lxc:///'
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/libvirt_qemu.yml b/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/libvirt_qemu.yml
new file mode 100644
index 00000000..b3166424
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/libvirt_qemu.yml
@@ -0,0 +1,2 @@
+plugin: community.libvirt.libvirt
+uri: 'qemu:///system'
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/playbooks/test-inventory.yml b/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/playbooks/test-inventory.yml
new file mode 100644
index 00000000..00176d31
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/playbooks/test-inventory.yml
@@ -0,0 +1,7 @@
+---
+- name: Create servers and test libvirt inventory plugin
+ hosts: localhost
+ gather_facts: False
+ tasks:
+ - debug:
+ var: hostvars
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/runme.sh b/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/runme.sh
new file mode 100755
index 00000000..3ac65452
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/inventory_libvirt/runme.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Exit on errors, exit when accessing unset variables and print all commands
+set -eux
+
+# Testing qemu connection
+export ANSIBLE_INVENTORY="./libvirt_qemu.yml"
+ansible-playbook playbooks/test-inventory.yml "$@"
+
+
+# Testing lxc connection
+export ANSIBLE_INVENTORY="./libvirt_lxc.yml"
+ansible-playbook playbooks/test-inventory.yml "$@"
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/aliases b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/aliases
new file mode 100644
index 00000000..e2a1952c
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/aliases
@@ -0,0 +1,6 @@
+shippable/posix/group1
+skip/aix
+skip/freebsd
+skip/osx
+needs/privileged
+destructive
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/files/foobar.xml b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/files/foobar.xml
new file mode 100644
index 00000000..768e10ea
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/files/foobar.xml
@@ -0,0 +1,9 @@
+<network>
+ <name>foobar</name>
+ <forward mode='nat'/>
+ <ip address='192.168.125.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.125.2' end='192.168.125.254'/>
+ </dhcp>
+ </ip>
+</network>
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/tasks/main.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/tasks/main.yml
new file mode 100644
index 00000000..3ea55b58
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/tasks/main.yml
@@ -0,0 +1,90 @@
+---
+- include_vars: '{{ item }}'
+ with_first_found:
+ - "{{ ansible_distribution }}-{{ ansible_distribution_version}}.yml"
+ - "{{ ansible_distribution }}-{{ ansible_distribution_major_version}}.yml"
+ - "{{ ansible_distribution }}.yml"
+ - "default.yml"
+
+- block:
+ - name: Install libvirt packages
+ package:
+ name: "{{ virt_net_packages }}"
+
+ - name: Start libvirt
+ service:
+ name: libvirtd
+ state: started
+
+ - name: Define the foobar network
+ community.libvirt.virt_net:
+ command: define
+ name: foobar
+ xml: '{{ lookup("file", "foobar.xml") }}'
+
+ - name: Define the foobar network (again)
+ community.libvirt.virt_net:
+ command: define
+ name: foobar
+ xml: '{{ lookup("file", "foobar.xml") }}'
+ register: second_virt_net_define
+
+ - name: Start the foobar network
+ community.libvirt.virt_net:
+ command: start
+ name: foobar
+
+ - name: Start the foobar network (again)
+ community.libvirt.virt_net:
+ command: start
+ name: foobar
+ register: second_virt_net_start
+
+ - name: Get facts for the foobar network
+ community.libvirt.virt_net:
+ command: facts
+ name: foobar
+ register: virt_net_facts
+
+ - name: Destroy the foobar network
+ community.libvirt.virt_net:
+ command: destroy
+ name: foobar
+
+ - name: Undefine the foobar network
+ community.libvirt.virt_net:
+ command: undefine
+ name: foobar
+ register: second_virt_net_define
+
+ - name: Undefine the foobar network (again)
+ community.libvirt.virt_net:
+ command: undefine
+ name: foobar
+ register: second_virt_net_undefine
+
+ - name: Ensure the second calls return "unchanged"
+ assert:
+ that:
+ - "second_virt_net_start is not changed"
+ - "second_virt_net_define is not changed"
+ - "second_virt_net_undefine is not changed"
+
+ - name: List all the networks
+ community.libvirt.virt_net:
+ command: list_nets
+
+ - name: Get all the network facts
+ community.libvirt.virt_net:
+ command: facts
+
+ always:
+ - name: Stop libvirt
+ service:
+ name: libvirtd
+ state: stopped
+
+ - name: Remove only the libvirt packages
+ package:
+ name: "{{ virt_net_packages|select('match', '.*libvirt.*')|list }}"
+ state: absent
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Debian.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Debian.yml
new file mode 100644
index 00000000..7d06d77c
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Debian.yml
@@ -0,0 +1,6 @@
+---
+virt_net_packages:
+ - libvirt-daemon
+ - libvirt-daemon-system
+ - python-libvirt
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Fedora-29.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Fedora-29.yml
new file mode 100644
index 00000000..dcf754dc
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Fedora-29.yml
@@ -0,0 +1,6 @@
+---
+virt_net_packages:
+ - libvirt
+ - libvirt-daemon
+ - python3-libvirt
+ - python3-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-7.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-7.yml
new file mode 100644
index 00000000..263281fe
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-7.yml
@@ -0,0 +1,6 @@
+---
+virt_net_packages:
+ - libvirt
+ - libvirt-daemon
+ - libvirt-python
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-8.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-8.yml
new file mode 100644
index 00000000..dcf754dc
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-8.yml
@@ -0,0 +1,6 @@
+---
+virt_net_packages:
+ - libvirt
+ - libvirt-daemon
+ - python3-libvirt
+ - python3-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-9.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-9.yml
new file mode 100644
index 00000000..dcf754dc
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/RedHat-9.yml
@@ -0,0 +1,6 @@
+---
+virt_net_packages:
+ - libvirt
+ - libvirt-daemon
+ - python3-libvirt
+ - python3-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-16.04.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-16.04.yml
new file mode 100644
index 00000000..b9ad4aa6
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-16.04.yml
@@ -0,0 +1,5 @@
+---
+virt_net_packages:
+ - libvirt-daemon
+ - python-libvirt
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-18.04.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-18.04.yml
new file mode 100644
index 00000000..b9ad4aa6
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-18.04.yml
@@ -0,0 +1,5 @@
+---
+virt_net_packages:
+ - libvirt-daemon
+ - python-libvirt
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-18.10.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-18.10.yml
new file mode 100644
index 00000000..7d06d77c
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/Ubuntu-18.10.yml
@@ -0,0 +1,6 @@
+---
+virt_net_packages:
+ - libvirt-daemon
+ - libvirt-daemon-system
+ - python-libvirt
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/default.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/default.yml
new file mode 100644
index 00000000..b9ad4aa6
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_net/vars/default.yml
@@ -0,0 +1,5 @@
+---
+virt_net_packages:
+ - libvirt-daemon
+ - python-libvirt
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/aliases b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/aliases
new file mode 100644
index 00000000..e2a1952c
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/aliases
@@ -0,0 +1,6 @@
+shippable/posix/group1
+skip/aix
+skip/freebsd
+skip/osx
+needs/privileged
+destructive
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/defaults/main.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/defaults/main.yml
new file mode 100644
index 00000000..4a329bff
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/defaults/main.yml
@@ -0,0 +1,4 @@
+---
+pool_info:
+ name: test_pool
+ path: /tmp/test_pool
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/tasks/directory_based_pool.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/tasks/directory_based_pool.yml
new file mode 100644
index 00000000..0ec09d85
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/tasks/directory_based_pool.yml
@@ -0,0 +1,139 @@
+---
+#
+# Create working directory
+#
+
+- name: "Crean up working directory"
+ file:
+ path: /tmp/test_pool
+ state: absent
+
+- name: "Create working directory"
+ file:
+ path: /tmp/test_pool
+ mode: 0755
+ state: directory
+
+#
+# Define storage pool
+#
+- name: "Define {{ pool_info.name }} on check_mode(pre)"
+ community.libvirt.virt_pool:
+ state: present
+ name: "{{ pool_info.name }}"
+ xml: '{{ lookup("template", "test_pool.xml.j2") }}'
+ register: result_pre
+ check_mode: true
+
+- name: "Define {{ pool_info.name }}"
+ community.libvirt.virt_pool:
+ state: present
+ name: "{{ pool_info.name }}"
+ xml: '{{ lookup("template", "test_pool.xml.j2") }}'
+ register: result
+
+- name: "Define {{ pool_info.name }} on check_mode(post)"
+ community.libvirt.virt_pool:
+ state: present
+ name: "{{ pool_info.name }}"
+ xml: '{{ lookup("template", "test_pool.xml.j2") }}'
+ register: result_post
+ check_mode: true
+
+- name: "Ensure the {{ pool_info.name }} has been defined"
+ assert:
+ that:
+ - result_pre is changed
+ - result is changed
+ - result_post is not changed
+ - 'result.created == "{{ pool_info.name }}"'
+
+#
+# Activate storage pool
+#
+- name: "Activate {{ pool_info.name }} on check_mode(pre)"
+ community.libvirt.virt_pool:
+ state: active
+ name: "{{ pool_info.name }}"
+ register: result_pre
+ check_mode: true
+
+- name: "Activate {{ pool_info.name }}"
+ community.libvirt.virt_pool:
+ state: active
+ name: "{{ pool_info.name }}"
+ register: result
+
+- name: "Activate {{ pool_info.name }} on check_mode(post}"
+ community.libvirt.virt_pool:
+ state: active
+ name: "{{ pool_info.name }}"
+ register: result_post
+ check_mode: true
+
+- name: "Ensure the {{ pool_info.name }} has been active"
+ assert:
+ that:
+ - result_pre is changed
+ - result is changed and result.msg == 0
+ - result_post is not changed
+
+#
+# Deactivate storage pool
+#
+- name: "Dectivate {{ pool_info.name }} on check_mode(pre)"
+ community.libvirt.virt_pool:
+ state: inactive
+ name: "{{ pool_info.name }}"
+ register: result_pre
+ check_mode: true
+
+- name: "Dectivate {{ pool_info.name }}"
+ community.libvirt.virt_pool:
+ state: inactive
+ name: "{{ pool_info.name }}"
+ register: result
+
+- name: "Dectivate {{ pool_info.name }} on check_mode(post}"
+ community.libvirt.virt_pool:
+ state: inactive
+ name: "{{ pool_info.name }}"
+ register: result_post
+ check_mode: true
+
+- name: "Ensure the {{ pool_info.name }} has been inactive"
+ assert:
+ that:
+ - result_pre is changed
+ - result is changed and result.msg == 0
+ - result_post is not changed
+
+#
+# Undefine storage pool
+#
+- name: Delete "{{ pool_info.name }} on check_mode(pre)"
+ community.libvirt.virt_pool:
+ state: absent
+ name: "{{ pool_info.name }}"
+ register: result_pre
+ check_mode: true
+
+- name: Delete "{{ pool_info.name }}"
+ community.libvirt.virt_pool:
+ state: absent
+ name: "{{ pool_info.name }}"
+ register: result
+
+- name: Delete "{{ pool_info.name }} on check_mode(post)"
+ community.libvirt.virt_pool:
+ state: absent
+ name: "{{ pool_info.name }}"
+ register: result_post
+ check_mode: true
+
+- name: "Ensure the {{ pool_info.name }} has been deleted"
+ assert:
+ that:
+ - result_pre is changed
+ - result is changed and result.msg == 0
+ - result_post is not changed
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/tasks/main.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/tasks/main.yml
new file mode 100644
index 00000000..f6422b3c
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/tasks/main.yml
@@ -0,0 +1,31 @@
+---
+- include_vars: '{{ item }}'
+ with_first_found:
+ - "{{ ansible_distribution }}-{{ ansible_distribution_version}}.yml"
+ - "{{ ansible_distribution }}-{{ ansible_distribution_major_version}}.yml"
+ - "{{ ansible_distribution }}.yml"
+ - "default.yml"
+
+- block:
+ - name: Install libvirt packages
+ package:
+ name: "{{ virt_pool_packages }}"
+
+ - name: Start libvirt service
+ service:
+ name: libvirtd
+ state: started
+
+ - name: Test for a directory based pool
+ import_tasks: directory_based_pool.yml
+
+ always:
+ - name: Stop libvirt
+ service:
+ name: libvirtd
+ state: stopped
+
+ - name: Remove only the libvirt packages
+ package:
+ name: "{{ virt_pool_packages|select('match', '.*libvirt.*')|list }}"
+ state: absent
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/templates/test_pool.xml.j2 b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/templates/test_pool.xml.j2
new file mode 100644
index 00000000..3da24a50
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/templates/test_pool.xml.j2
@@ -0,0 +1,11 @@
+<pool type='dir'>
+ <name>{{ pool_info.name }}</name>
+ <capacity unit='bytes'>0</capacity>
+ <allocation unit='bytes'>0</allocation>
+ <available unit='bytes'>0</available>
+ <source>
+ </source>
+ <target>
+ <path>{{ pool_info.path }}</path>
+ </target>
+</pool>
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/CentOS-7.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/CentOS-7.yml
new file mode 100644
index 00000000..1ccb2a18
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/CentOS-7.yml
@@ -0,0 +1,6 @@
+---
+virt_pool_packages:
+ - libvirt
+ - libvirt-daemon
+ - libvirt-python
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/CentOS-8.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/CentOS-8.yml
new file mode 100644
index 00000000..053c662b
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/CentOS-8.yml
@@ -0,0 +1,8 @@
+---
+ansible_python_interpreter: /usr/libexec/platform-python
+
+virt_pool_packages:
+ - libvirt
+ - libvirt-daemon
+ - python3-libvirt
+ - python3-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Debian.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Debian.yml
new file mode 100644
index 00000000..a55f4b23
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Debian.yml
@@ -0,0 +1,6 @@
+---
+virt_pool_packages:
+ - libvirt-daemon
+ - libvirt-daemon-system
+ - python-libvirt
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Fedora-34.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Fedora-34.yml
new file mode 100644
index 00000000..c95a3598
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Fedora-34.yml
@@ -0,0 +1,6 @@
+---
+virt_pool_packages:
+ - libvirt
+ - libvirt-daemon
+ - python3-libvirt
+ - python3-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-7.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-7.yml
new file mode 100644
index 00000000..1ccb2a18
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-7.yml
@@ -0,0 +1,6 @@
+---
+virt_pool_packages:
+ - libvirt
+ - libvirt-daemon
+ - libvirt-python
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-8.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-8.yml
new file mode 100644
index 00000000..322301e3
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-8.yml
@@ -0,0 +1,9 @@
+---
+# RHEL 8/CentOS 8 only provides python-libvirt package for the default Python
+ansible_python_interpreter: /usr/libexec/platform-python
+
+virt_pool_packages:
+ - libvirt
+ - libvirt-daemon
+ - python3-libvirt
+ - python3-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-9.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-9.yml
new file mode 100644
index 00000000..322301e3
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/RedHat-9.yml
@@ -0,0 +1,9 @@
+---
+# RHEL 8/CentOS 8 only provides python-libvirt package for the default Python
+ansible_python_interpreter: /usr/libexec/platform-python
+
+virt_pool_packages:
+ - libvirt
+ - libvirt-daemon
+ - python3-libvirt
+ - python3-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-18.04.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-18.04.yml
new file mode 100644
index 00000000..bb27ffcd
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-18.04.yml
@@ -0,0 +1,5 @@
+---
+virt_pool_packages:
+ - libvirt-daemon
+ - python-libvirt
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-18.10.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-18.10.yml
new file mode 100644
index 00000000..a55f4b23
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-18.10.yml
@@ -0,0 +1,6 @@
+---
+virt_pool_packages:
+ - libvirt-daemon
+ - libvirt-daemon-system
+ - python-libvirt
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-20.04.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-20.04.yml
new file mode 100644
index 00000000..a55f4b23
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/Ubuntu-20.04.yml
@@ -0,0 +1,6 @@
+---
+virt_pool_packages:
+ - libvirt-daemon
+ - libvirt-daemon-system
+ - python-libvirt
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/default.yml b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/default.yml
new file mode 100644
index 00000000..bb27ffcd
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/integration/targets/virt_pool/vars/default.yml
@@ -0,0 +1,5 @@
+---
+virt_pool_packages:
+ - libvirt-daemon
+ - python-libvirt
+ - python-lxml
diff --git a/ansible_collections/community/libvirt/tests/sanity/ignore-2.10.txt b/ansible_collections/community/libvirt/tests/sanity/ignore-2.10.txt
new file mode 100644
index 00000000..f6584fe1
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/sanity/ignore-2.10.txt
@@ -0,0 +1,10 @@
+tests/unit/mock/path.py future-import-boilerplate
+tests/unit/mock/path.py metaclass-boilerplate
+tests/unit/mock/yaml_helper.py future-import-boilerplate
+tests/unit/mock/yaml_helper.py metaclass-boilerplate
+tests/unit/modules/cloud/misc/virt_net/conftest.py future-import-boilerplate
+tests/unit/modules/cloud/misc/virt_net/conftest.py metaclass-boilerplate
+tests/unit/modules/cloud/misc/virt_net/test_virt_net.py future-import-boilerplate
+tests/unit/modules/cloud/misc/virt_net/test_virt_net.py metaclass-boilerplate
+tests/utils/shippable/timing.py shebang
+tests/utils/shippable/check_matrix.py replace-urlopen
diff --git a/ansible_collections/community/libvirt/tests/sanity/ignore-2.11.txt b/ansible_collections/community/libvirt/tests/sanity/ignore-2.11.txt
new file mode 100644
index 00000000..f6584fe1
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/sanity/ignore-2.11.txt
@@ -0,0 +1,10 @@
+tests/unit/mock/path.py future-import-boilerplate
+tests/unit/mock/path.py metaclass-boilerplate
+tests/unit/mock/yaml_helper.py future-import-boilerplate
+tests/unit/mock/yaml_helper.py metaclass-boilerplate
+tests/unit/modules/cloud/misc/virt_net/conftest.py future-import-boilerplate
+tests/unit/modules/cloud/misc/virt_net/conftest.py metaclass-boilerplate
+tests/unit/modules/cloud/misc/virt_net/test_virt_net.py future-import-boilerplate
+tests/unit/modules/cloud/misc/virt_net/test_virt_net.py metaclass-boilerplate
+tests/utils/shippable/timing.py shebang
+tests/utils/shippable/check_matrix.py replace-urlopen
diff --git a/ansible_collections/community/libvirt/tests/sanity/ignore-2.12.txt b/ansible_collections/community/libvirt/tests/sanity/ignore-2.12.txt
new file mode 100644
index 00000000..50392e8e
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/sanity/ignore-2.12.txt
@@ -0,0 +1,2 @@
+tests/utils/shippable/timing.py shebang
+tests/utils/shippable/check_matrix.py replace-urlopen
diff --git a/ansible_collections/community/libvirt/tests/sanity/ignore-2.13.txt b/ansible_collections/community/libvirt/tests/sanity/ignore-2.13.txt
new file mode 100644
index 00000000..50392e8e
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/sanity/ignore-2.13.txt
@@ -0,0 +1,2 @@
+tests/utils/shippable/timing.py shebang
+tests/utils/shippable/check_matrix.py replace-urlopen
diff --git a/ansible_collections/community/libvirt/tests/sanity/ignore-2.14.txt b/ansible_collections/community/libvirt/tests/sanity/ignore-2.14.txt
new file mode 100644
index 00000000..50392e8e
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/sanity/ignore-2.14.txt
@@ -0,0 +1,2 @@
+tests/utils/shippable/timing.py shebang
+tests/utils/shippable/check_matrix.py replace-urlopen
diff --git a/ansible_collections/community/libvirt/tests/sanity/ignore-2.9.txt b/ansible_collections/community/libvirt/tests/sanity/ignore-2.9.txt
new file mode 100644
index 00000000..f6584fe1
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/sanity/ignore-2.9.txt
@@ -0,0 +1,10 @@
+tests/unit/mock/path.py future-import-boilerplate
+tests/unit/mock/path.py metaclass-boilerplate
+tests/unit/mock/yaml_helper.py future-import-boilerplate
+tests/unit/mock/yaml_helper.py metaclass-boilerplate
+tests/unit/modules/cloud/misc/virt_net/conftest.py future-import-boilerplate
+tests/unit/modules/cloud/misc/virt_net/conftest.py metaclass-boilerplate
+tests/unit/modules/cloud/misc/virt_net/test_virt_net.py future-import-boilerplate
+tests/unit/modules/cloud/misc/virt_net/test_virt_net.py metaclass-boilerplate
+tests/utils/shippable/timing.py shebang
+tests/utils/shippable/check_matrix.py replace-urlopen
diff --git a/ansible_collections/community/libvirt/tests/unit/compat/__init__.py b/ansible_collections/community/libvirt/tests/unit/compat/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/compat/__init__.py
diff --git a/ansible_collections/community/libvirt/tests/unit/compat/builtins.py b/ansible_collections/community/libvirt/tests/unit/compat/builtins.py
new file mode 100644
index 00000000..f60ee678
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/compat/builtins.py
@@ -0,0 +1,33 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+#
+# Compat for python2.7
+#
+
+# One unittest needs to import builtins via __import__() so we need to have
+# the string that represents it
+try:
+ import __builtin__
+except ImportError:
+ BUILTINS = 'builtins'
+else:
+ BUILTINS = '__builtin__'
diff --git a/ansible_collections/community/libvirt/tests/unit/compat/mock.py b/ansible_collections/community/libvirt/tests/unit/compat/mock.py
new file mode 100644
index 00000000..0972cd2e
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/compat/mock.py
@@ -0,0 +1,122 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+'''
+Compat module for Python3.x's unittest.mock module
+'''
+import sys
+
+# Python 2.7
+
+# Note: Could use the pypi mock library on python3.x as well as python2.x. It
+# is the same as the python3 stdlib mock library
+
+try:
+ # Allow wildcard import because we really do want to import all of mock's
+ # symbols into this compat shim
+ # pylint: disable=wildcard-import,unused-wildcard-import
+ from unittest.mock import *
+except ImportError:
+ # Python 2
+ # pylint: disable=wildcard-import,unused-wildcard-import
+ try:
+ from mock import *
+ except ImportError:
+ print('You need the mock library installed on python2.x to run tests')
+
+
+# Prior to 3.4.4, mock_open cannot handle binary read_data
+if sys.version_info >= (3,) and sys.version_info < (3, 4, 4):
+ file_spec = None
+
+ def _iterate_read_data(read_data):
+ # Helper for mock_open:
+ # Retrieve lines from read_data via a generator so that separate calls to
+ # readline, read, and readlines are properly interleaved
+ sep = b'\n' if isinstance(read_data, bytes) else '\n'
+ data_as_list = [l + sep for l in read_data.split(sep)]
+
+ if data_as_list[-1] == sep:
+ # If the last line ended in a newline, the list comprehension will have an
+ # extra entry that's just a newline. Remove this.
+ data_as_list = data_as_list[:-1]
+ else:
+ # If there wasn't an extra newline by itself, then the file being
+ # emulated doesn't have a newline to end the last line remove the
+ # newline that our naive format() added
+ data_as_list[-1] = data_as_list[-1][:-1]
+
+ for line in data_as_list:
+ yield line
+
+ def mock_open(mock=None, read_data=''):
+ """
+ A helper function to create a mock to replace the use of `open`. It works
+ for `open` called directly or used as a context manager.
+
+ The `mock` argument is the mock object to configure. If `None` (the
+ default) then a `MagicMock` will be created for you, with the API limited
+ to methods or attributes available on standard file handles.
+
+ `read_data` is a string for the `read` methoddline`, and `readlines` of the
+ file handle to return. This is an empty string by default.
+ """
+ def _readlines_side_effect(*args, **kwargs):
+ if handle.readlines.return_value is not None:
+ return handle.readlines.return_value
+ return list(_data)
+
+ def _read_side_effect(*args, **kwargs):
+ if handle.read.return_value is not None:
+ return handle.read.return_value
+ return type(read_data)().join(_data)
+
+ def _readline_side_effect():
+ if handle.readline.return_value is not None:
+ while True:
+ yield handle.readline.return_value
+ for line in _data:
+ yield line
+
+ global file_spec
+ if file_spec is None:
+ import _io
+ file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))))
+
+ if mock is None:
+ mock = MagicMock(name='open', spec=open)
+
+ handle = MagicMock(spec=file_spec)
+ handle.__enter__.return_value = handle
+
+ _data = _iterate_read_data(read_data)
+
+ handle.write.return_value = None
+ handle.read.return_value = None
+ handle.readline.return_value = None
+ handle.readlines.return_value = None
+
+ handle.read.side_effect = _read_side_effect
+ handle.readline.side_effect = _readline_side_effect()
+ handle.readlines.side_effect = _readlines_side_effect
+
+ mock.return_value = handle
+ return mock
diff --git a/ansible_collections/community/libvirt/tests/unit/compat/unittest.py b/ansible_collections/community/libvirt/tests/unit/compat/unittest.py
new file mode 100644
index 00000000..98f08ad6
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/compat/unittest.py
@@ -0,0 +1,38 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+'''
+Compat module for Python2.7's unittest module
+'''
+
+import sys
+
+# Allow wildcard import because we really do want to import all of
+# unittests's symbols into this compat shim
+# pylint: disable=wildcard-import,unused-wildcard-import
+if sys.version_info < (2, 7):
+ try:
+ # Need unittest2 on python2.6
+ from unittest2 import *
+ except ImportError:
+ print('You need unittest2 installed on python2.6.x to run tests')
+else:
+ from unittest import *
diff --git a/ansible_collections/community/libvirt/tests/unit/mock/__init__.py b/ansible_collections/community/libvirt/tests/unit/mock/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/mock/__init__.py
diff --git a/ansible_collections/community/libvirt/tests/unit/mock/loader.py b/ansible_collections/community/libvirt/tests/unit/mock/loader.py
new file mode 100644
index 00000000..00a58412
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/mock/loader.py
@@ -0,0 +1,116 @@
+# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+
+from ansible.errors import AnsibleParserError
+from ansible.parsing.dataloader import DataLoader
+from ansible.module_utils._text import to_bytes, to_text
+
+
+class DictDataLoader(DataLoader):
+
+ def __init__(self, file_mapping=None):
+ file_mapping = {} if file_mapping is None else file_mapping
+ assert type(file_mapping) == dict
+
+ super(DictDataLoader, self).__init__()
+
+ self._file_mapping = file_mapping
+ self._build_known_directories()
+ self._vault_secrets = None
+
+ def load_from_file(self, path, cache=True, unsafe=False):
+ path = to_text(path)
+ if path in self._file_mapping:
+ return self.load(self._file_mapping[path], path)
+ return None
+
+ # TODO: the real _get_file_contents returns a bytestring, so we actually convert the
+ # unicode/text it's created with to utf-8
+ def _get_file_contents(self, file_name):
+ file_name = to_text(file_name)
+ if file_name in self._file_mapping:
+ return (to_bytes(self._file_mapping[file_name]), False)
+ else:
+ raise AnsibleParserError("file not found: %s" % file_name)
+
+ def path_exists(self, path):
+ path = to_text(path)
+ return path in self._file_mapping or path in self._known_directories
+
+ def is_file(self, path):
+ path = to_text(path)
+ return path in self._file_mapping
+
+ def is_directory(self, path):
+ path = to_text(path)
+ return path in self._known_directories
+
+ def list_directory(self, path):
+ ret = []
+ path = to_text(path)
+ for x in (list(self._file_mapping.keys()) + self._known_directories):
+ if x.startswith(path):
+ if os.path.dirname(x) == path:
+ ret.append(os.path.basename(x))
+ return ret
+
+ def is_executable(self, path):
+ # FIXME: figure out a way to make paths return true for this
+ return False
+
+ def _add_known_directory(self, directory):
+ if directory not in self._known_directories:
+ self._known_directories.append(directory)
+
+ def _build_known_directories(self):
+ self._known_directories = []
+ for path in self._file_mapping:
+ dirname = os.path.dirname(path)
+ while dirname not in ('/', ''):
+ self._add_known_directory(dirname)
+ dirname = os.path.dirname(dirname)
+
+ def push(self, path, content):
+ rebuild_dirs = False
+ if path not in self._file_mapping:
+ rebuild_dirs = True
+
+ self._file_mapping[path] = content
+
+ if rebuild_dirs:
+ self._build_known_directories()
+
+ def pop(self, path):
+ if path in self._file_mapping:
+ del self._file_mapping[path]
+ self._build_known_directories()
+
+ def clear(self):
+ self._file_mapping = dict()
+ self._known_directories = []
+
+ def get_basedir(self):
+ return os.getcwd()
+
+ def set_vault_secrets(self, vault_secrets):
+ self._vault_secrets = vault_secrets
diff --git a/ansible_collections/community/libvirt/tests/unit/mock/path.py b/ansible_collections/community/libvirt/tests/unit/mock/path.py
new file mode 100644
index 00000000..39b09099
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/mock/path.py
@@ -0,0 +1,5 @@
+from ansible_collections.ansible.libvirt.tests.unit.compat.mock import MagicMock
+from ansible.utils.path import unfrackpath
+
+
+mock_unfrackpath_noop = MagicMock(spec_set=unfrackpath, side_effect=lambda x, *args, **kwargs: x)
diff --git a/ansible_collections/community/libvirt/tests/unit/mock/procenv.py b/ansible_collections/community/libvirt/tests/unit/mock/procenv.py
new file mode 100644
index 00000000..96328184
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/mock/procenv.py
@@ -0,0 +1,90 @@
+# (c) 2016, Matt Davis <mdavis@ansible.com>
+# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import sys
+import json
+
+from contextlib import contextmanager
+from io import BytesIO, StringIO
+from ansible_collections.ansible.libvirt.tests.unit.compat import unittest
+from ansible.module_utils.six import PY3
+from ansible.module_utils._text import to_bytes
+
+
+@contextmanager
+def swap_stdin_and_argv(stdin_data='', argv_data=tuple()):
+ """
+ context manager that temporarily masks the test runner's values for stdin and argv
+ """
+ real_stdin = sys.stdin
+ real_argv = sys.argv
+
+ if PY3:
+ fake_stream = StringIO(stdin_data)
+ fake_stream.buffer = BytesIO(to_bytes(stdin_data))
+ else:
+ fake_stream = BytesIO(to_bytes(stdin_data))
+
+ try:
+ sys.stdin = fake_stream
+ sys.argv = argv_data
+
+ yield
+ finally:
+ sys.stdin = real_stdin
+ sys.argv = real_argv
+
+
+@contextmanager
+def swap_stdout():
+ """
+ context manager that temporarily replaces stdout for tests that need to verify output
+ """
+ old_stdout = sys.stdout
+
+ if PY3:
+ fake_stream = StringIO()
+ else:
+ fake_stream = BytesIO()
+
+ try:
+ sys.stdout = fake_stream
+
+ yield fake_stream
+ finally:
+ sys.stdout = old_stdout
+
+
+class ModuleTestCase(unittest.TestCase):
+ def setUp(self, module_args=None):
+ if module_args is None:
+ module_args = {'_ansible_remote_tmp': '/tmp', '_ansible_keep_remote_files': False}
+
+ args = json.dumps(dict(ANSIBLE_MODULE_ARGS=module_args))
+
+ # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
+ self.stdin_swap = swap_stdin_and_argv(stdin_data=args)
+ self.stdin_swap.__enter__()
+
+ def tearDown(self):
+ # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
+ self.stdin_swap.__exit__(None, None, None)
diff --git a/ansible_collections/community/libvirt/tests/unit/mock/vault_helper.py b/ansible_collections/community/libvirt/tests/unit/mock/vault_helper.py
new file mode 100644
index 00000000..dcce9c78
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/mock/vault_helper.py
@@ -0,0 +1,39 @@
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible.module_utils._text import to_bytes
+
+from ansible.parsing.vault import VaultSecret
+
+
+class TextVaultSecret(VaultSecret):
+ '''A secret piece of text. ie, a password. Tracks text encoding.
+
+ The text encoding of the text may not be the default text encoding so
+ we keep track of the encoding so we encode it to the same bytes.'''
+
+ def __init__(self, text, encoding=None, errors=None, _bytes=None):
+ super(TextVaultSecret, self).__init__()
+ self.text = text
+ self.encoding = encoding or 'utf-8'
+ self._bytes = _bytes
+ self.errors = errors or 'strict'
+
+ @property
+ def bytes(self):
+ '''The text encoded with encoding, unless we specifically set _bytes.'''
+ return self._bytes or to_bytes(self.text, encoding=self.encoding, errors=self.errors)
diff --git a/ansible_collections/community/libvirt/tests/unit/mock/yaml_helper.py b/ansible_collections/community/libvirt/tests/unit/mock/yaml_helper.py
new file mode 100644
index 00000000..cc095fea
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/mock/yaml_helper.py
@@ -0,0 +1,121 @@
+import io
+import yaml
+
+from ansible.module_utils.six import PY3
+from ansible.parsing.yaml.loader import AnsibleLoader
+from ansible.parsing.yaml.dumper import AnsibleDumper
+
+
+class YamlTestUtils(object):
+ """Mixin class to combine with a unittest.TestCase subclass."""
+ def _loader(self, stream):
+ """Vault related tests will want to override this.
+
+ Vault cases should setup a AnsibleLoader that has the vault password."""
+ return AnsibleLoader(stream)
+
+ def _dump_stream(self, obj, stream, dumper=None):
+ """Dump to a py2-unicode or py3-string stream."""
+ if PY3:
+ return yaml.dump(obj, stream, Dumper=dumper)
+ else:
+ return yaml.dump(obj, stream, Dumper=dumper, encoding=None)
+
+ def _dump_string(self, obj, dumper=None):
+ """Dump to a py2-unicode or py3-string"""
+ if PY3:
+ return yaml.dump(obj, Dumper=dumper)
+ else:
+ return yaml.dump(obj, Dumper=dumper, encoding=None)
+
+ def _dump_load_cycle(self, obj):
+ # Each pass though a dump or load revs the 'generation'
+ # obj to yaml string
+ string_from_object_dump = self._dump_string(obj, dumper=AnsibleDumper)
+
+ # wrap a stream/file like StringIO around that yaml
+ stream_from_object_dump = io.StringIO(string_from_object_dump)
+ loader = self._loader(stream_from_object_dump)
+ # load the yaml stream to create a new instance of the object (gen 2)
+ obj_2 = loader.get_data()
+
+ # dump the gen 2 objects directory to strings
+ string_from_object_dump_2 = self._dump_string(obj_2,
+ dumper=AnsibleDumper)
+
+ # The gen 1 and gen 2 yaml strings
+ self.assertEqual(string_from_object_dump, string_from_object_dump_2)
+ # the gen 1 (orig) and gen 2 py object
+ self.assertEqual(obj, obj_2)
+
+ # again! gen 3... load strings into py objects
+ stream_3 = io.StringIO(string_from_object_dump_2)
+ loader_3 = self._loader(stream_3)
+ obj_3 = loader_3.get_data()
+
+ string_from_object_dump_3 = self._dump_string(obj_3, dumper=AnsibleDumper)
+
+ self.assertEqual(obj, obj_3)
+ # should be transitive, but...
+ self.assertEqual(obj_2, obj_3)
+ self.assertEqual(string_from_object_dump, string_from_object_dump_3)
+
+ def _old_dump_load_cycle(self, obj):
+ '''Dump the passed in object to yaml, load it back up, dump again, compare.'''
+ stream = io.StringIO()
+
+ yaml_string = self._dump_string(obj, dumper=AnsibleDumper)
+ self._dump_stream(obj, stream, dumper=AnsibleDumper)
+
+ yaml_string_from_stream = stream.getvalue()
+
+ # reset stream
+ stream.seek(0)
+
+ loader = self._loader(stream)
+ # loader = AnsibleLoader(stream, vault_password=self.vault_password)
+ obj_from_stream = loader.get_data()
+
+ stream_from_string = io.StringIO(yaml_string)
+ loader2 = self._loader(stream_from_string)
+ # loader2 = AnsibleLoader(stream_from_string, vault_password=self.vault_password)
+ obj_from_string = loader2.get_data()
+
+ stream_obj_from_stream = io.StringIO()
+ stream_obj_from_string = io.StringIO()
+
+ if PY3:
+ yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper)
+ yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper)
+ else:
+ yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper, encoding=None)
+ yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper, encoding=None)
+
+ yaml_string_stream_obj_from_stream = stream_obj_from_stream.getvalue()
+ yaml_string_stream_obj_from_string = stream_obj_from_string.getvalue()
+
+ stream_obj_from_stream.seek(0)
+ stream_obj_from_string.seek(0)
+
+ if PY3:
+ yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper)
+ yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper)
+ else:
+ yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper, encoding=None)
+ yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper, encoding=None)
+
+ assert yaml_string == yaml_string_obj_from_stream
+ assert yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
+ assert (yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string == yaml_string_stream_obj_from_stream ==
+ yaml_string_stream_obj_from_string)
+ assert obj == obj_from_stream
+ assert obj == obj_from_string
+ assert obj == yaml_string_obj_from_stream
+ assert obj == yaml_string_obj_from_string
+ assert obj == obj_from_stream == obj_from_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
+ return {'obj': obj,
+ 'yaml_string': yaml_string,
+ 'yaml_string_from_stream': yaml_string_from_stream,
+ 'obj_from_stream': obj_from_stream,
+ 'obj_from_string': obj_from_string,
+ 'yaml_string_obj_from_string': yaml_string_obj_from_string}
diff --git a/ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/__init__.py b/ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/__init__.py
diff --git a/ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/conftest.py b/ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/conftest.py
new file mode 100644
index 00000000..68acada8
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/conftest.py
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright: (c) 2019, Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+import pytest
+
+from ansible_collections.community.libvirt.plugins.modules import virt_net
+
+from ansible_collections.community.libvirt.tests.unit.compat import mock
+
+
+virt_net.libvirt = None
+virt_net.HAS_VIRT = True
+
+
+class DummyNetwork():
+ def __init__(self, name, isActive=True):
+ self._name = name
+ self._isActive = isActive
+
+ def name(self):
+ return self._name
+
+ def isActive(self):
+ return self._isActive
+
+
+class DummyLibvirtConn():
+ def __init__(self):
+ self._network = [
+ DummyNetwork("inactive_net", isActive=False),
+ DummyNetwork("active_net", isActive=True)]
+
+ def listNetworks(self):
+ return [i.name() for i in self._network]
+
+ def networkLookupByName(self, name):
+ for i in self._network:
+ if i.name() == name:
+ return i
+
+ def listDefinedNetworks(self):
+ return []
+
+
+class DummyLibvirt():
+ VIR_ERR_NETWORK_EXIST = 'VIR_ERR_NETWORK_EXIST'
+
+ @classmethod
+ def open(cls, uri):
+ return DummyLibvirtConn()
+
+ class libvirtError(Exception):
+ def __init__(self):
+ self.error_code
+
+ def get_error_code(self):
+ return self.error_code
+
+
+@pytest.fixture
+def dummy_libvirt(monkeypatch):
+ monkeypatch.setattr(virt_net, 'libvirt', DummyLibvirt)
+ return DummyLibvirt
+
+
+@pytest.fixture
+def virt_net_obj(dummy_libvirt):
+ return virt_net.VirtNetwork('qemu:///nowhere', mock.MagicMock())
diff --git a/ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/test_virt_net.py b/ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/test_virt_net.py
new file mode 100644
index 00000000..a6133f9f
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/unit/modules/cloud/misc/virt_net/test_virt_net.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright: (c) 2019, Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+from ansible_collections.community.libvirt.tests.unit.compat import mock
+
+
+def test_virt_net_create_already_active(virt_net_obj, dummy_libvirt):
+ virt_net_obj.conn.create = mock.Mock()
+ assert virt_net_obj.create("active_net") is None
+ virt_net_obj.conn.create.assert_not_called()
+
+
+def test_virt_net_recreate(virt_net_obj, dummy_libvirt):
+ virt_net_obj.conn.create = mock.Mock()
+ dummy_libvirt.libvirtError.error_code = 'VIR_ERR_NETWORK_EXIST'
+ virt_net_obj.conn.create.side_effect = dummy_libvirt.libvirtError
+ assert virt_net_obj.create("active_net") is None
+
+
+def test_virt_stop_ignore_inactive(virt_net_obj):
+ virt_net_obj.conn.destroy = mock.Mock()
+ virt_net_obj.stop('inactive_net')
+ virt_net_obj.conn.destroy.assert_not_called()
+
+
+def test_virt_stop_active(virt_net_obj, monkeypatch):
+ virt_net_obj.conn.destroy = mock.Mock()
+ virt_net_obj.stop('active_net')
+ virt_net_obj.conn.destroy.assert_called_with('active_net')
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/check_matrix.py b/ansible_collections/community/libvirt/tests/utils/shippable/check_matrix.py
new file mode 100755
index 00000000..567181fc
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/check_matrix.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+"""Verify the currently executing Shippable test matrix matches the one defined in the "shippable.yml" file."""
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import datetime
+import json
+import os
+import re
+import sys
+import time
+
+from ansible.module_utils.urls import open_url
+
+try:
+ from typing import NoReturn
+except ImportError:
+ NoReturn = None
+
+try:
+ # noinspection PyCompatibility
+ from urllib2 import urlopen # pylint: disable=ansible-bad-import-from
+except ImportError:
+ # noinspection PyCompatibility
+ from urllib.request import urlopen
+
+
+def main(): # type: () -> None
+ """Main entry point."""
+ repo_full_name = os.environ['REPO_FULL_NAME']
+ required_repo_full_name = 'ansible-collections/community.libvirt'
+
+ if repo_full_name != required_repo_full_name:
+ sys.stderr.write('Skipping matrix check on repo "%s" which is not "%s".\n' % (repo_full_name, required_repo_full_name))
+ return
+
+ with open('shippable.yml', 'rb') as yaml_file:
+ yaml = yaml_file.read().decode('utf-8').splitlines()
+
+ defined_matrix = [match.group(1) for match in [re.search(r'^ *- env: T=(.*)$', line) for line in yaml] if match and match.group(1) != 'none']
+
+ if not defined_matrix:
+ fail('No matrix entries found in the "shippable.yml" file.',
+ 'Did you modify the "shippable.yml" file?')
+
+ run_id = os.environ['SHIPPABLE_BUILD_ID']
+ sleep = 1
+ jobs = []
+
+ for attempts_remaining in range(4, -1, -1):
+ try:
+ jobs = json.loads(urlopen('https://api.shippable.com/jobs?runIds=%s' % run_id).read())
+
+ if not isinstance(jobs, list):
+ raise Exception('Shippable run %s data is not a list.' % run_id)
+
+ break
+ except Exception as ex:
+ if not attempts_remaining:
+ fail('Unable to retrieve Shippable run %s matrix.' % run_id,
+ str(ex))
+
+ sys.stderr.write('Unable to retrieve Shippable run %s matrix: %s\n' % (run_id, ex))
+ sys.stderr.write('Trying again in %d seconds...\n' % sleep)
+ time.sleep(sleep)
+ sleep *= 2
+
+ if len(jobs) != len(defined_matrix):
+ if len(jobs) == 1:
+ hint = '\n\nMake sure you do not use the "Rebuild with SSH" option.'
+ else:
+ hint = ''
+
+ fail('Shippable run %s has %d jobs instead of the expected %d jobs.' % (run_id, len(jobs), len(defined_matrix)),
+ 'Try re-running the entire matrix.%s' % hint)
+
+ actual_matrix = dict((job.get('jobNumber'), dict(tuple(line.split('=', 1)) for line in job.get('env', [])).get('T', '')) for job in jobs)
+ errors = [(job_number, test, actual_matrix.get(job_number)) for job_number, test in enumerate(defined_matrix, 1) if actual_matrix.get(job_number) != test]
+
+ if len(errors):
+ error_summary = '\n'.join('Job %s expected "%s" but found "%s" instead.' % (job_number, expected, actual) for job_number, expected, actual in errors)
+
+ fail('Shippable run %s has a job matrix mismatch.' % run_id,
+ 'Try re-running the entire matrix.\n\n%s' % error_summary)
+
+
+def fail(message, output): # type: (str, str) -> NoReturn
+ # Include a leading newline to improve readability on Shippable "Tests" tab.
+ # Without this, the first line becomes indented.
+ output = '\n' + output.strip()
+
+ timestamp = datetime.datetime.utcnow().replace(microsecond=0).isoformat()
+
+ # hack to avoid requiring junit-xml, which isn't pre-installed on Shippable outside our test containers
+ xml = '''
+<?xml version="1.0" encoding="utf-8"?>
+<testsuites disabled="0" errors="1" failures="0" tests="1" time="0.0">
+\t<testsuite disabled="0" errors="1" failures="0" file="None" log="None" name="ansible-test" skipped="0" tests="1" time="0" timestamp="%s" url="None">
+\t\t<testcase classname="timeout" name="timeout">
+\t\t\t<error message="%s" type="error">%s</error>
+\t\t</testcase>
+\t</testsuite>
+</testsuites>
+''' % (timestamp, message, output)
+
+ path = 'shippable/testresults/check-matrix.xml'
+ dir_path = os.path.dirname(path)
+
+ if not os.path.exists(dir_path):
+ os.makedirs(dir_path)
+
+ with open(path, 'w') as junit_fd:
+ junit_fd.write(xml.lstrip())
+
+ sys.stderr.write(message + '\n')
+ sys.stderr.write(output + '\n')
+
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/cloud.sh b/ansible_collections/community/libvirt/tests/utils/shippable/cloud.sh
new file mode 100755
index 00000000..d76c3228
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/cloud.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+set -o pipefail -eux
+
+declare -a args
+IFS='/:' read -ra args <<< "$1"
+
+cloud="${args[0]}"
+python="${args[1]}"
+group="${args[2]}"
+
+target="shippable/${cloud}/group${group}/"
+
+stage="${S:-prod}"
+
+# shellcheck disable=SC2086
+ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
+ --remote-terminate always --remote-stage "${stage}" \
+ --docker --python "${python}"
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/freebsd.sh b/ansible_collections/community/libvirt/tests/utils/shippable/freebsd.sh
new file mode 100755
index 00000000..cd3014cc
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/freebsd.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+set -o pipefail -eux
+
+declare -a args
+IFS='/:' read -ra args <<< "$1"
+
+platform="${args[0]}"
+version="${args[1]}"
+
+if [ "${#args[@]}" -gt 2 ]; then
+ target="shippable/posix/group${args[2]}/"
+else
+ target="shippable/posix/"
+fi
+
+stage="${S:-prod}"
+provider="${P:-default}"
+
+# shellcheck disable=SC2086
+ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
+ --remote "${platform}/${version}" --remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}"
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/linux.sh b/ansible_collections/community/libvirt/tests/utils/shippable/linux.sh
new file mode 100755
index 00000000..9cc2f966
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/linux.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+set -o pipefail -eux
+
+declare -a args
+IFS='/:' read -ra args <<< "$1"
+
+image="${args[1]}"
+
+if [ "${#args[@]}" -gt 2 ]; then
+ target="shippable/posix/group${args[2]}/"
+else
+ target="shippable/posix/"
+fi
+
+# shellcheck disable=SC2086
+ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
+ --docker "${image}"
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/osx.sh b/ansible_collections/community/libvirt/tests/utils/shippable/osx.sh
new file mode 100755
index 00000000..cd3014cc
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/osx.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+set -o pipefail -eux
+
+declare -a args
+IFS='/:' read -ra args <<< "$1"
+
+platform="${args[0]}"
+version="${args[1]}"
+
+if [ "${#args[@]}" -gt 2 ]; then
+ target="shippable/posix/group${args[2]}/"
+else
+ target="shippable/posix/"
+fi
+
+stage="${S:-prod}"
+provider="${P:-default}"
+
+# shellcheck disable=SC2086
+ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
+ --remote "${platform}/${version}" --remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}"
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/remote.sh b/ansible_collections/community/libvirt/tests/utils/shippable/remote.sh
new file mode 100755
index 00000000..cd3014cc
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/remote.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+set -o pipefail -eux
+
+declare -a args
+IFS='/:' read -ra args <<< "$1"
+
+platform="${args[0]}"
+version="${args[1]}"
+
+if [ "${#args[@]}" -gt 2 ]; then
+ target="shippable/posix/group${args[2]}/"
+else
+ target="shippable/posix/"
+fi
+
+stage="${S:-prod}"
+provider="${P:-default}"
+
+# shellcheck disable=SC2086
+ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
+ --remote "${platform}/${version}" --remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}"
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/rhel.sh b/ansible_collections/community/libvirt/tests/utils/shippable/rhel.sh
new file mode 100755
index 00000000..cd3014cc
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/rhel.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+set -o pipefail -eux
+
+declare -a args
+IFS='/:' read -ra args <<< "$1"
+
+platform="${args[0]}"
+version="${args[1]}"
+
+if [ "${#args[@]}" -gt 2 ]; then
+ target="shippable/posix/group${args[2]}/"
+else
+ target="shippable/posix/"
+fi
+
+stage="${S:-prod}"
+provider="${P:-default}"
+
+# shellcheck disable=SC2086
+ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
+ --remote "${platform}/${version}" --remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}"
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/sanity.sh b/ansible_collections/community/libvirt/tests/utils/shippable/sanity.sh
new file mode 100755
index 00000000..0c54a42c
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/sanity.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+set -o pipefail -eux
+
+# shellcheck disable=SC2086
+ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \
+ --docker \
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/shippable.sh b/ansible_collections/community/libvirt/tests/utils/shippable/shippable.sh
new file mode 100755
index 00000000..854ce08f
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/shippable.sh
@@ -0,0 +1,206 @@
+#!/usr/bin/env bash
+
+set -o pipefail -eux
+
+declare -a args
+IFS='/:' read -ra args <<< "$1"
+
+ansible_version="${args[0]}"
+script="${args[1]}"
+
+function join {
+ local IFS="$1";
+ shift;
+ echo "$*";
+}
+
+# Ensure we can write other collections to this dir
+sudo chown "$(whoami)" "${PWD}/../../"
+
+test="$(join / "${args[@]:1}")"
+
+docker images ansible/ansible
+docker images quay.io/ansible/*
+docker ps
+
+for container in $(docker ps --format '{{.Image}} {{.ID}}' | grep -v -e '^drydock/' -e '^quay.io/ansible/azure-pipelines-test-container:' | sed 's/^.* //'); do
+ docker rm -f "${container}" || true # ignore errors
+done
+
+docker ps
+
+if [ -d /home/shippable/cache/ ]; then
+ ls -la /home/shippable/cache/
+fi
+
+command -v python
+python -V
+
+function retry
+{
+ # shellcheck disable=SC2034
+ for repetition in 1 2 3; do
+ set +e
+ "$@"
+ result=$?
+ set -e
+ if [ ${result} == 0 ]; then
+ return ${result}
+ fi
+ echo "@* -> ${result}"
+ done
+ echo "Command '@*' failed 3 times!"
+ exit 1
+}
+
+command -v pip
+pip --version
+pip list --disable-pip-version-check
+if [ "${ansible_version}" == "devel" ]; then
+ retry pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
+else
+ retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check
+fi
+
+export PATH="${PWD}/bin:${PATH}"
+if [ "${SHIPPABLE_BUILD_ID:-}" ]; then
+ export ANSIBLE_COLLECTIONS_PATHS="${HOME}/.ansible"
+ SHIPPABLE_RESULT_DIR="$(pwd)/shippable"
+ TEST_DIR="${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/libvirt"
+ mkdir -p "${TEST_DIR}"
+ cp -aT "${SHIPPABLE_BUILD_DIR}" "${TEST_DIR}"
+ cd "${TEST_DIR}"
+else
+ # AZP
+ export ANSIBLE_COLLECTIONS_PATHS="$PWD/../../../"
+fi
+
+export PYTHONIOENCODING='utf-8'
+
+if [ "${JOB_TRIGGERED_BY_NAME:-}" == "nightly-trigger" ]; then
+ COVERAGE=yes
+ COMPLETE=yes
+fi
+
+if [ -n "${COVERAGE:-}" ]; then
+ # on-demand coverage reporting triggered by setting the COVERAGE environment variable to a non-empty value
+ export COVERAGE="--coverage"
+elif [[ "${COMMIT_MESSAGE}" =~ ci_coverage ]]; then
+ # on-demand coverage reporting triggered by having 'ci_coverage' in the latest commit message
+ export COVERAGE="--coverage"
+else
+ # on-demand coverage reporting disabled (default behavior, always-on coverage reporting remains enabled)
+ export COVERAGE="--coverage-check"
+fi
+
+if [ -n "${COMPLETE:-}" ]; then
+ # disable change detection triggered by setting the COMPLETE environment variable to a non-empty value
+ export CHANGED=""
+elif [[ "${COMMIT_MESSAGE}" =~ ci_complete ]]; then
+ # disable change detection triggered by having 'ci_complete' in the latest commit message
+ export CHANGED=""
+else
+ # enable change detection (default behavior)
+ export CHANGED="--changed"
+fi
+
+if [ "${IS_PULL_REQUEST:-}" == "true" ]; then
+ # run unstable tests which are targeted by focused changes on PRs
+ export UNSTABLE="--allow-unstable-changed"
+else
+ # do not run unstable tests outside PRs
+ export UNSTABLE=""
+fi
+
+# remove empty core/extras module directories from PRs created prior to the repo-merge
+find plugins -type d -empty -print -delete
+
+function cleanup
+{
+ # for complete on-demand coverage generate a report for all files with no coverage on the "sanity/5" job so we only have one copy
+ if [ "${COVERAGE}" == "--coverage" ] && [ "${CHANGED}" == "" ] && [ "${test}" == "sanity/5" ]; then
+ stub="--stub"
+ # trigger coverage reporting for stubs even if no other coverage data exists
+ mkdir -p tests/output/coverage/
+ else
+ stub=""
+ fi
+
+ if [ -d tests/output/coverage/ ]; then
+ if find tests/output/coverage/ -mindepth 1 -name '.*' -prune -o -print -quit | grep -q .; then
+ process_coverage='yes' # process existing coverage files
+ elif [ "${stub}" ]; then
+ process_coverage='yes' # process coverage when stubs are enabled
+ else
+ process_coverage=''
+ fi
+
+ if [ "${process_coverage}" ]; then
+ # use python 3.7 for coverage to avoid running out of memory during coverage xml processing
+ # only use it for coverage to avoid the additional overhead of setting up a virtual environment for a potential no-op job
+ virtualenv --python /usr/bin/python3.7 ~/ansible-venv
+ set +ux
+ . ~/ansible-venv/bin/activate
+ set -ux
+
+ # shellcheck disable=SC2086
+ ansible-test coverage xml --color -v --requirements --group-by command --group-by version ${stub:+"$stub"}
+ cp -a tests/output/reports/coverage=*.xml "$SHIPPABLE_RESULT_DIR/codecoverage/"
+
+ if [ "${ansible_version}" != "2.9" ]; then
+ # analyze and capture code coverage aggregated by integration test target
+ ansible-test coverage analyze targets generate -v "$SHIPPABLE_RESULT_DIR/testresults/coverage-analyze-targets.json"
+ fi
+
+ # upload coverage report to codecov.io only when using complete on-demand coverage
+ if [ "${COVERAGE}" == "--coverage" ] && [ "${CHANGED}" == "" ]; then
+ for file in tests/output/reports/coverage=*.xml; do
+ flags="${file##*/coverage=}"
+ flags="${flags%-powershell.xml}"
+ flags="${flags%.xml}"
+ # remove numbered component from stub files when converting to tags
+ flags="${flags//stub-[0-9]*/stub}"
+ flags="${flags//=/,}"
+ flags="${flags//[^a-zA-Z0-9_,]/_}"
+
+ bash <(curl -s https://ansible-ci-files.s3.us-east-1.amazonaws.com/codecov/codecov.sh) \
+ -f "${file}" \
+ -F "${flags}" \
+ -n "${test}" \
+ -t e27e1287-0583-48ee-8a1f-867be2b25b46 \
+ -X coveragepy \
+ -X gcov \
+ -X fix \
+ -X search \
+ -X xcode \
+ || echo "Failed to upload code coverage report to codecov.io: ${file}"
+ done
+ fi
+ fi
+ fi
+
+ if [ -d tests/output/junit/ ]; then
+ cp -aT tests/output/junit/ "$SHIPPABLE_RESULT_DIR/testresults/"
+ fi
+
+ if [ -d tests/output/data/ ]; then
+ cp -a tests/output/data/ "$SHIPPABLE_RESULT_DIR/testresults/"
+ fi
+
+ if [ -d tests/output/bot/ ]; then
+ cp -aT tests/output/bot/ "$SHIPPABLE_RESULT_DIR/testresults/"
+ fi
+}
+
+if [ "${SHIPPABLE_BUILD_ID:-}" ]; then trap cleanup EXIT; fi
+
+if [[ "${COVERAGE:-}" == "--coverage" ]]; then
+ timeout=60
+else
+ timeout=50
+fi
+
+ansible-test env --dump --show --timeout "${timeout}" --color -v
+
+if [ "${SHIPPABLE_BUILD_ID:-}" ]; then "tests/utils/shippable/check_matrix.py"; fi
+"tests/utils/shippable/${script}.sh" "${test}"
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/timing.py b/ansible_collections/community/libvirt/tests/utils/shippable/timing.py
new file mode 100755
index 00000000..fb538271
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/timing.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python3.7
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import sys
+import time
+
+start = time.time()
+
+sys.stdin.reconfigure(errors='surrogateescape')
+sys.stdout.reconfigure(errors='surrogateescape')
+
+for line in sys.stdin:
+ seconds = time.time() - start
+ sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line))
+ sys.stdout.flush()
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/timing.sh b/ansible_collections/community/libvirt/tests/utils/shippable/timing.sh
new file mode 100755
index 00000000..77e25783
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/timing.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -o pipefail -eu
+
+"$@" 2>&1 | "$(dirname "$0")/timing.py"
diff --git a/ansible_collections/community/libvirt/tests/utils/shippable/units.sh b/ansible_collections/community/libvirt/tests/utils/shippable/units.sh
new file mode 100755
index 00000000..4bf9e05c
--- /dev/null
+++ b/ansible_collections/community/libvirt/tests/utils/shippable/units.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+set -o pipefail -eux
+
+if [[ "${COVERAGE:-}" == "--coverage" ]]; then
+ timeout=90
+else
+ timeout=30
+fi
+
+ansible-test env --timeout "${timeout}" --color -v
+
+# shellcheck disable=SC2086
+ansible-test units --color -v --docker default ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \