Skip to content

Arbitrary host expressions for Ansible backend #807

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

amarao
Copy link
Contributor

@amarao amarao commented May 5, 2025

Ansible has extensive so-called host expressions: ability to join/exclude hosts from a host list based on logical expressions:

Examples:

  • database,&primary - hosts in database and primary groups
  • database,!standby - hosts in database group but not in standby group
  • database[0] - first host in the group

Full list is here: https://docs.ansible.com/ansible/latest/inventory_guide/intro_patterns.html

testnfra lacked this ability for long time (see #609, rejected, where I was asked to bring patterns).

I've decided to try to implement them. Implementing from scratch is very hard (see link above to see all features and complexity). I've tried to reuse ansible code (specifically, InventoryManager, which allows evaluation of the host expressions). Proper support for InventoryManager also required to add ConfigManager (I wanted to keep full support for ANSIBLE_INVENTORY environment var which I use a lot for many testcases).

I understand, that bringing from ansible import .. could break a lot of things, so instead of 'switching to Ansible for everything', I've added a simple heuristic:

  • older features (like normal groups and globs for host names) are going to work old way (keeping all existing tests running as before).
  • Only if host expression is containing signs of complicated expression, switch to ansible. This will limit breakage due to possible ansible drift, only to tests, which are dependent on complex expressions.

Examples

testinfra_hosts = ["ansible://etcd(0)"]

def test_etcd_quorum(host):
    ...
tesinfra_hosts = ["ansible://node_exporter,!prometheus"]

def test_node_exporter_without_prometheus(host):
    ...

Host expression problem

I also found, that ansible://groupname[0] is not valid uri ([] is reserved for IPv6 addreses in the host part of the URI). I thought about possible workarounds, and the least invasive was to replace ansible://groupname[0] with ansible://groupname(0). Slightly odd, but perfectly readable and limited only to the specific case.

Limitations for possible characters in 'host' part of URI is also the reason why regexp (~) can not be supported this way, unfortunately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants