Files
kubevirt.core/AGENTS.md
Javier Cano Cano f1f41934f7 feat(AGENTS): Add context documentation for AI agents
It adds documentation to provide context about the project to AI agents.

Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Javier Cano Cano <jcanocan@redhat.com>
2026-05-13 16:09:46 +02:00

13 KiB

AGENTS.MD - kubevirt.core

Strict rules

  • Always make sure Apache 2.0 headers are present.
  • Always run make format, make test-unit, make test-sanity, make test-integration before pushing.

Project Overview

kubevirt.core is an Ansible collection that provides modules and plugins for managing KubeVirt virtual machines on Kubernetes clusters. It includes modules to create, delete, and query VirtualMachines and VirtualMachineInstances (kubevirt_vm, kubevirt_vm_info, kubevirt_vmi_info), as well as a dynamic inventory plugin (kubevirt) that discovers running VMs for use as Ansible targets. The collection depends on kubernetes.core and the Python kubernetes client library to interact with the Kubernetes API.

Architecture

Ansible collection project with three main plugins:

  • kubevirt: Inventory source for KubeVirt VirtualMachines
  • kubevirt_vm: Create or delete KubeVirt VirtualMachines
  • kubevirt_vm_info: Describe KubeVirt VirtualMachines
  • kubevirt_vmi_info: Describe KubeVirt VirtualMachineInstances

The key directories are:

  • plugins/ — Contains all Ansible plugin code.
    • plugins/modules/ — Ansible modules (kubevirt_vm, kubevirt_vm_info, kubevirt_vmi_info) that implement the CRUD operations against the KubeVirt API.
    • plugins/inventory/ — Dynamic inventory plugin (kubevirt.py) that discovers KubeVirt VMs and exposes them as Ansible hosts.
    • plugins/module_utils/ — Shared Python helpers (diff.py, info.py) used by the modules to handle resource diffing and info retrieval.
    • plugins/doc_fragments/ — Reusable documentation fragments (e.g., kubevirt_auth_options.py) included in module docs.
  • tests/ — All test suites for the collection.
    • tests/unit/ — Unit tests for plugin logic.
    • tests/integration/ — Integration tests that run against a live KubeVirt cluster.
    • tests/sanity/ — Ansible sanity test ignore files per Ansible version.
  • meta/ — Collection metadata (runtime.yml) defining the minimum supported Ansible version (requires_ansible).
  • docs/ — Project documentation sources (developing.md for code conventions, testing.md for test setup, releasing.md for versioning strategy).
  • examples/ — Sample playbooks and inventory files demonstrating collection usage.
  • changelogs/ — Changelog configuration and release fragments used by antsibull-changelog.
  • hack/ — Helper scripts for CI/dev environments (e.g., e2e-setup.sh for end-to-end cluster setup).
  • bin/ — Vendored tool wrappers (kind, kubectl) used by CI and local development.

Build and Development

Prerequisites

  • Python (check README.md Section Ansible and Python version compatibility for required version).
  • Ansible (check README.md Section Ansible and Python version compatibility for required version).
  • kubernetes.core Ansible collection (see requirements.yml for version constraints). Install with ansible-galaxy collection install -r requirements.yml.
  • Python libraries: jsonpatch, kubernetes, PyYAML (see requirements.txt for version constraints). Install with pip install -r requirements.txt.
  • Test dependencies: pytest, pytest-ansible, pytest-mock, pytest-xdist, ansible-compat, typing-extensions (see test-requirements.txt). Install with pip install -r test-requirements.txt.
  • Formatting: black (installed automatically by tox when running make format).
  • tox and tox-ansible for running tests and managing virtualenvs.

Key make targets

  • make build-venv — Create a development virtualenv (via tox) and symlink it to .venv.
  • make format — Run black code formatter.
  • make test-unit — Run unit tests across supported Ansible versions.
  • make test-sanity — Run Ansible sanity tests across supported Ansible versions.

Cluster development

  • make test-integration — Run integration tests (requires a running KubeVirt cluster).
  • make cluster-up — Spin up a local Kind cluster with KubeVirt installed.
  • make cluster-down — Tear down the local Kind cluster.

