From 71a88007fe776d2af55de89a4a4cf1aeab3c3a2c Mon Sep 17 00:00:00 2001 From: Felix Matouschek Date: Wed, 24 Apr 2024 16:18:39 +0200 Subject: [PATCH] feat(kubevirt_vm_info): Set wait_condition based on running Add the running parameter to kubevirt_vm_info from which the wait_condition is derived from when parameter wait is set to yes. Signed-off-by: Felix Matouschek --- plugins/modules/kubevirt_vm_info.py | 39 +++++++++++++++---- .../plugins/modules/test_kubevirt_vm_info.py | 35 ++++++++++++++++- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/plugins/modules/kubevirt_vm_info.py b/plugins/modules/kubevirt_vm_info.py index 1c931f9..3bbffb7 100644 --- a/plugins/modules/kubevirt_vm_info.py +++ b/plugins/modules/kubevirt_vm_info.py @@ -46,11 +46,19 @@ options: type: list elements: str default: [] + running: + description: + - Specify whether the VirtualMachine should be running. + - This affects the ready condition to wait for. + - This requires C(wait) and is only used when I(wait=yes). + type: bool + version_added: 1.4.0 wait: description: - Whether to wait for the VirtualMachine to end up in the ready state. + - By default this is waiting for the VirtualMachine to be up and running. + - Modify this behavior by setting C(running). type: bool - default: no wait_sleep: description: - Number of seconds to sleep between checks. @@ -94,11 +102,18 @@ EXAMPLES = """ label_selectors: - app=test -- name: Wait until the VirtualMachine is Ready +- name: Wait until the VirtualMachine is running kubevirt.core.kubevirt_vm_info: name: testvm namespace: default wait: true + +- name: Wait until the VirtualMachine is stopped + kubevirt.core.kubevirt_vm_info: + name: testvm + namespace: default + running: false + wait: true """ RETURN = """ @@ -109,7 +124,7 @@ api_found: type: bool resources: description: - - The VirtualMachine(s) that exists + - The VirtualMachine(s) that exist(s) returned: success type: complex contains: @@ -165,8 +180,12 @@ def execute_module(module, svc): # Set kind to query for VirtualMachines KIND = "VirtualMachine" - # Set wait_condition to allow waiting for the ready state of the VirtualMachine - WAIT_CONDITION = {"type": "Ready", "status": True} + # Set wait_condition to allow waiting for the ready state of the + # VirtualMachine based on the running parameter. + if module.params["running"] is None or module.params["running"]: + wait_condition = {"type": "Ready", "status": True} + else: + wait_condition = {"type": "Ready", "status": False, "reason": "VMINotExists"} facts = svc.find( kind=KIND, @@ -178,7 +197,7 @@ def execute_module(module, svc): wait=module.params["wait"], wait_sleep=module.params["wait_sleep"], wait_timeout=module.params["wait_timeout"], - condition=WAIT_CONDITION, + condition=wait_condition, ) module.exit_json(changed=False, **facts) @@ -194,7 +213,8 @@ def arg_spec(): "namespace": {}, "label_selectors": {"type": "list", "elements": "str", "default": []}, "field_selectors": {"type": "list", "elements": "str", "default": []}, - "wait": {"type": "bool", "default": False}, + "running": {"type": "bool"}, + "wait": {"type": "bool"}, "wait_sleep": {"type": "int", "default": 5}, "wait_timeout": {"type": "int", "default": 120}, } @@ -208,7 +228,10 @@ def main(): main instantiates the AnsibleK8SModule and runs the module. """ module = AnsibleK8SModule( - module_class=AnsibleModule, argument_spec=arg_spec(), supports_check_mode=True + module_class=AnsibleModule, + argument_spec=arg_spec(), + required_by={"running": "wait"}, + supports_check_mode=True, ) try: diff --git a/tests/unit/plugins/modules/test_kubevirt_vm_info.py b/tests/unit/plugins/modules/test_kubevirt_vm_info.py index b5a05a2..39d0687 100644 --- a/tests/unit/plugins/modules/test_kubevirt_vm_info.py +++ b/tests/unit/plugins/modules/test_kubevirt_vm_info.py @@ -17,7 +17,9 @@ from ansible_collections.kubevirt.core.plugins.modules import ( ) from ansible_collections.kubevirt.core.tests.unit.utils.ansible_module_mock import ( AnsibleExitJson, + AnsibleFailJson, exit_json, + fail_json, set_module_args, ) @@ -31,7 +33,7 @@ def find_args_default(): "namespace": None, "label_selectors": [], "field_selectors": [], - "wait": False, + "wait": None, "wait_sleep": 5, "wait_timeout": 120, "condition": {"type": "Ready", "status": True}, @@ -60,6 +62,35 @@ def find_args_field_selector(find_args_default): } +@pytest.fixture(scope="module") +def find_args_running(find_args_default): + return find_args_default | { + "wait": True, + "condition": {"type": "Ready", "status": True}, + } + + +@pytest.fixture(scope="module") +def find_args_stopped(find_args_default): + return find_args_default | { + "wait": True, + "condition": {"type": "Ready", "status": False, "reason": "VMINotExists"}, + } + + +@pytest.mark.parametrize( + "module_args", + [ + {"running": False}, + ], +) +def test_module_fails_when_required_args_missing(monkeypatch, module_args): + monkeypatch.setattr(AnsibleModule, "fail_json", fail_json) + with pytest.raises(AnsibleFailJson): + set_module_args(module_args) + kubevirt_vm_info.main() + + @pytest.mark.parametrize( "module_args,find_args", [ @@ -67,6 +98,8 @@ def find_args_field_selector(find_args_default): ({"name": "testvm", "namespace": "default"}, "find_args_name_namespace"), ({"label_selectors": "app=test"}, "find_args_label_selector"), ({"field_selectors": "app=test"}, "find_args_field_selector"), + ({"wait": True, "running": True}, "find_args_running"), + ({"wait": True, "running": False}, "find_args_stopped"), ], ) def test_module(request, monkeypatch, mocker, module_args, find_args):