diff --git a/changelogs/fragments/fix-import_role-_from-options.yml b/changelogs/fragments/fix-import_role-_from-options.yml new file mode 100644 index 00000000000..b6b0e2395cc --- /dev/null +++ b/changelogs/fragments/fix-import_role-_from-options.yml @@ -0,0 +1,2 @@ +minor_changes: + - import_role - allow subdirectories with ``_from`` options for parity with ``include_role`` (https://github.com/ansible/ansible/issues/82584). diff --git a/lib/ansible/playbook/role_include.py b/lib/ansible/playbook/role_include.py index 1e5c48bb0e1..628f26ec0a8 100644 --- a/lib/ansible/playbook/role_include.py +++ b/lib/ansible/playbook/role_include.py @@ -16,8 +16,6 @@ from __future__ import annotations -from os.path import basename - import ansible.constants as C from ansible.errors import AnsibleParserError from ansible.playbook.attribute import NonInheritableFieldAttribute @@ -141,7 +139,7 @@ class IncludeRole(TaskInclude): args_value = ir.args.get(key) if not isinstance(args_value, string_types): raise AnsibleParserError('Expected a string for %s but got %s instead' % (key, type(args_value))) - ir._from_files[from_key] = basename(args_value) + ir._from_files[from_key] = args_value # apply is only valid for includes, not imports as they inherit directly apply_attrs = ir.args.get('apply', {}) diff --git a/test/integration/targets/roles/no_outside_import.yml b/test/integration/targets/roles/no_outside_import.yml new file mode 100644 index 00000000000..c9e0d130e50 --- /dev/null +++ b/test/integration/targets/roles/no_outside_import.yml @@ -0,0 +1,6 @@ +- hosts: testhost + gather_facts: false + tasks: + - import_role: + name: a + tasks_from: subdir/../../../../no_outside.yml diff --git a/test/integration/targets/roles/roles/a/tasks/subdir/entrypoint.yml b/test/integration/targets/roles/roles/a/tasks/subdir/entrypoint.yml new file mode 100644 index 00000000000..331ec9405f8 --- /dev/null +++ b/test/integration/targets/roles/roles/a/tasks/subdir/entrypoint.yml @@ -0,0 +1 @@ +- debug: msg=subdir diff --git a/test/integration/targets/roles/runme.sh b/test/integration/targets/roles/runme.sh index bf3aaf58239..5227e42ed86 100755 --- a/test/integration/targets/roles/runme.sh +++ b/test/integration/targets/roles/runme.sh @@ -26,13 +26,19 @@ ansible-playbook role_complete.yml -i ../../inventory -i fake, --tags unreachabl ansible-playbook data_integrity.yml -i ../../inventory "$@" # ensure role fails when trying to load 'non role' in _from -ansible-playbook no_outside.yml -i ../../inventory > role_outside_output.log 2>&1 || true -if grep "as it is not inside the expected role path" role_outside_output.log >/dev/null; then - echo "Test passed (playbook failed with expected output, output not shown)." -else - echo "Test failed, expected output from playbook failure is missing, output not shown)." - exit 1 -fi +test_no_outside=("no_outside.yml" "no_outside_import.yml") +for file in "${test_no_outside[@]}"; do + ansible-playbook "$file" -i ../../inventory > "${file}_output.log" 2>&1 || true + if grep "as it is not inside the expected role path" "${file}_output.log" >/dev/null; then + echo "Test passed for $file (playbook failed with expected output, output not shown)." + else + echo "Test failed for $file, expected output from playbook failure is missing, output not shown)." + exit 1 + fi +done + +# ensure subdir contained to role in tasks_from is valid +ansible-playbook test_subdirs.yml -i ../../inventory "$@" # ensure vars scope is correct ansible-playbook vars_scope.yml -i ../../inventory "$@" diff --git a/test/integration/targets/roles/test_subdirs.yml b/test/integration/targets/roles/test_subdirs.yml new file mode 100644 index 00000000000..503239d0999 --- /dev/null +++ b/test/integration/targets/roles/test_subdirs.yml @@ -0,0 +1,10 @@ +--- +- hosts: testhost + gather_facts: false + tasks: + - import_role: + name: a + tasks_from: subdir/entrypoint.yml + - include_role: + name: a + tasks_from: subdir/entrypoint.yml