summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Clay <mclay@redhat.com>2022-01-31 11:19:23 -0800
committerMatt Clay <matt@mystile.com>2022-01-31 16:12:44 -0800
commit1ef0bc3fd6be147427244c268452f10d3647685c (patch)
tree6a26e5279261e75b2a9b66fca1419226f7cb35ae
parentf496edc6e95cc46abe29715bebb3737626adbaca (diff)
downloadansible-1ef0bc3fd6be147427244c268452f10d3647685c.tar.gz
[stable-2.12] ansible-test - Use relative paths in junit output. (#76871)
* ansible-test - Use relative paths in junit output. Also fix a traceback in the junit callback during automatic fact gathering. * ansible-test - Handle out-of-tree JUnit paths. (cherry picked from commit fbb5d56bd274c44b193cb95f0230b9352f62aab2) Co-authored-by: Matt Clay <mclay@redhat.com>
-rw-r--r--changelogs/fragments/ansible-test-junit-relative-paths.yml6
-rw-r--r--lib/ansible/plugins/callback/junit.py13
-rw-r--r--test/lib/ansible_test/_internal/commands/integration/__init__.py14
3 files changed, 27 insertions, 6 deletions
diff --git a/changelogs/fragments/ansible-test-junit-relative-paths.yml b/changelogs/fragments/ansible-test-junit-relative-paths.yml
new file mode 100644
index 0000000000..b1ace19687
--- /dev/null
+++ b/changelogs/fragments/ansible-test-junit-relative-paths.yml
@@ -0,0 +1,6 @@
+bugfixes:
+ - ansible-test - Use relative paths in JUnit files generated during integration test runs.
+ - ansible-test - Replace the directory portion of out-of-tree paths in JUnit files from integration tests with the ``out-of-tree:`` prefix.
+ - junit callback - Fix traceback during automatic fact gathering when using relative paths.
+minor_changes:
+ - junit callback - Add support for replacing the directory portion of out-of-tree relative task paths with a placeholder.
diff --git a/lib/ansible/plugins/callback/junit.py b/lib/ansible/plugins/callback/junit.py
index 73284a33ae..c69770e17b 100644
--- a/lib/ansible/plugins/callback/junit.py
+++ b/lib/ansible/plugins/callback/junit.py
@@ -40,6 +40,13 @@ DOCUMENTATION = '''
version_added: "2.8"
env:
- name: JUNIT_TASK_RELATIVE_PATH
+ replace_out_of_tree_path:
+ name: Replace out of tree path
+ default: none
+ description: Replace the directory portion of an out-of-tree relative task path with the given placeholder
+ version_added: "2.12.3"
+ env:
+ - name: JUNIT_REPLACE_OUT_OF_TREE_PATH
fail_on_change:
name: JUnit fail on change
default: False
@@ -141,6 +148,7 @@ class CallbackModule(CallbackBase):
self._include_setup_tasks_in_report = os.getenv('JUNIT_INCLUDE_SETUP_TASKS_IN_REPORT', 'True').lower()
self._hide_task_arguments = os.getenv('JUNIT_HIDE_TASK_ARGUMENTS', 'False').lower()
self._test_case_prefix = os.getenv('JUNIT_TEST_CASE_PREFIX', '')
+ self._replace_out_of_tree_path = os.getenv('JUNIT_REPLACE_OUT_OF_TREE_PATH', None)
self._playbook_path = None
self._playbook_name = None
self._play_name = None
@@ -208,11 +216,14 @@ class CallbackModule(CallbackBase):
name = '[%s] %s: %s' % (host_data.name, task_data.play, task_data.name)
duration = host_data.finish - task_data.start
- if self._task_relative_path:
+ if self._task_relative_path and task_data.path:
junit_classname = os.path.relpath(task_data.path, self._task_relative_path)
else:
junit_classname = task_data.path
+ if self._replace_out_of_tree_path is not None and junit_classname.startswith('../'):
+ junit_classname = self._replace_out_of_tree_path + os.path.basename(junit_classname)
+
if self._task_class == 'true':
junit_classname = re.sub(r'\.yml:[0-9]+$', '', junit_classname)
diff --git a/test/lib/ansible_test/_internal/commands/integration/__init__.py b/test/lib/ansible_test/_internal/commands/integration/__init__.py
index 743ea9d423..839b24aecf 100644
--- a/test/lib/ansible_test/_internal/commands/integration/__init__.py
+++ b/test/lib/ansible_test/_internal/commands/integration/__init__.py
@@ -242,7 +242,7 @@ def integration_test_environment(
ansible_config = ansible_config_src
vars_file = os.path.join(data_context().content.root, data_context().content.integration_vars_path)
- yield IntegrationEnvironment(integration_dir, targets_dir, inventory_path, ansible_config, vars_file)
+ yield IntegrationEnvironment(data_context().content.root, integration_dir, targets_dir, inventory_path, ansible_config, vars_file)
return
# When testing a collection, the temporary directory must reside within the collection.
@@ -320,7 +320,7 @@ def integration_test_environment(
make_dirs(os.path.dirname(file_dst))
shutil.copy2(file_src, file_dst)
- yield IntegrationEnvironment(integration_dir, targets_dir, inventory_path, ansible_config, vars_file)
+ yield IntegrationEnvironment(temp_dir, integration_dir, targets_dir, inventory_path, ansible_config, vars_file)
finally:
if not args.explain:
remove_tree(temp_dir)
@@ -590,7 +590,7 @@ def command_integration_script(
if args.verbosity:
cmd.append('-' + ('v' * args.verbosity))
- env = integration_environment(args, target, test_dir, test_env.inventory_path, test_env.ansible_config, env_config)
+ env = integration_environment(args, target, test_dir, test_env.inventory_path, test_env.ansible_config, env_config, test_env)
cwd = os.path.join(test_env.targets_dir, target.relative_path)
env.update(dict(
@@ -711,7 +711,7 @@ def command_integration_role(
if args.verbosity:
cmd.append('-' + ('v' * args.verbosity))
- env = integration_environment(args, target, test_dir, test_env.inventory_path, test_env.ansible_config, env_config)
+ env = integration_environment(args, target, test_dir, test_env.inventory_path, test_env.ansible_config, env_config, test_env)
cwd = test_env.integration_dir
env.update(dict(
@@ -766,6 +766,7 @@ def integration_environment(
inventory_path, # type: str
ansible_config, # type: t.Optional[str]
env_config, # type: t.Optional[CloudEnvironmentConfig]
+ test_env, # type: IntegrationEnvironment
): # type: (...) -> t.Dict[str, str]
"""Return a dictionary of environment variables to use when running the given integration test target."""
env = ansible_environment(args, ansible_config=ansible_config)
@@ -774,6 +775,8 @@ def integration_environment(
integration = dict(
JUNIT_OUTPUT_DIR=ResultType.JUNIT.path,
+ JUNIT_TASK_RELATIVE_PATH=test_env.test_dir,
+ JUNIT_REPLACE_OUT_OF_TREE_PATH='out-of-tree:',
ANSIBLE_CALLBACKS_ENABLED=','.join(sorted(set(callback_plugins))),
ANSIBLE_TEST_CI=args.metadata.ci_provider or get_ci_provider().code,
ANSIBLE_TEST_COVERAGE='check' if args.coverage_check else ('yes' if args.coverage else ''),
@@ -797,7 +800,8 @@ def integration_environment(
class IntegrationEnvironment:
"""Details about the integration environment."""
- def __init__(self, integration_dir, targets_dir, inventory_path, ansible_config, vars_file):
+ def __init__(self, test_dir, integration_dir, targets_dir, inventory_path, ansible_config, vars_file):
+ self.test_dir = test_dir
self.integration_dir = integration_dir
self.targets_dir = targets_dir
self.inventory_path = inventory_path