Building collection

In order to build the collection and install it locally, run:

ansible-galaxy collection build .
ansible-galaxy collection install kubevirt-kubevirt.core-*.tar.gz

Contributor's guidelines

Check developing.md to get code and naming style conventions.

Testing

  • Unit tests: pytest is used. Run with make test-unit.
  • Integration tests: Tests ran in a live Kubernetes cluster. These tests are collections of ansible playbooks crafted to deploy, fetch and assert certain actions.
  • Sanity tests: Built-in ansible-test sanity checks (PEP 8, import validation, documentation, etc.). Run with make test-sanity. Per-version ignore files live in tests/sanity/, in this directory, a per-version ignore file need to be added everytime there is a new version of ansible-core..
  • Module unit tests: Located in tests/unit/plugins/modules/. These tests invoke each module's main() entry point with patched AnsibleModule args and mocked API clients, verifying argument validation, expected API calls, and exit/fail outcomes without hitting a real cluster.
  • Blackbox unit tests: Located in tests/unit/plugins/inventory/blackbox/. These tests call _populate_inventory with crafted VM, VMI, and service data, then assert the resulting inventory state (host vars, groups, connections). They verify user-facing inventory behaviour end-to-end without hitting a real cluster.

Follow instructions in testing.md to set up development environments. Use the make targets for running the tests. Before running a test that makes use of ansible-test command such as make test-integration, it is required to spam a Kubernetes cluster using make cluster-up and to bind mount the repository as described in testing.md section "Running tests with ansible-test". Moreover, the Kubernetes cluster can be used to do quick tests such as running a test Ansible inventory, Ansible playbook, etc. In directory, bin the tool kubectl can be found to work with the cluster directly. Nevertheless, in this project, ansible commands are preferred.

Test patterns

Naming conventions

  • Test files are named test_<function_name>.py, one per function under test.
  • Test functions are named test_<function>_<scenario> (e.g., test_fetch_objects_early_return).

Unit test conventions

  • Unit tests must assert and test each and every code branch.
  • Unit tests use mocker.patch / mocker.patch.object (from pytest-mock) for patching, and monkeypatch when simpler attribute replacement suffices.
  • Unit test must use @pytest.mark.parametrize as much as possible.
  • When parametrize arguments become too complex or definitions could be reused across tests, define them as module-level dict constants and combine variants using the | (dict union) operator.
  • Use pytest.raises(Exception, match=pattern) for exception message validation.

Shared fixtures and utilities

  • tests/unit/plugins/inventory/conftest.py provides shared fixtures (inventory, groups, hosts, client) all scoped to function for test isolation.
  • Test files may define local fixtures when scenarios require specific setup (e.g., test_kubevirt_format_dynamic_api_exc.py).
  • tests/unit/utils/ansible_module_mock.py provides the patch_module_args() context manager and AnsibleExitJson/AnsibleFailJson exception classes used across module tests.
  • tests/unit/plugins/inventory/constants.py provides shared constants (DEFAULT_NAMESPACE, DEFAULT_BASE_DOMAIN) and a merge_dicts() helper for deep dictionary merging.
  • request.getfixturevalue() is used for dynamic fixture lookup when tests need to select fixtures at runtime.

Integration test structure

  • Integration tests are located inside each target directory depending on which plugin is being tested (tests/integration/targets/).
  • Each target contains: runme.sh (entry point), generate.yml (generates test files from Jinja2 templates), and *.yml.j2 templates.
  • Tests follow a Generate -> Run -> Verify -> Cleanup lifecycle with bash trap handlers for cleanup on failure.
  • Namespace isolation is achieved via random suffixes to prevent conflicts between test runs.

Plugin Design

Inventory plugin — plugins/inventory/kubevirt.py

Dynamic inventory plugin that extends Ansible's BaseInventoryPlugin, Constructable, and Cacheable. Config files must end in *.kubevirt.yml or *.kubevirt.yaml.

The plugin follows a fetch-then-populate pipeline:

  1. Parse the user config and build an options dataclass.
  2. Check the inventory cache or fetch VMs, VMIs, and Services from the Kubernetes API via the kubernetes.core dynamic client.
  3. Populate the inventory by creating groups (by cluster name and namespace) and adding hosts with variables derived from VM/VMI metadata and status.

