Use json for test inventory - ci_complete (#86118)

* Use json for test inventory - ci_complete

Uses the JSON/YAML format for the inventory files generated by
`ansible-test`. This solves minor issues with using complex values when
building the test inventory files like backslashes or more complex data
structures.

* Apply suggestions from code review

Co-authored-by: Matt Clay <matt@mystile.com>

* Add changelog and use more limited ext config var - ci_complete

---------

Co-authored-by: Matt Clay <matt@mystile.com>
This commit is contained in:
Jordan Borean
2025-11-04 13:25:03 +10:00
committed by GitHub
parent 3c5bb535a9
commit 829373bfb9
4 changed files with 18 additions and 22 deletions

View File

@@ -0,0 +1,4 @@
minor_changes:
- >-
ansible-test - add ``.winrm`` and ``.networking`` as valid JSON/YAML inventory file extensions. This should not
affect any public facing code as it is used internally for inventories generated by ``ansible-test``.

View File

@@ -93,6 +93,7 @@ def ansible_environment(args: CommonConfig, color: bool = True, ansible_config:
ansible = dict(
ANSIBLE_PYTHON_MODULE_RLIMIT_NOFILE=str(SOFT_RLIMIT_NOFILE),
ANSIBLE_INVENTORY_PLUGIN_EXTS='.yaml, .yml, .json, .winrm, .networking', # allows the yaml/json inventory format for windows and networking
ANSIBLE_FORCE_COLOR='%s' % 'true' if args.color and color else 'false',
ANSIBLE_FORCE_HANDLERS='true', # allow cleanup handlers to run when tests fail
ANSIBLE_HOST_PATTERN_MISMATCH='error', # prevent tests from unintentionally passing when hosts are not found

View File

@@ -202,31 +202,24 @@ class Inventory:
def write(self, args: CommonConfig, path: str) -> None:
"""Write the given inventory to the specified path on disk."""
# NOTE: Switching the inventory generation to write JSON would be nice, but is currently not possible due to the use of hard-coded inventory filenames.
# The name `inventory` works for the POSIX integration tests, but `inventory.winrm` and `inventory.networking` will only parse in INI format.
# If tests are updated to use the `INVENTORY_PATH` environment variable, then this could be changed.
# Also, some tests detect the test type by inspecting the suffix on the inventory filename, which would break if it were changed.
inventory_text = ''
inventory_data: dict[str, dict[str, dict[str, dict[str, object]]]] = dict()
for group, hosts in self.host_groups.items():
inventory_text += f'[{group}]\n'
group_data = inventory_data.setdefault(group, dict())
hosts_data = group_data.setdefault('hosts', dict())
for host, variables in hosts.items():
kvp = ' '.join(f"{key}={value!r}" for key, value in variables.items())
inventory_text += f'{host} {kvp}\n'
inventory_text += '\n'
host_entry = hosts_data.setdefault(host, dict())
host_entry.update(variables)
for group, children in (self.extra_groups or {}).items():
inventory_text += f'[{group}]\n'
group_data = inventory_data.setdefault(group, dict())
group_children = group_data.setdefault('children', dict())
for child in children:
inventory_text += f'{child}\n'
group_children[child] = dict()
inventory_text += '\n'
inventory_text = inventory_text.strip()
inventory_text = json.dumps(inventory_data, indent=4)
if not args.explain:
write_text_file(path, inventory_text + '\n')
@@ -1380,7 +1373,7 @@ class NetworkRemoteProfile(RemoteProfile[NetworkRemoteConfig]):
env = ansible_environment(self.args)
module_name = f'{self.config.collection + "." if self.config.collection else ""}{self.config.platform}_command'
with tempfile.NamedTemporaryFile() as inventory_file:
with tempfile.NamedTemporaryFile(suffix='.json') as inventory_file:
inventory.write(self.args, inventory_file.name)
cmd = ['ansible', '-m', module_name, '-a', 'commands=?', '-i', inventory_file.name, 'all']
@@ -1636,7 +1629,7 @@ class WindowsRemoteProfile(RemoteProfile[WindowsRemoteConfig]):
env = ansible_environment(self.args)
module_name = 'ansible.windows.win_ping'
with tempfile.NamedTemporaryFile() as inventory_file:
with tempfile.NamedTemporaryFile(suffix='.json') as inventory_file:
inventory.write(self.args, inventory_file.name)
cmd = ['ansible', '-m', module_name, '-i', inventory_file.name, 'all']

View File

@@ -109,9 +109,7 @@ def create_windows_inventory(args: EnvironmentConfig, path: str, target_hosts: l
# The `testhost` group is needed to support the `binary_modules_winrm` integration test.
# The test should be updated to remove the need for this.
extra_groups={
'testhost:children': [
'windows',
],
'testhost': ['windows'],
},
)
@@ -145,7 +143,7 @@ def create_network_inventory(args: EnvironmentConfig, path: str, target_hosts: l
# see: https://github.com/ansible/ansible/pull/34661
# see: https://github.com/ansible/ansible/pull/34707
extra_groups={
'net:children': sorted(host_groups),
'net': list(sorted(host_groups)),
},
)