%ansible_test_unit: handle test dependencies on other collections

epel9
Maxwell G 1 year ago
parent f820268993
commit 65040b8666
No known key found for this signature in database
GPG Key ID: F79E4E25E8C661F8

@ -2,7 +2,7 @@
Name: ansible-packaging Name: ansible-packaging
Version: 1 Version: 1
Release: 14%{?dist} Release: 15%{?dist}
Summary: RPM packaging macros and generators for Ansible collections Summary: RPM packaging macros and generators for Ansible collections
License: GPL-3.0-or-later License: GPL-3.0-or-later
@ -153,6 +153,9 @@ echo "Ensure macro prefers the collection namespace and name passed as an argume
%changelog %changelog
* Sat Feb 10 2024 Maxwell G <maxwell@gtmx.me> - 1-15
- %%ansible_test_unit: handle test dependencies on other collections
* Mon Jan 22 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1-14 * Mon Jan 22 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1-14
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild

@ -19,13 +19,15 @@ the provided arguments.
""" """
import argparse import argparse
import json
import os import os
import shutil import shutil
import subprocess import subprocess
import sys import sys
from itertools import chain
from pathlib import Path from pathlib import Path
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
from typing import Any, Dict, Optional, Sequence, Union from typing import Any, Dict, Optional, Sequence, Tuple, Union
from yaml import CSafeLoader, load from yaml import CSafeLoader, load
@ -64,6 +66,7 @@ class AnsibleCollection:
"ansible-galaxy", "ansible-galaxy",
"collection", "collection",
"install", "install",
"--force",
"-n", "-n",
"-p", "-p",
str(destdir), str(destdir),
@ -84,13 +87,24 @@ class AnsibleCollection:
with open(filelist, "w", encoding="utf-8") as file: with open(filelist, "w", encoding="utf-8") as file:
file.write(contents) file.write(contents)
def unit_test(self, extra_args: Sequence) -> None: def unit_test(
with TemporaryDirectory() as temp: self,
temppath = Path(temp) / "ansible_collections" / self.namespace / self.name extra_args: Sequence[str],
extra_paths: Sequence[Path],
collections: Sequence[str],
) -> None:
with TemporaryDirectory() as _temp:
temp = Path(_temp)
temppath = temp / "ansible_collections" / self.namespace / self.name
shutil.copytree( shutil.copytree(
self.collection_srcdir, self.collection_srcdir,
temppath, temppath,
) )
collection_paths = (
self._get_collection_path(collection) for collection in collections
)
for extra in chain(collection_paths, extra_paths):
self._handle_extra_path(temp, extra)
args = ("ansible-test", "units", *extra_args) args = ("ansible-test", "units", *extra_args)
print(f"Running: {args}") print(f"Running: {args}")
print() print()
@ -104,6 +118,63 @@ class AnsibleCollection:
env={**os.environ, "ANSIBLE_GALAXY_COLLECTIONS_PATH_WARNING": "0"}, env={**os.environ, "ANSIBLE_GALAXY_COLLECTIONS_PATH_WARNING": "0"},
) )
def _get_collection_path(self, collection: str) -> Path:
proc = subprocess.run(
["ansible-galaxy", "collection", "list", "--format=json", collection],
check=True,
universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
# {
# "/usr/share/ansible/collections/ansible_collections": {
# "community.general": {
# "version": "8.2.0"
# }
# }
# }
data: Dict[str, Dict[str, Any]] = json.loads(proc.stdout)
for path, collection_part in data.items():
version = collection_part[collection]["version"]
print(f"Using locally-installed version {version} of {collection}")
return Path(path, *collection.split(".", 1))
raise CollectionError(f"Failed to add {collection} to the test tree")
def _handle_extra_path(self, collection_tree: Path, extra_path: Path) -> None:
namespace_name = _get_namespace_name(extra_path)
if namespace_name == (self.namespace, self.name):
raise CollectionError(
f"{extra_path} is the same collection as {self.collection_srcdir}"
)
new_path = Path(collection_tree, "ansible_collections", *namespace_name)
if new_path.is_dir():
raise CollectionError(
f"Cannot copy {extra_path}."
f" Collection {namespace_name} was already added."
)
print(
f"Copying {extra_path} ({'.'.join(namespace_name)}) to the collection tree"
)
shutil.copytree(extra_path, new_path)
def _get_namespace_name(extra_path: Path) -> Tuple[str, str]:
data_file = extra_path / "MANIFEST.json"
data_file2 = extra_path / "galaxy.yml"
if data_file.is_file():
with data_file.open("r", encoding="utf-8") as fp:
data = json.load(fp)["collection_info"]
elif data_file2.is_file():
data_file = data_file2
with data_file2.open("r", encoding="utf-8") as fp:
data = load(fp, Loader=CSafeLoader)
else:
raise CollectionError(f"No metadata file found for collection in {extra_path}")
expected_keys = {"namespace", "name"}
if set(data) & expected_keys != expected_keys:
raise CollectionError(f"Invalid metadata file: {data_file}")
return data["namespace"], data["name"]
def parseargs() -> argparse.Namespace: def parseargs() -> argparse.Namespace:
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
@ -132,13 +203,33 @@ def parseargs() -> argparse.Namespace:
help="Run ansible-test unit after creating the necessary directory structure", help="Run ansible-test unit after creating the necessary directory structure",
) )
test_parser.add_argument( test_parser.add_argument(
"extra_args", nargs="*", help="Extra arguments to pass to ansible-test" "-p",
"--extra-path",
dest="extra_paths",
action="append",
help="Path to an extra collection include in the test ansible_collection tree",
type=Path,
)
test_parser.add_argument(
"-c",
"--collection",
action="append",
dest="collections",
help="Add a collection from the collection path to the test tree",
) )
args = parser.parse_args() test_parser.set_defaults(allow_extra_args=True)
args, extra_args = parser.parse_known_args()
# add_subparsers does not support required on Python 3.6 # add_subparsers does not support required on Python 3.6
if not args.action: if not args.action:
parser.print_usage() parser.print_usage()
sys.exit(2) sys.exit(2)
if extra_args:
if not getattr(args, "allow_extra_args", False):
parser.error(f"unrecognized arguments: {' '.join(extra_args)}")
if extra_args and extra_args[0] == "--":
extra_args = extra_args[1:]
args.extra_args = extra_args
vars(args).pop("allow_extra_args", None)
return args return args
@ -149,11 +240,15 @@ def main():
collection.install(args.collections_dir) collection.install(args.collections_dir)
collection.write_filelist(args.filelist) collection.write_filelist(args.filelist)
elif args.action == "test": elif args.action == "test":
collection.unit_test(args.extra_args) collection.unit_test(
args.extra_args,
(args.extra_paths or ()),
(args.collections or ()),
)
if __name__ == "__main__": if __name__ == "__main__":
try: try:
main() main()
except (CollectionError, subprocess.CalledProcessError) as err: except (CollectionError, subprocess.CalledProcessError) as err:
sys.exit(err) sys.exit(str(err))

@ -16,9 +16,9 @@
--filelist %{ansible_collection_filelist} --filelist %{ansible_collection_filelist}
} }
%ansible_test_unit() %{shrink: %ansible_test_unit(p:c:) %{shrink:
%{_rpmconfigdir}/ansible_collection.py test -- %{_rpmconfigdir}/ansible_collection.py test
--python-interpreter %{__python3} --local %{?*} %{**} --python-interpreter %{__python3} --local
} }
# TODO: Officially deprecate this macro and add the following line to the macro # TODO: Officially deprecate this macro and add the following line to the macro

Loading…
Cancel
Save