Key design details:

  • Host naming is configurable via host_format (default: {namespace}-{name}).
  • Host vars are prefixed with vm_ or vmi_ depending on the source object. Status fields are converted from camelCase to snake_case.
  • Connection address resolution follows a priority order: kube_secondary_dns derived hostname, LoadBalancer/NodePort service host+port, or the VMI's primary interface IP.
  • Windows VMs are auto-detected (via guestOSInfo, preference annotations, or vm.kubevirt.io/os annotation) and set ansible_connection=winrm with WinRM service port lookup.
  • Supports Ansible constructed features (compose, groups, keyed_groups).
  • Includes backwards-compatible handling for a deprecated connections parameter (removed in 3.0.0).

Module — plugins/modules/kubevirt_vm.py

Creates, patches, or deletes KubeVirt VirtualMachines. The module:

  1. Defines its argument spec by merging module-specific args with auth and common specs from kubernetes.core.
  2. Constructs a VM resource definition from module params, translating Ansible-style snake_case params into the KubeVirt API spec (camelCase).
  3. Sets a wait condition based on running/run_strategy params to determine expected VM state.
  4. Delegates execution to kubernetes.core's runner.

Supports name or generate_name (mutually exclusive), running or run_strategy (mutually exclusive), instancetype/preference matchers, data volume templates, and hidden_fields for filtering noisy metadata from results.

Module — plugins/modules/kubevirt_vm_info.py

Read-only module to describe KubeVirt VirtualMachines. Builds its arg spec from a shared info spec (defined in module_utils/info.py) plus auth args, adds a running parameter to control the wait condition, and delegates to a shared info execution function.

Module — plugins/modules/kubevirt_vmi_info.py

Read-only module to describe KubeVirt VirtualMachineInstances. Structurally identical to kubevirt_vm_info but queries VirtualMachineInstance resources and has no running parameter (always waits for Ready=True).

Shared utilities — plugins/module_utils/

  • info.py — Shared argument spec and execution logic for the info modules. Instantiates a K8sService, performs the resource lookup, and exits with results.
  • diff.py — Monkey-patches kubernetes.core's diff logic to ignore metadata-only changes (generation, resourceVersion), fixing false-positive "changed" results.

Conventions

Code

  • All source files must carry Apache 2.0 license headers.
  • Code style and naming conventions are documented in developing.md.
  • Always use strong typing in the function headers. This applies to parameters and return values.

Commits

  • Commit messages follow conventional commits with scope, e.g. feat(vm_info): ..., fix(tests): ..., chore(deps): ....
  • Commits must be signed off (git commit -s).
  • If an AI agent assisted the developer, the commit must add assisted-by and the AI agent signature.

Pull requests and issues

  • PRs must follow .github/PULL_REQUEST_TEMPLATE.md. Key sections: what the PR does, which issue(s) it fixes, reviewer notes, and a release note block.
  • Issues must follow the templates in .github/ISSUE_TEMPLATE/ (bug_report.md, feature_request.md).
  • Always read the relevant template before creating a PR or issue and fill in all sections.
  • PRs must pass CI (linter, sanity, unit, and integration tests) before merge.

Versioning and releases

  • The project follows Semantic Versioning 2.0.0 as documented in releasing.md.
  • Releases are triggered by annotated git tags. The CI workflow (.github/workflows/release.yml) builds the collection, publishes to Ansible Galaxy, and creates a GitHub release.
  • Changelog entries are managed by antsibull-changelog using fragments in changelogs/fragments/.

CI

  • Main CI workflow (.github/workflows/ci.yml) runs: tree-clean check, ansible-lint, sanity tests, and unit tests across a matrix of Ansible and Python versions.
  • Integration tests run in a separate workflow (.github/workflows/integration.yml) against a Kind cluster with KubeVirt.
  • Docs linting validates Ansible documentation format via antsibull-docs (.github/workflows/extra-docs-linting.yml).
  • Dependency updates are automated via Renovate (renovate.json), which manages e2e-setup tool versions, GitHub Actions, and collection dependencies.