summaryrefslogtreecommitdiffstats
path: root/collections-debian-merged/ansible_collections/community/kubevirt/tests
diff options
context:
space:
mode:
Diffstat (limited to 'collections-debian-merged/ansible_collections/community/kubevirt/tests')
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/aliases1
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/constraints.txt1
-rwxr-xr-xcollections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/inventory_diff.py69
-rwxr-xr-xcollections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/runme.sh70
-rwxr-xr-xcollections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/server.py163
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/test.out61
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.10.txt20
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.11.txt20
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.9.txt5
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/compat/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/compat/mock.py122
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/compat/unittest.py38
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/module_utils/test_kubevirt.py54
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/kubevirt_fixtures.py74
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/test_kubevirt_rs.py78
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/test_kubevirt_vm.py113
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/utils.py52
-rw-r--r--collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/requirements.txt2
19 files changed, 943 insertions, 0 deletions
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/aliases b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/aliases
new file mode 100644
index 00000000..765b70da
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/aliases
@@ -0,0 +1 @@
+shippable/posix/group2
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/constraints.txt b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/constraints.txt
new file mode 100644
index 00000000..c44f44e9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/constraints.txt
@@ -0,0 +1 @@
+setuptools < 45 ; python_version <= '2.7' # setuptools 45 and later require python 3.5 or later
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/inventory_diff.py b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/inventory_diff.py
new file mode 100755
index 00000000..df5a7661
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/inventory_diff.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+import sys
+
+
+def check_hosts(contrib, plugin):
+ contrib_hosts = sorted(contrib['_meta']['hostvars'].keys())
+ plugin_hosts = sorted(plugin['_meta']['hostvars'].keys())
+ assert contrib_hosts == plugin_hosts
+ return contrib_hosts, plugin_hosts
+
+
+def check_groups(contrib, plugin):
+ contrib_groups = set(contrib.keys())
+ plugin_groups = set(plugin.keys())
+ missing_groups = contrib_groups.difference(plugin_groups)
+ if missing_groups:
+ print("groups: %s are missing from the plugin" % missing_groups)
+ assert not missing_groups
+ return contrib_groups, plugin_groups
+
+
+def check_host_vars(key, value, plugin, host):
+ # tags are a dict in the plugin
+ if key.startswith('ec2_tag'):
+ print('assert tag', key, value)
+ assert 'tags' in plugin['_meta']['hostvars'][host], 'b file does not have tags in host'
+ btags = plugin['_meta']['hostvars'][host]['tags']
+ tagkey = key.replace('ec2_tag_', '')
+ assert tagkey in btags, '%s tag not in b file host tags' % tagkey
+ assert value == btags[tagkey], '%s != %s' % (value, btags[tagkey])
+ else:
+ print('assert var', key, value, key in plugin['_meta']['hostvars'][host], plugin['_meta']['hostvars'][host].get(key))
+ assert key in plugin['_meta']['hostvars'][host], "%s not in b's %s hostvars" % (key, host)
+ assert value == plugin['_meta']['hostvars'][host][key], "%s != %s" % (value, plugin['_meta']['hostvars'][host][key])
+
+
+def main():
+ # a should be the source of truth (the script output)
+ a = sys.argv[1]
+ # b should be the thing to check (the plugin output)
+ b = sys.argv[2]
+
+ with open(a, 'r') as f:
+ adata = json.loads(f.read())
+ with open(b, 'r') as f:
+ bdata = json.loads(f.read())
+
+ print(adata)
+ print(bdata)
+
+ # all hosts should be present obviously
+ ahosts, bhosts = check_hosts(adata, bdata)
+
+ # all groups should be present obviously
+ agroups, bgroups = check_groups(adata, bdata)
+
+ # check host vars can be reconstructed
+ for ahost in ahosts:
+ contrib_host_vars = adata['_meta']['hostvars'][ahost]
+ for key, value in contrib_host_vars.items():
+ check_host_vars(key, value, bdata, ahost)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/runme.sh b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/runme.sh
new file mode 100755
index 00000000..ea163ab1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/runme.sh
@@ -0,0 +1,70 @@
+#!/usr/bin/env bash
+
+if [[ $(python --version 2>&1) =~ 2\.6 ]]
+ then
+ echo "Openshift client is not supported on Python 2.6"
+ exit 0
+fi
+
+set -eux
+
+# TODO: quay.io/ansible/default-test-container:2.7.0 doesn't have virtualenv included
+apt -y update
+apt -y install python3-virtualenv
+
+source virtualenv.sh
+pip install openshift -c constraints.txt
+
+./server.py &
+
+cleanup() {
+ kill -9 "$(jobs -p)"
+}
+
+trap cleanup INT TERM EXIT
+
+# Fake auth file
+mkdir -p ~/.kube/
+cat <<EOF > ~/.kube/config
+apiVersion: v1
+clusters:
+- cluster:
+ insecure-skip-tls-verify: true
+ server: http://localhost:12345
+ name: development
+contexts:
+- context:
+ cluster: development
+ user: developer
+ name: dev-frontend
+current-context: dev-frontend
+kind: Config
+preferences: {}
+users:
+- name: developer
+ user:
+ token: ZDNg7LzSlp8a0u0fht_tRnPMTOjxqgJGCyi_iy0ecUw
+EOF
+
+#################################################
+# RUN THE PLUGIN
+#################################################
+
+# run the plugin second
+export ANSIBLE_INVENTORY_ENABLED=community.kubevirt.kubevirt
+export ANSIBLE_INVENTORY=test.kubevirt.yml
+
+cat << EOF > "$OUTPUT_DIR/test.kubevirt.yml"
+plugin: community.kubevirt.kubevirt
+connections:
+ - namespaces:
+ - default
+EOF
+
+ANSIBLE_JINJA2_NATIVE=1 ansible-inventory -vvvv -i "$OUTPUT_DIR/test.kubevirt.yml" --list --output="$OUTPUT_DIR/plugin.out"
+
+#################################################
+# DIFF THE RESULTS
+#################################################
+
+./inventory_diff.py "$(pwd)/test.out" "$OUTPUT_DIR/plugin.out"
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/server.py b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/server.py
new file mode 100755
index 00000000..376889e7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/server.py
@@ -0,0 +1,163 @@
+#!/usr/bin/env python
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+import os
+
+try:
+ from http.server import HTTPServer
+ from http.server import SimpleHTTPRequestHandler
+except ImportError:
+ from BaseHTTPServer import HTTPServer
+ from SimpleHTTPServer import SimpleHTTPRequestHandler
+
+from threading import Thread
+
+try:
+ from urllib.parse import urlparse
+except ImportError:
+ from urlparse import urlparse
+
+
+class TestHandler(SimpleHTTPRequestHandler):
+ # Path handlers:
+ handlers = {}
+
+ def log_message(self, format, *args):
+ """
+ Empty method, so we don't mix output of HTTP server with tests
+ """
+ pass
+
+ def do_GET(self):
+ params = urlparse(self.path)
+
+ if params.path in self.handlers:
+ self.handlers[params.path](self)
+ else:
+ SimpleHTTPRequestHandler.do_GET(self)
+
+ def do_POST(self):
+ params = urlparse(self.path)
+
+ if params.path in self.handlers:
+ self.handlers[params.path](self)
+ else:
+ SimpleHTTPRequestHandler.do_POST(self)
+
+
+class TestServer(object):
+ # The host and port and path used by the embedded tests web server:
+ PORT = None
+
+ # The embedded web server:
+ _httpd = None
+ # Thread for http server:
+ _thread = None
+
+ def set_json_response(self, path, code, body):
+ def _handle_request(handler):
+ handler.send_response(code)
+ handler.send_header('Content-Type', 'application/json')
+ handler.end_headers()
+
+ data = json.dumps(body, ensure_ascii=False).encode('utf-8')
+ handler.wfile.write(data)
+
+ TestHandler.handlers[path] = _handle_request
+
+ def start_server(self, host='localhost'):
+ self._httpd = HTTPServer((host, 12345), TestHandler)
+ self._thread = Thread(target=self._httpd.serve_forever)
+ self._thread.start()
+
+ def stop_server(self):
+ self._httpd.shutdown()
+ self._thread.join()
+
+
+if __name__ == '__main__':
+ print(os.getpid())
+ server = TestServer()
+ server.start_server()
+ server.set_json_response(path="/version", code=200, body={})
+ server.set_json_response(path="/api", code=200, body={
+ "kind": "APIVersions", "versions": ["v1"], "serverAddressByClientCIDRs": [{"clientCIDR": "0.0.0.0/0", "serverAddress": "localhost:12345"}]
+ })
+ server.set_json_response(path="/api/v1", code=200, body={'resources': {}})
+ server.set_json_response(path="/apis", code=200, body={
+ "kind": "APIGroupList", "apiVersion": "v1",
+ "groups": [{
+ "name": "kubevirt.io", "versions": [{"groupVersion": "kubevirt.io/v1alpha3", "version": "v1alpha3"}],
+ "preferredVersion": {"groupVersion": "kubevirt.io/v1alpha3", "version": "v1alpha3"}
+ }]
+ })
+ server.set_json_response(
+ path="/apis/kubevirt.io/v1alpha3",
+ code=200,
+ body={
+ "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "kubevirt.io/v1alpha3",
+ "resources": [{
+ "name": "virtualmachineinstances", "singularName": "virtualmachineinstance",
+ "namespaced": True, "kind": "VirtualMachineInstance",
+ "verbs": ["delete", "deletecollection", "get", "list", "patch", "create", "update", "watch"],
+ "shortNames":["vmi", "vmis"]
+ }]
+ }
+ )
+ server.set_json_response(
+ path="/apis/kubevirt.io/v1alpha3/namespaces/default/virtualmachineinstances",
+ code=200,
+ body={'apiVersion': 'kubevirt.io/v1alpha3',
+ 'items': [{'apiVersion': 'kubevirt.io/v1alpha3',
+ 'kind': 'VirtualMachineInstance',
+ 'metadata': {'annotations': {'ansible': '{"data1": "yes", "data2": "no"}'},
+ 'creationTimestamp': '2019-04-05T14:17:02Z',
+ 'generateName': 'myvm',
+ 'generation': 1,
+ 'labels': {'kubevirt.io/nodeName': 'localhost',
+ 'label': 'x',
+ 'vm.cnv.io/name': 'myvm'},
+ 'name': 'myvm',
+ 'namespace': 'default',
+ 'ownerReferences': [{'apiVersion': 'kubevirt.io/v1alpha3',
+ 'blockOwnerDeletion': True,
+ 'controller': True,
+ 'kind': 'VirtualMachine',
+ 'name': 'myvm',
+ 'uid': 'f78ebe62-5666-11e9-a214-0800279ffc6b'}],
+ 'resourceVersion': '1614085',
+ 'selfLink': '/apis/kubevirt.io/v1alpha3/namespaces/default/virtualmachineinstances/myvm',
+ 'uid': '7ba1b196-57ad-11e9-9e2e-0800279ffc6b'},
+ 'spec': {'domain': {'devices': {'disks': [{'disk': {'bus': 'virtio'},
+ 'name': 'containerdisk'},
+ {'disk': {'bus': 'virtio'}, 'name': 'ansiblecloudinitdisk'}],
+ 'interfaces': [{'bridge': {}, 'name': 'default'}]},
+ 'firmware': {'uuid': 'cdf77e9e-871b-5acb-a707-80ef3d4b9849'},
+ 'machine': {'type': ''},
+ 'resources': {'requests': {'memory': '64M'}}},
+ 'networks': [{'name': 'default', 'pod': {}}],
+ 'volumes': [{'containerDisk': {'image': 'kubevirt/cirros-container-disk-demo:v0.11.0'},
+ 'name': 'containerdisk'},
+ {'cloudInitNoCloud': {'userData': '#cloud-config\npassword: password\nchpasswd: { expire: False }'},
+ 'name': 'ansiblecloudinitdisk'}]},
+ 'status': {'conditions': [{'lastProbeTime': None,
+ 'lastTransitionTime': None,
+ 'status': 'True',
+ 'type': 'LiveMigratable'},
+ {'lastProbeTime': None,
+ 'lastTransitionTime': '2019-04-05T14:17:27Z',
+ 'status': 'True',
+ 'type': 'Ready'}],
+ 'interfaces': [{'ipAddress': '172.17.0.19',
+ 'mac': '02:42:ac:11:00:13',
+ 'name': 'default'}],
+ 'migrationMethod': 'BlockMigration',
+ 'nodeName': 'localhost',
+ 'phase': 'Running'}}],
+ 'kind': 'VirtualMachineInstanceList',
+ 'metadata': {'continue': '',
+ 'resourceVersion': '1614862',
+ 'selfLink': '/apis/kubevirt.io/v1alpha3/namespaces/default/virtualmachineinstances'}}
+ )
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/test.out b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/test.out
new file mode 100644
index 00000000..932aade0
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/integration/targets/inventory_kubevirt/test.out
@@ -0,0 +1,61 @@
+{
+ "_meta": {
+ "hostvars": {
+ "default-myvm-7ba1b196-57ad-11e9-9e2e-0800279ffc6b": {
+ "annotations": {
+ "ansible": "{\"data1\": \"yes\", \"data2\": \"no\"}"
+ },
+ "ansible_host": "172.17.0.19",
+ "data1": "yes",
+ "data2": "no",
+ "labels": {
+ "kubevirt.io/nodeName": "localhost",
+ "label": "x",
+ "vm.cnv.io/name": "myvm"
+ },
+ "object_type": "vm",
+ "resource_version": "1614085",
+ "uid": "7ba1b196-57ad-11e9-9e2e-0800279ffc6b"
+ }
+ }
+ },
+ "all": {
+ "children": [
+ "label_kubevirt_io_nodeName_localhost",
+ "label_label_x",
+ "label_vm_cnv_io_name_myvm",
+ "localhost_12345",
+ "ungrouped"
+ ]
+ },
+ "label_kubevirt_io_nodeName_localhost": {
+ "hosts": [
+ "default-myvm-7ba1b196-57ad-11e9-9e2e-0800279ffc6b"
+ ]
+ },
+ "label_label_x": {
+ "hosts": [
+ "default-myvm-7ba1b196-57ad-11e9-9e2e-0800279ffc6b"
+ ]
+ },
+ "label_vm_cnv_io_name_myvm": {
+ "hosts": [
+ "default-myvm-7ba1b196-57ad-11e9-9e2e-0800279ffc6b"
+ ]
+ },
+ "localhost_12345": {
+ "children": [
+ "namespace_default"
+ ]
+ },
+ "namespace_default": {
+ "children": [
+ "namespace_default_vms"
+ ]
+ },
+ "namespace_default_vms": {
+ "hosts": [
+ "default-myvm-7ba1b196-57ad-11e9-9e2e-0800279ffc6b"
+ ]
+ }
+}
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.10.txt b/collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.10.txt
new file mode 100644
index 00000000..63be782b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.10.txt
@@ -0,0 +1,20 @@
+plugins/modules/kubevirt_cdi_upload.py validate-modules:doc-missing-type
+plugins/modules/kubevirt_cdi_upload.py validate-modules:doc-required-mismatch
+plugins/modules/kubevirt_cdi_upload.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_cdi_upload.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_preset.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_preset.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_preset.py validate-modules:parameter-type-not-in-doc
+plugins/modules/kubevirt_pvc.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_pvc.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_pvc.py validate-modules:parameter-type-not-in-doc
+plugins/modules/kubevirt_pvc.py validate-modules:return-syntax-error
+plugins/modules/kubevirt_rs.py validate-modules:doc-required-mismatch
+plugins/modules/kubevirt_rs.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_rs.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_rs.py validate-modules:parameter-type-not-in-doc
+plugins/modules/kubevirt_template.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_template.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_vm.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_vm.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_vm.py validate-modules:parameter-type-not-in-doc
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.11.txt b/collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.11.txt
new file mode 100644
index 00000000..63be782b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.11.txt
@@ -0,0 +1,20 @@
+plugins/modules/kubevirt_cdi_upload.py validate-modules:doc-missing-type
+plugins/modules/kubevirt_cdi_upload.py validate-modules:doc-required-mismatch
+plugins/modules/kubevirt_cdi_upload.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_cdi_upload.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_preset.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_preset.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_preset.py validate-modules:parameter-type-not-in-doc
+plugins/modules/kubevirt_pvc.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_pvc.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_pvc.py validate-modules:parameter-type-not-in-doc
+plugins/modules/kubevirt_pvc.py validate-modules:return-syntax-error
+plugins/modules/kubevirt_rs.py validate-modules:doc-required-mismatch
+plugins/modules/kubevirt_rs.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_rs.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_rs.py validate-modules:parameter-type-not-in-doc
+plugins/modules/kubevirt_template.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_template.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_vm.py validate-modules:mutually_exclusive-unknown
+plugins/modules/kubevirt_vm.py validate-modules:parameter-list-no-elements
+plugins/modules/kubevirt_vm.py validate-modules:parameter-type-not-in-doc
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.9.txt b/collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.9.txt
new file mode 100644
index 00000000..beccb65d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/sanity/ignore-2.9.txt
@@ -0,0 +1,5 @@
+plugins/modules/kubevirt_cdi_upload.py validate-modules:doc-missing-type
+plugins/modules/kubevirt_preset.py validate-modules:parameter-type-not-in-doc
+plugins/modules/kubevirt_pvc.py validate-modules:parameter-type-not-in-doc
+plugins/modules/kubevirt_rs.py validate-modules:parameter-type-not-in-doc
+plugins/modules/kubevirt_vm.py validate-modules:parameter-type-not-in-doc
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/compat/__init__.py b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/compat/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/compat/__init__.py
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/compat/mock.py b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/compat/mock.py
new file mode 100644
index 00000000..0972cd2e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/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/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/compat/unittest.py b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/compat/unittest.py
new file mode 100644
index 00000000..98f08ad6
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/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/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/module_utils/test_kubevirt.py b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/module_utils/test_kubevirt.py
new file mode 100644
index 00000000..5cec7d4e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/module_utils/test_kubevirt.py
@@ -0,0 +1,54 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+import pytest
+
+from ansible_collections.community.kubevirt.plugins.module_utils import kubevirt as mymodule
+
+
+def test_simple_merge_dicts():
+ dict1 = {'labels': {'label1': 'value'}}
+ dict2 = {'labels': {'label2': 'value'}}
+ dict3 = json.dumps({'labels': {'label1': 'value', 'label2': 'value'}}, sort_keys=True)
+ assert dict3 == json.dumps(dict(mymodule.KubeVirtRawModule.merge_dicts(dict1, dict2)), sort_keys=True)
+
+
+def test_simple_multi_merge_dicts():
+ dict1 = {'labels': {'label1': 'value', 'label3': 'value'}}
+ dict2 = {'labels': {'label2': 'value'}}
+ dict3 = json.dumps({'labels': {'label1': 'value', 'label2': 'value', 'label3': 'value'}}, sort_keys=True)
+ assert dict3 == json.dumps(dict(mymodule.KubeVirtRawModule.merge_dicts(dict1, dict2)), sort_keys=True)
+
+
+def test_double_nested_merge_dicts():
+ dict1 = {'metadata': {'labels': {'label1': 'value', 'label3': 'value'}}}
+ dict2 = {'metadata': {'labels': {'label2': 'value'}}}
+ dict3 = json.dumps({'metadata': {'labels': {'label1': 'value', 'label2': 'value', 'label3': 'value'}}}, sort_keys=True)
+ assert dict3 == json.dumps(dict(mymodule.KubeVirtRawModule.merge_dicts(dict1, dict2)), sort_keys=True)
+
+
+@pytest.mark.parametrize("lval, operations, rval, result", [
+ ('v1', ['<', '<='], 'v2', True),
+ ('v1', ['>', '>=', '=='], 'v2', False),
+ ('v1', ['>'], 'v1alpha1', True),
+ ('v1', ['==', '<', '<='], 'v1alpha1', False),
+ ('v1beta5', ['==', '<=', '>='], 'v1beta5', True),
+ ('v1beta5', ['<', '>', '!='], 'v1beta5', False),
+
+])
+def test_kubeapiversion_comparisons(lval, operations, rval, result):
+ KubeAPIVersion = mymodule.KubeAPIVersion
+ for op in operations:
+ test = '(KubeAPIVersion("{0}") {1} KubeAPIVersion("{2}")) == {3}'.format(lval, op, rval, result)
+ assert eval(test)
+
+
+@pytest.mark.parametrize("ver", ('nope', 'v1delta7', '1.5', 'v1beta', 'v'))
+def test_kubeapiversion_unsupported_versions(ver):
+ threw = False
+ try:
+ mymodule.KubeAPIVersion(ver)
+ except ValueError:
+ threw = True
+ assert threw
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/__init__.py b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/__init__.py
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/kubevirt_fixtures.py b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/kubevirt_fixtures.py
new file mode 100644
index 00000000..645c70ca
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/kubevirt_fixtures.py
@@ -0,0 +1,74 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import pytest
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.community.kubevirt.tests.unit.compat.mock import MagicMock
+
+from ansible_collections.community.kubernetes.plugins.module_utils.common import K8sAnsibleMixin
+from ansible_collections.community.kubernetes.plugins.module_utils.raw import KubernetesRawModule
+from ansible_collections.community.kubevirt.plugins.module_utils.kubevirt import KubeVirtRawModule
+
+import openshift.dynamic
+
+RESOURCE_DEFAULT_ARGS = {'api_version': 'v1alpha3', 'group': 'kubevirt.io',
+ 'prefix': 'apis', 'namespaced': True}
+
+
+class AnsibleExitJson(Exception):
+ """Exception class to be raised by module.exit_json and caught
+ by the test case"""
+ def __init__(self, **kwargs):
+ for k in kwargs:
+ setattr(self, k, kwargs[k])
+
+ def __getitem__(self, attr):
+ return getattr(self, attr)
+
+
+class AnsibleFailJson(Exception):
+ """Exception class to be raised by module.fail_json and caught
+ by the test case"""
+ def __init__(self, **kwargs):
+ for k in kwargs:
+ setattr(self, k, kwargs[k])
+
+ def __getitem__(self, attr):
+ return getattr(self, attr)
+
+
+def exit_json(*args, **kwargs):
+ kwargs['success'] = True
+ if 'changed' not in kwargs:
+ kwargs['changed'] = False
+ raise AnsibleExitJson(**kwargs)
+
+
+def fail_json(*args, **kwargs):
+ kwargs['success'] = False
+ raise AnsibleFailJson(**kwargs)
+
+
+@pytest.fixture()
+def base_fixture(monkeypatch):
+ monkeypatch.setattr(
+ AnsibleModule, "exit_json", exit_json)
+ monkeypatch.setattr(
+ AnsibleModule, "fail_json", fail_json)
+ # Create mock methods in Resource directly, otherwise dyn client
+ # tries binding those to corresponding methods in DynamicClient
+ # (with partial()), which is more problematic to intercept
+ openshift.dynamic.Resource.get = MagicMock()
+ openshift.dynamic.Resource.create = MagicMock()
+ openshift.dynamic.Resource.delete = MagicMock()
+ openshift.dynamic.Resource.patch = MagicMock()
+ openshift.dynamic.Resource.search = MagicMock()
+ openshift.dynamic.Resource.watch = MagicMock()
+ # Globally mock some methods, since all tests will use this
+ KubernetesRawModule.patch_resource = MagicMock()
+ KubernetesRawModule.patch_resource.return_value = ({}, None)
+ K8sAnsibleMixin.get_api_client = MagicMock()
+ K8sAnsibleMixin.get_api_client.return_value = None
+ K8sAnsibleMixin.find_resource = MagicMock()
+ KubeVirtRawModule.find_supported_resource = MagicMock()
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/test_kubevirt_rs.py b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/test_kubevirt_rs.py
new file mode 100644
index 00000000..b9425ee9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/test_kubevirt_rs.py
@@ -0,0 +1,78 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import pytest
+
+openshiftdynamic = pytest.importorskip("openshift.dynamic")
+
+from ansible_collections.community.kubevirt.tests.unit.plugins.modules.utils import set_module_args
+from .kubevirt_fixtures import base_fixture, RESOURCE_DEFAULT_ARGS, AnsibleExitJson
+
+from ansible_collections.community.kubernetes.plugins.module_utils.raw import KubernetesRawModule
+from ansible_collections.community.kubevirt.plugins.modules import kubevirt_rs as mymodule
+
+KIND = 'VirtualMachineInstanceReplicaSet'
+
+
+@pytest.mark.usefixtures("base_fixture")
+@pytest.mark.parametrize("_replicas, _changed", ((1, True),
+ (3, True),
+ (2, False),
+ (5, True),))
+def test_scale_rs_nowait(_replicas, _changed):
+ _name = 'test-rs'
+ # Desired state:
+ args = dict(name=_name, namespace='vms', replicas=_replicas, wait=False)
+ set_module_args(args)
+
+ # Mock pre-change state:
+ resource_args = dict(kind=KIND, **RESOURCE_DEFAULT_ARGS)
+ mymodule.KubeVirtVMIRS.find_supported_resource.return_value = openshiftdynamic.Resource(**resource_args)
+ res_inst = openshiftdynamic.ResourceInstance('', dict(kind=KIND, metadata={'name': _name}, spec={'replicas': 2}))
+ openshiftdynamic.Resource.get.return_value = res_inst
+ openshiftdynamic.Resource.search.return_value = [res_inst]
+
+ # Final state, after patching the object
+ KubernetesRawModule.patch_resource.return_value = dict(kind=KIND, metadata={'name': _name},
+ spec={'replicas': _replicas}), None
+
+ # Run code:
+ with pytest.raises(AnsibleExitJson) as result:
+ mymodule.KubeVirtVMIRS().execute_module()
+
+ # Verify result:
+ assert result.value['changed'] == _changed
+
+
+@pytest.mark.usefixtures("base_fixture")
+@pytest.mark.parametrize("_replicas, _success", ((1, False),
+ (2, False),
+ (5, True),))
+def test_scale_rs_wait(_replicas, _success):
+ _name = 'test-rs'
+ # Desired state:
+ args = dict(name=_name, namespace='vms', replicas=5, wait=True)
+ set_module_args(args)
+
+ # Mock pre-change state:
+ resource_args = dict(kind=KIND, **RESOURCE_DEFAULT_ARGS)
+ mymodule.KubeVirtVMIRS.find_supported_resource.return_value = openshiftdynamic.Resource(**resource_args)
+ res_inst = openshiftdynamic.ResourceInstance('', dict(kind=KIND, metadata={'name': _name}, spec={'replicas': 2}))
+ openshiftdynamic.Resource.get.return_value = res_inst
+ openshiftdynamic.Resource.search.return_value = [res_inst]
+
+ # ~Final state, after patching the object (`replicas` match desired state)
+ KubernetesRawModule.patch_resource.return_value = dict(kind=KIND, name=_name, metadata={'name': _name},
+ spec={'replicas': 5}), None
+
+ # Final final state, as returned by resource.watch()
+ final_obj = dict(metadata=dict(name=_name), status=dict(readyReplicas=_replicas), **resource_args)
+ event = openshiftdynamic.ResourceInstance(None, final_obj)
+ openshiftdynamic.Resource.watch.return_value = [dict(object=event)]
+
+ # Run code:
+ with pytest.raises(Exception) as result:
+ mymodule.KubeVirtVMIRS().execute_module()
+
+ # Verify result:
+ assert result.value['success'] == _success
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/test_kubevirt_vm.py b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/test_kubevirt_vm.py
new file mode 100644
index 00000000..975876e7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/test_kubevirt_vm.py
@@ -0,0 +1,113 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import pytest
+
+openshiftdynamic = pytest.importorskip("openshift.dynamic")
+
+from ansible_collections.community.kubevirt.tests.unit.plugins.modules.utils import set_module_args
+from .kubevirt_fixtures import base_fixture, RESOURCE_DEFAULT_ARGS, AnsibleExitJson
+
+from ansible_collections.community.kubevirt.plugins.module_utils.kubevirt import KubeVirtRawModule
+from ansible_collections.community.kubevirt.plugins.modules import kubevirt_vm as mymodule
+
+KIND = 'VirtulMachine'
+
+
+@pytest.mark.usefixtures("base_fixture")
+def test_create_vm_with_multus_nowait():
+ # Desired state:
+ args = dict(
+ state='present', name='testvm',
+ namespace='vms',
+ interfaces=[
+ {'bridge': {}, 'name': 'default', 'network': {'pod': {}}},
+ {'bridge': {}, 'name': 'mynet', 'network': {'multus': {'networkName': 'mynet'}}},
+ ],
+ wait=False,
+ )
+ set_module_args(args)
+
+ # State as "returned" by the "k8s cluster":
+ resource_args = dict(kind=KIND, **RESOURCE_DEFAULT_ARGS)
+ KubeVirtRawModule.find_supported_resource.return_value = openshiftdynamic.Resource(**resource_args)
+ openshiftdynamic.Resource.get.return_value = None # Object doesn't exist in the cluster
+
+ # Run code:
+ with pytest.raises(AnsibleExitJson) as result:
+ mymodule.KubeVirtVM().execute_module()
+
+ # Verify result:
+ assert result.value['changed']
+ assert result.value['method'] == 'create'
+
+
+@pytest.mark.usefixtures("base_fixture")
+@pytest.mark.parametrize("_wait", (False, True))
+def test_vm_is_absent(_wait):
+ # Desired state:
+ args = dict(
+ state='absent', name='testvmi',
+ namespace='vms',
+ wait=_wait,
+ )
+ set_module_args(args)
+
+ # State as "returned" by the "k8s cluster":
+ resource_args = dict(kind=KIND, **RESOURCE_DEFAULT_ARGS)
+ KubeVirtRawModule.find_supported_resource.return_value = openshiftdynamic.Resource(**resource_args)
+ openshiftdynamic.Resource.get.return_value = None # Object doesn't exist in the cluster
+
+ # Run code:
+ with pytest.raises(AnsibleExitJson) as result:
+ mymodule.KubeVirtVM().execute_module()
+
+ # Verify result:
+ assert not result.value['kubevirt_vm']
+ assert result.value['method'] == 'delete'
+ # Note: nothing actually gets deleted, as we mock that there's not object in the cluster present,
+ # so if the method changes to something other than 'delete' at some point, that's fine
+
+
+@pytest.mark.usefixtures("base_fixture")
+def test_vmpreset_create():
+ KIND = 'VirtulMachineInstancePreset'
+ # Desired state:
+ args = dict(state='present', name='testvmipreset', namespace='vms', memory='1024Mi', wait=False)
+ set_module_args(args)
+
+ # State as "returned" by the "k8s cluster":
+ resource_args = dict(kind=KIND, **RESOURCE_DEFAULT_ARGS)
+ KubeVirtRawModule.find_supported_resource.return_value = openshiftdynamic.Resource(**resource_args)
+ openshiftdynamic.Resource.get.return_value = None # Object doesn't exist in the cluster
+
+ # Run code:
+ with pytest.raises(AnsibleExitJson) as result:
+ mymodule.KubeVirtVM().execute_module()
+
+ # Verify result:
+ assert result.value['changed']
+ assert result.value['method'] == 'create'
+
+
+@pytest.mark.usefixtures("base_fixture")
+def test_vmpreset_is_absent():
+ KIND = 'VirtulMachineInstancePreset'
+ # Desired state:
+ args = dict(state='absent', name='testvmipreset', namespace='vms')
+ set_module_args(args)
+
+ # State as "returned" by the "k8s cluster":
+ resource_args = dict(kind=KIND, **RESOURCE_DEFAULT_ARGS)
+ KubeVirtRawModule.find_supported_resource.return_value = openshiftdynamic.Resource(**resource_args)
+ openshiftdynamic.Resource.get.return_value = None # Object doesn't exist in the cluster
+
+ # Run code:
+ with pytest.raises(AnsibleExitJson) as result:
+ mymodule.KubeVirtVM().execute_module()
+
+ # Verify result:
+ assert not result.value['kubevirt_vm']
+ assert result.value['method'] == 'delete'
+ # Note: nothing actually gets deleted, as we mock that there's not object in the cluster present,
+ # so if the method changes to something other than 'delete' at some point, that's fine
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/utils.py b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/utils.py
new file mode 100644
index 00000000..a340d28d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/plugins/modules/utils.py
@@ -0,0 +1,52 @@
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+
+from ansible_collections.community.kubevirt.tests.unit.compat import unittest
+from ansible_collections.community.kubevirt.tests.unit.compat.mock import patch
+from ansible.module_utils import basic
+from ansible.module_utils._text import to_bytes
+
+
+def set_module_args(args):
+ if '_ansible_remote_tmp' not in args:
+ args['_ansible_remote_tmp'] = '/tmp'
+ if '_ansible_keep_remote_files' not in args:
+ args['_ansible_keep_remote_files'] = False
+
+ args = json.dumps({'ANSIBLE_MODULE_ARGS': args})
+ basic._ANSIBLE_ARGS = to_bytes(args)
+
+
+class AnsibleExitJson(Exception):
+ pass
+
+
+class AnsibleFailJson(Exception):
+ pass
+
+
+def exit_json(*args, **kwargs):
+ if 'changed' not in kwargs:
+ kwargs['changed'] = False
+ raise AnsibleExitJson(kwargs)
+
+
+def fail_json(*args, **kwargs):
+ kwargs['failed'] = True
+ raise AnsibleFailJson(kwargs)
+
+
+class ModuleTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_module = patch.multiple(basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json)
+ self.mock_module.start()
+ self.mock_sleep = patch('time.sleep')
+ self.mock_sleep.start()
+ set_module_args({})
+ self.addCleanup(self.mock_module.stop)
+ self.addCleanup(self.mock_sleep.stop)
diff --git a/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/requirements.txt b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/requirements.txt
new file mode 100644
index 00000000..73fafe55
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/kubevirt/tests/unit/requirements.txt
@@ -0,0 +1,2 @@
+# requirement for kubevirt modules
+openshift ; python_version >= '2.7'