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>
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-integrationbefore 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 VirtualMachineskubevirt_vm: Create or delete KubeVirt VirtualMachineskubevirt_vm_info: Describe KubeVirt VirtualMachineskubevirt_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.mdfor code conventions,testing.mdfor test setup,releasing.mdfor versioning strategy).examples/— Sample playbooks and inventory files demonstrating collection usage.changelogs/— Changelog configuration and release fragments used byantsibull-changelog.hack/— Helper scripts for CI/dev environments (e.g.,e2e-setup.shfor 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.coreAnsible collection (seerequirements.ymlfor version constraints). Install withansible-galaxy collection install -r requirements.yml.- Python libraries:
jsonpatch,kubernetes,PyYAML(seerequirements.txtfor version constraints). Install withpip install -r requirements.txt. - Test dependencies:
pytest,pytest-ansible,pytest-mock,pytest-xdist,ansible-compat,typing-extensions(seetest-requirements.txt). Install withpip install -r test-requirements.txt. - Formatting:
black(installed automatically bytoxwhen runningmake format). toxandtox-ansiblefor running tests and managing virtualenvs.
Key make targets
make build-venv— Create a development virtualenv (via tox) and symlink it to.venv.make format— Runblackcode 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 sanitychecks (PEP 8, import validation, documentation, etc.). Run withmake test-sanity. Per-version ignore files live intests/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'smain()entry point with patchedAnsibleModuleargs 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_inventorywith 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(frompytest-mock) for patching, andmonkeypatchwhen simpler attribute replacement suffices. - Unit test must use
@pytest.mark.parametrizeas 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.pyprovides shared fixtures (inventory,groups,hosts,client) all scoped tofunctionfor 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.pyprovides thepatch_module_args()context manager andAnsibleExitJson/AnsibleFailJsonexception classes used across module tests.tests/unit/plugins/inventory/constants.pyprovides shared constants (DEFAULT_NAMESPACE,DEFAULT_BASE_DOMAIN) and amerge_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
targetdirectory 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.j2templates. - 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:
- Parse the user config and build an options dataclass.
- Check the inventory cache or fetch VMs, VMIs, and Services from the Kubernetes API via the
kubernetes.coredynamic client. - 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_orvmi_depending on the source object. Status fields are converted from camelCase to snake_case. - Connection address resolution follows a priority order:
kube_secondary_dnsderived hostname, LoadBalancer/NodePort service host+port, or the VMI's primary interface IP. - Windows VMs are auto-detected (via
guestOSInfo, preference annotations, orvm.kubevirt.io/osannotation) and setansible_connection=winrmwith WinRM service port lookup. - Supports Ansible
constructedfeatures (compose,groups,keyed_groups). - Includes backwards-compatible handling for a deprecated
connectionsparameter (removed in 3.0.0).
Module — plugins/modules/kubevirt_vm.py
Creates, patches, or deletes KubeVirt VirtualMachines. The module:
- Defines its argument spec by merging module-specific args with auth and common specs from
kubernetes.core. - Constructs a VM resource definition from module params, translating Ansible-style snake_case params into the KubeVirt API spec (camelCase).
- Sets a wait condition based on
running/run_strategyparams to determine expected VM state. - 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 aK8sService, performs the resource lookup, and exits with results.diff.py— Monkey-patcheskubernetes.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-byand 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-changelogusing fragments inchangelogs/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.