diff --git a/README.md b/README.md index df82141..f6665be 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,6 @@ ansible-galaxy collection install -r requirements.yml #### Python libraries -- jinja2 - jsonpatch - kubernetes>=28.1.0 - PyYAML>=3.11 diff --git a/plugins/modules/kubevirt_vm.py b/plugins/modules/kubevirt_vm.py index 676f66d..9199f55 100644 --- a/plugins/modules/kubevirt_vm.py +++ b/plugins/modules/kubevirt_vm.py @@ -151,7 +151,6 @@ requirements: - "kubernetes >= 28.1.0" - "PyYAML >= 3.11" - "jsonpatch" -- "jinja2" """ EXAMPLES = """ @@ -263,7 +262,6 @@ result: from copy import deepcopy from typing import Dict -import traceback from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import ( AnsibleModule, @@ -282,91 +280,48 @@ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions imp CoreException, ) -try: - import yaml -except ImportError: - HAS_YAML = False - YAML_IMPORT_ERROR = traceback.format_exc() -else: - HAS_YAML = True - YAML_IMPORT_ERROR = None -try: - from jinja2 import Environment -except ImportError: - HAS_JINJA = False - JINJA_IMPORT_ERROR = traceback.format_exc() -else: - HAS_JINJA = True - JINJA_IMPORT_ERROR = None - - -VM_TEMPLATE = """ -apiVersion: {{ api_version }} -kind: VirtualMachine -metadata: - {% if name %} - name: {{ name }} - {% endif %} - {% if generate_name %} - generateName: {{ generate_name }} - {% endif %} - namespace: {{ namespace }} - {% if annotations %} - annotations: - {{ annotations | to_yaml | indent(4) }} - {%- endif %} - {% if labels %} - labels: - {{ labels | to_yaml | indent(4) }} - {%- endif %} -spec: - running: {{ running | lower }} - {% if instancetype %} - instancetype: - {{ instancetype | to_yaml | indent(4) }} - {%- endif %} - {% if preference %} - preference: - {{ preference | to_yaml | indent(4) }} - {%- endif %} - {% if data_volume_templates %} - dataVolumeTemplates: - {{ data_volume_templates | to_yaml | indent(2) }} - {%- endif %} - template: - {% if annotations or labels %} - metadata: - {% if annotations %} - annotations: - {{ annotations | to_yaml | indent(8) }} - {%- endif %} - {% if labels %} - labels: - {{ labels | to_yaml | indent(8) }} - {%- endif %} - {% endif %} - spec: - {% if spec %} - {{ spec | to_yaml | indent (6) }} - {%- else %} - domain: - devices: {} - {% endif %} -""" - - -def render_template(params: Dict) -> str: +def create_vm(params: Dict) -> Dict: """ - render_template uses Jinja2 to render the VM_TEMPLATE into a string. + create_vm constructs a VM from the module parameters. """ - env = Environment(autoescape=False, trim_blocks=True, lstrip_blocks=True) - env.filters["to_yaml"] = lambda data, *_, **kw: yaml.dump( - data, allow_unicode=True, default_flow_style=False, **kw - ) + vm = { + "apiVersion": params["api_version"], + "kind": "VirtualMachine", + "metadata": { + "namespace": params["namespace"], + }, + "spec": { + "running": params["running"], + "template": {"spec": {"domain": {"devices": {}}}}, + }, + } - template = env.from_string(VM_TEMPLATE.strip()) - return template.render(params) + if (name := params.get("name")) is not None: + vm["metadata"]["name"] = name + if (generate_name := params.get("generate_name")) is not None: + vm["metadata"]["generateName"] = generate_name + + template_metadata = {} + if (annotations := params.get("annotations")) is not None: + vm["metadata"]["annotations"] = annotations + template_metadata["annotations"] = annotations + if (labels := params.get("labels")) is not None: + vm["metadata"]["labels"] = labels + template_metadata["labels"] = labels + if template_metadata: + vm["spec"]["template"]["metadata"] = template_metadata + + if (instancetype := params.get("instancetype")) is not None: + vm["spec"]["instancetype"] = instancetype + if (preference := params.get("preference")) is not None: + vm["spec"]["preference"] = preference + if (data_volume_templates := params.get("data_volume_templates")) is not None: + vm["spec"]["dataVolumeTemplates"] = data_volume_templates + if (spec := params.get("spec")) is not None: + vm["spec"]["template"]["spec"] = spec + + return vm def arg_spec() -> Dict: @@ -428,8 +383,8 @@ def main() -> None: supports_check_mode=True, ) - # Set resource_definition to our rendered template - module.params["resource_definition"] = render_template(module.params) + # Set resource_definition to our constructed VM + module.params["resource_definition"] = create_vm(module.params) # Set wait_condition to allow waiting for the ready state of the VirtualMachine if module.params["running"]: diff --git a/requirements.txt b/requirements.txt index 2e1bd6d..5ce90ad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -jinja2 jsonpatch kubernetes>=28.1.0 PyYAML>=3.11 diff --git a/tests/unit/plugins/modules/test_kubevirt_vm.py b/tests/unit/plugins/modules/test_kubevirt_vm.py index 0310285..a9ffe07 100644 --- a/tests/unit/plugins/modules/test_kubevirt_vm.py +++ b/tests/unit/plugins/modules/test_kubevirt_vm.py @@ -8,8 +8,6 @@ __metaclass__ = type import pytest -from yaml import dump - from ansible.module_utils.basic import AnsibleModule from ansible_collections.kubernetes.core.plugins.module_utils.k8s import runner from ansible_collections.kubevirt.core.plugins.modules import kubevirt_vm @@ -204,7 +202,7 @@ def module_params_delete(module_params_default): def k8s_module_params_create(module_params_create, vm_definition_create): return module_params_create | { "generate_name": None, - "resource_definition": dump(vm_definition_create, sort_keys=False), + "resource_definition": vm_definition_create, "wait_condition": {"type": "Ready", "status": True}, } @@ -213,7 +211,7 @@ def k8s_module_params_create(module_params_create, vm_definition_create): def k8s_module_params_running(module_params_running, vm_definition_running): return module_params_running | { "generate_name": None, - "resource_definition": dump(vm_definition_running, sort_keys=False), + "resource_definition": vm_definition_running, "wait_condition": {"type": "Ready", "status": True}, } @@ -222,7 +220,7 @@ def k8s_module_params_running(module_params_running, vm_definition_running): def k8s_module_params_stopped(module_params_stopped, vm_definition_stopped): return module_params_stopped | { "generate_name": None, - "resource_definition": dump(vm_definition_stopped, sort_keys=False), + "resource_definition": vm_definition_stopped, "wait_condition": {"type": "Ready", "status": False, "reason": "VMINotExists"}, } @@ -231,7 +229,7 @@ def k8s_module_params_stopped(module_params_stopped, vm_definition_stopped): def k8s_module_params_delete(module_params_delete, vm_definition_running): return module_params_delete | { "generate_name": None, - "resource_definition": dump(vm_definition_running, sort_keys=False), + "resource_definition": vm_definition_running, "wait_condition": {"type": "Ready", "status": True}, } @@ -305,7 +303,7 @@ def test_module( @pytest.fixture(scope="module") -def render_template_params(): +def create_vm_params(): return { "api_version": "kubevirt.io/v1", "running": True, @@ -314,36 +312,36 @@ def render_template_params(): @pytest.fixture(scope="module") -def render_template_params_annotations(render_template_params): - return render_template_params | { +def create_vm_params_annotations(create_vm_params): + return create_vm_params | { "annotations": {"test": "test"}, } @pytest.fixture(scope="module") -def render_template_params_labels(render_template_params): - return render_template_params | { +def create_vm_params_labels(create_vm_params): + return create_vm_params | { "labels": {"test": "test"}, } @pytest.fixture(scope="module") -def render_template_params_instancetype(render_template_params): - return render_template_params | { +def create_vm_params_instancetype(create_vm_params): + return create_vm_params | { "instancetype": {"name": "u1.medium"}, } @pytest.fixture(scope="module") -def render_template_params_preference(render_template_params): - return render_template_params | { +def create_vm_params_preference(create_vm_params): + return create_vm_params | { "preference": {"name": "fedora"}, } @pytest.fixture(scope="module") -def render_template_params_datavolumetemplate(render_template_params): - return render_template_params | { +def create_vm_params_datavolumetemplate(create_vm_params): + return create_vm_params | { "data_volume_templates": [ { "metadata": {"name": "testdv"}, @@ -364,22 +362,22 @@ def render_template_params_datavolumetemplate(render_template_params): @pytest.fixture(scope="module") -def render_template_params_name(render_template_params): - return render_template_params | { +def create_vm_params_name(create_vm_params): + return create_vm_params | { "name": "testvm", } @pytest.fixture(scope="module") -def render_template_params_generate_name(render_template_params): - return render_template_params | { +def create_vm_params_generate_name(create_vm_params): + return create_vm_params | { "generate_name": "testvm-1234", } @pytest.fixture(scope="module") -def render_template_params_specs(render_template_params): - return render_template_params | { +def create_vm_params_specs(create_vm_params): + return create_vm_params | { "spec": { "domain": { "devices": { @@ -395,7 +393,7 @@ def render_template_params_specs(render_template_params): @pytest.fixture(scope="module") -def vm_template(): +def created_vm(): return { "apiVersion": "kubevirt.io/v1", "kind": "VirtualMachine", @@ -416,7 +414,7 @@ def vm_template(): @pytest.fixture(scope="module") -def vm_template_labels(): +def created_vm_labels(): return { "apiVersion": "kubevirt.io/v1", "kind": "VirtualMachine", @@ -443,7 +441,7 @@ def vm_template_labels(): @pytest.fixture(scope="module") -def vm_template_annotations(): +def created_vm_annotations(): return { "apiVersion": "kubevirt.io/v1", "kind": "VirtualMachine", @@ -470,7 +468,7 @@ def vm_template_annotations(): @pytest.fixture(scope="module") -def vm_template_instancetype(): +def created_vm_instancetype(): return { "apiVersion": "kubevirt.io/v1", "kind": "VirtualMachine", @@ -492,7 +490,7 @@ def vm_template_instancetype(): @pytest.fixture(scope="module") -def vm_template_preference(): +def created_vm_preference(): return { "apiVersion": "kubevirt.io/v1", "kind": "VirtualMachine", @@ -514,7 +512,7 @@ def vm_template_preference(): @pytest.fixture(scope="module") -def vm_template_datavolumetemplate(): +def created_vm_datavolumetemplate(): return { "apiVersion": "kubevirt.io/v1", "kind": "VirtualMachine", @@ -551,7 +549,7 @@ def vm_template_datavolumetemplate(): @pytest.fixture(scope="module") -def vm_template_name(): +def created_vm_name(): return { "apiVersion": "kubevirt.io/v1", "kind": "VirtualMachine", @@ -573,7 +571,7 @@ def vm_template_name(): @pytest.fixture(scope="module") -def vm_template_generate_name(): +def created_vm_generate_name(): return { "apiVersion": "kubevirt.io/v1", "kind": "VirtualMachine", @@ -595,7 +593,7 @@ def vm_template_generate_name(): @pytest.fixture(scope="module") -def vm_template_specs(): +def created_vm_specs(): return { "apiVersion": "kubevirt.io/v1", "kind": "VirtualMachine", @@ -622,20 +620,20 @@ def vm_template_specs(): @pytest.mark.parametrize( - "params,rendered_template", + "params,expected", [ - ("render_template_params", "vm_template"), - ("render_template_params_annotations", "vm_template_annotations"), - ("render_template_params_labels", "vm_template_labels"), - ("render_template_params_instancetype", "vm_template_instancetype"), - ("render_template_params_preference", "vm_template_preference"), - ("render_template_params_datavolumetemplate", "vm_template_datavolumetemplate"), - ("render_template_params_name", "vm_template_name"), - ("render_template_params_generate_name", "vm_template_generate_name"), - ("render_template_params_specs", "vm_template_specs"), + ("create_vm_params", "created_vm"), + ("create_vm_params_annotations", "created_vm_annotations"), + ("create_vm_params_labels", "created_vm_labels"), + ("create_vm_params_instancetype", "created_vm_instancetype"), + ("create_vm_params_preference", "created_vm_preference"), + ("create_vm_params_datavolumetemplate", "created_vm_datavolumetemplate"), + ("create_vm_params_name", "created_vm_name"), + ("create_vm_params_generate_name", "created_vm_generate_name"), + ("create_vm_params_specs", "created_vm_specs"), ], ) -def test_render_template(request, params, rendered_template): - assert kubevirt_vm.render_template(request.getfixturevalue(params)) == dump( - request.getfixturevalue(rendered_template), sort_keys=False - ) +def test_create_vm(request, params, expected): + assert kubevirt_vm.create_vm( + request.getfixturevalue(params) + ) == request.getfixturevalue(expected) diff --git a/tests/unit/requirements.txt b/tests/unit/requirements.txt index f47f344..93e7491 100644 --- a/tests/unit/requirements.txt +++ b/tests/unit/requirements.txt @@ -1,5 +1,4 @@ # This file is required by ansible-test units -jinja2 jsonpatch kubernetes>=28.1.0 PyYAML>=3.11