summaryrefslogtreecommitdiff
path: root/test/integration/targets
diff options
context:
space:
mode:
authorcos <cos>2024-04-20 09:15:12 +0200
committercos <cos>2024-04-20 09:44:47 +0200
commitbbed591285e1882d05198e518f75873af58939f5 (patch)
treec25b33652187f7070d0c2467663c11d6cd4e2326 /test/integration/targets
parentc4f015da4ac75017b97c24ef6601bdd98872e60f (diff)
downloaddebian-ansible-core-upstream/failed-recreation-attempt.zip
Attempt to recreate upstream branch state from tar filesupstream/failed-recreation-attempt
Unfortunately this was a too naive approach, and the result fails to build. Work around that version control is behind the actual package version in trixie. As is obvious from the lacking commits in the salsa repository and also visible on https://tracker.debian.org/pkg/ansible-core with the report from vcswatch stating: VCS repository is not up to date. This commit contains all changes from ansible-core_2.14.13.orig.tar.gz to ansible-core_2.16.5.orig.tar.gz, which should hopefully be a squashed representation on the same set of changes on the uploader's unpushed git tree.
Diffstat (limited to 'test/integration/targets')
-rw-r--r--test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/MANIFEST.json2
-rw-r--r--test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py1
-rw-r--r--test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/lookup/noop.py3
-rw-r--r--test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/MANIFEST.json2
-rw-r--r--test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py1
-rw-r--r--test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py22
-rw-r--r--test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/test/yolo.yml19
-rw-r--r--test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/MANIFEST.json2
-rw-r--r--test/integration/targets/ansible-doc/randommodule-text.output26
-rw-r--r--test/integration/targets/ansible-doc/randommodule.output19
-rwxr-xr-xtest/integration/targets/ansible-doc/runme.sh134
-rw-r--r--test/integration/targets/ansible-galaxy-collection-cli/files/expected.txt6
-rw-r--r--test/integration/targets/ansible-galaxy-collection-cli/files/galaxy.yml1
-rw-r--r--test/integration/targets/ansible-galaxy-collection-cli/files/make_collection_dir.py4
-rw-r--r--test/integration/targets/ansible-galaxy-collection-scm/tasks/main.yml2
-rw-r--r--test/integration/targets/ansible-galaxy-collection-scm/tasks/multi_collection_repo_all.yml2
-rw-r--r--test/integration/targets/ansible-galaxy-collection-scm/tasks/setup_recursive_scm_dependency.yml7
-rw-r--r--test/integration/targets/ansible-galaxy-collection/library/reset_pulp.py57
-rw-r--r--test/integration/targets/ansible-galaxy-collection/library/setup_collections.py15
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/build.yml25
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/download.yml4
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/fail_fast_resolvelib.yml2
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/init.yml65
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/install.yml203
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/install_offline.yml8
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/list.yml41
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/main.yml43
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/publish.yml5
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/supported_resolvelib.yml8
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/upgrade.yml2
-rw-r--r--test/integration/targets/ansible-galaxy-collection/tasks/verify.yml8
-rw-r--r--test/integration/targets/ansible-galaxy-collection/templates/ansible.cfg.j216
-rw-r--r--test/integration/targets/ansible-galaxy-collection/vars/main.yml43
-rwxr-xr-xtest/integration/targets/ansible-galaxy-role/files/create-role-archive.py21
-rw-r--r--test/integration/targets/ansible-galaxy-role/tasks/dir-traversal.yml86
-rw-r--r--test/integration/targets/ansible-galaxy-role/tasks/main.yml15
-rw-r--r--test/integration/targets/ansible-galaxy/files/testserver.py19
-rwxr-xr-xtest/integration/targets/ansible-galaxy/runme.sh7
-rw-r--r--test/integration/targets/ansible-inventory/files/valid_sample.yml2
-rw-r--r--test/integration/targets/ansible-inventory/tasks/main.yml7
-rwxr-xr-xtest/integration/targets/ansible-pull/runme.sh5
-rw-r--r--test/integration/targets/ansible-runner/aliases1
-rw-r--r--test/integration/targets/ansible-runner/files/adhoc_example1.py1
-rw-r--r--test/integration/targets/ansible-test-cloud-openshift/aliases2
-rw-r--r--test/integration/targets/ansible-test-cloud-openshift/tasks/main.yml11
-rwxr-xr-xtest/integration/targets/ansible-test-container/runme.py11
-rw-r--r--test/integration/targets/ansible-test-sanity-import/ansible_collections/ns/col/plugins/lookup/vendor1.py4
-rw-r--r--test/integration/targets/ansible-test-sanity-import/ansible_collections/ns/col/plugins/lookup/vendor2.py4
-rwxr-xr-xtest/integration/targets/ansible-test-sanity-import/runme.sh22
-rw-r--r--test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/col/plugins/modules/sidecar.yaml3
-rw-r--r--test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/failure/README.md1
-rw-r--r--test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/ps_only/README.md1
-rw-r--r--test/integration/targets/ansible-test-sanity-validate-modules/expected.txt21
-rwxr-xr-xtest/integration/targets/ansible-test-sanity-validate-modules/runme.sh12
-rw-r--r--test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/README.md1
-rw-r--r--test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/meta/runtime.yml9
-rw-r--r--test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/lookup/bad.py4
-rw-r--r--test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/lookup/world.py2
-rw-r--r--test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/modules/bad.py2
-rw-r--r--test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/random_directory/bad.py2
-rw-r--r--test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/integration/targets/hello/files/bad.py4
-rw-r--r--test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/sanity/ignore.txt1
-rwxr-xr-xtest/integration/targets/ansible-test-sanity/runme.sh6
-rwxr-xr-xtest/integration/targets/ansible-test/venv-pythons.py10
-rw-r--r--test/integration/targets/ansible-vault/invalid_format/broken-group-vars-tasks.yml2
-rwxr-xr-xtest/integration/targets/ansible-vault/runme.sh32
-rw-r--r--test/integration/targets/ansible-vault/test_vault.yml2
-rw-r--r--test/integration/targets/ansible-vault/test_vaulted_template.yml2
-rw-r--r--test/integration/targets/ansible/aliases1
-rw-r--r--test/integration/targets/ansible/ansible-testé.cfg2
-rwxr-xr-xtest/integration/targets/ansible/runme.sh6
-rw-r--r--test/integration/targets/apt/aliases1
-rw-r--r--test/integration/targets/apt/tasks/apt.yml51
-rw-r--r--test/integration/targets/apt/tasks/repo.yml2
-rw-r--r--test/integration/targets/apt_key/aliases1
-rw-r--r--test/integration/targets/apt_key/tasks/main.yml2
-rw-r--r--test/integration/targets/apt_repository/aliases1
-rw-r--r--test/integration/targets/apt_repository/tasks/apt.yml18
-rw-r--r--test/integration/targets/apt_repository/tasks/mode_cleanup.yaml2
-rw-r--r--test/integration/targets/argspec/library/argspec.py6
-rw-r--r--test/integration/targets/become/tasks/main.yml4
-rw-r--r--test/integration/targets/blockinfile/tasks/main.yml3
-rw-r--r--test/integration/targets/blocks/unsafe_failed_task.yml2
-rw-r--r--test/integration/targets/callback_default/callback_default.out.result_format_yaml_lossy_verbose.stdout4
-rw-r--r--test/integration/targets/callback_default/callback_default.out.result_format_yaml_verbose.stdout4
-rw-r--r--test/integration/targets/check_mode/check_mode.yml2
-rw-r--r--test/integration/targets/check_mode/roles/test_check_mode/tasks/main.yml8
-rw-r--r--test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/connection/localconn.py2
-rw-r--r--test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing.py5
-rw-r--r--test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing_redirect_collection.py5
-rw-r--r--test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing_redirect_module.py5
-rw-r--r--test/integration/targets/collections/collections/ansible_collections/testns/content_adj/plugins/inventory/statichost.py1
-rw-r--r--test/integration/targets/collections/test_task_resolved_plugin/callback_plugins/display_resolved_action.py1
-rw-r--r--test/integration/targets/command_nonexisting/tasks/main.yml2
-rw-r--r--test/integration/targets/command_shell/tasks/main.yml42
-rw-r--r--test/integration/targets/conditionals/play.yml26
-rw-r--r--test/integration/targets/connection_delegation/aliases1
-rw-r--r--test/integration/targets/connection_paramiko_ssh/test_connection.inventory2
-rw-r--r--test/integration/targets/connection_psrp/tests.yml11
-rw-r--r--test/integration/targets/connection_winrm/tests.yml3
-rw-r--r--test/integration/targets/copy/tasks/main.yml2
-rw-r--r--test/integration/targets/copy/tasks/tests.yml152
-rw-r--r--test/integration/targets/cron/aliases1
-rw-r--r--test/integration/targets/debconf/tasks/main.yml42
-rw-r--r--test/integration/targets/delegate_to/delegate_local_from_root.yml2
-rwxr-xr-xtest/integration/targets/delegate_to/runme.sh4
-rw-r--r--test/integration/targets/delegate_to/test_delegate_to.yml27
-rw-r--r--test/integration/targets/dnf/aliases2
-rw-r--r--test/integration/targets/dnf/tasks/dnf.yml55
-rw-r--r--test/integration/targets/dnf/tasks/main.yml6
-rw-r--r--test/integration/targets/dnf/tasks/skip_broken_and_nobest.yml3
-rw-r--r--test/integration/targets/dnf/tasks/test_sos_removal.yml4
-rw-r--r--test/integration/targets/dpkg_selections/aliases1
-rw-r--r--test/integration/targets/dpkg_selections/tasks/dpkg_selections.yaml12
-rw-r--r--test/integration/targets/egg-info/lookup_plugins/import_pkg_resources.py2
-rw-r--r--test/integration/targets/environment/test_environment.yml10
-rw-r--r--test/integration/targets/error_from_connection/connection_plugins/dummy.py1
-rw-r--r--test/integration/targets/expect/tasks/main.yml9
-rw-r--r--test/integration/targets/facts_linux_network/aliases1
-rw-r--r--test/integration/targets/fetch/roles/fetch_tests/tasks/failures.yml10
-rw-r--r--test/integration/targets/file/tasks/link_rewrite.yml10
-rw-r--r--test/integration/targets/file/tasks/main.yml2
-rw-r--r--test/integration/targets/filter_core/tasks/main.yml32
-rw-r--r--test/integration/targets/filter_encryption/base.yml12
-rw-r--r--test/integration/targets/filter_mathstuff/tasks/main.yml54
-rw-r--r--test/integration/targets/find/tasks/main.yml3
-rw-r--r--test/integration/targets/fork_safe_stdio/aliases2
-rwxr-xr-xtest/integration/targets/fork_safe_stdio/runme.sh2
-rw-r--r--test/integration/targets/gathering_facts/library/file_utils.py3
-rwxr-xr-xtest/integration/targets/gathering_facts/runme.sh14
-rw-r--r--test/integration/targets/get_url/tasks/main.yml2
-rw-r--r--test/integration/targets/get_url/tasks/use_netrc.yml6
-rw-r--r--test/integration/targets/git/tasks/depth.yml9
-rw-r--r--test/integration/targets/git/tasks/forcefully-fetch-tag.yml4
-rw-r--r--test/integration/targets/git/tasks/gpg-verification.yml10
-rw-r--r--test/integration/targets/git/tasks/localmods.yml26
-rw-r--r--test/integration/targets/git/tasks/main.yml50
-rw-r--r--test/integration/targets/git/tasks/missing_hostkey.yml3
-rw-r--r--test/integration/targets/git/tasks/missing_hostkey_acceptnew.yml3
-rw-r--r--test/integration/targets/git/tasks/reset-origin.yml9
-rw-r--r--test/integration/targets/git/tasks/setup-local-repos.yml33
-rw-r--r--test/integration/targets/git/tasks/setup.yml38
-rw-r--r--test/integration/targets/git/tasks/single-branch.yml6
-rw-r--r--test/integration/targets/git/tasks/specific-revision.yml18
-rw-r--r--test/integration/targets/git/vars/main.yml1
-rw-r--r--test/integration/targets/group/tasks/main.yml23
-rw-r--r--test/integration/targets/group/tasks/tests.yml681
-rwxr-xr-xtest/integration/targets/handlers/runme.sh27
-rw-r--r--test/integration/targets/include_vars/tasks/main.yml52
-rw-r--r--test/integration/targets/include_vars/vars/services/service_vars.yml2
-rw-r--r--test/integration/targets/include_vars/vars/services/service_vars_fqcn.yml2
-rw-r--r--test/integration/targets/include_when_parent_is_dynamic/tasks.yml2
-rw-r--r--test/integration/targets/include_when_parent_is_static/tasks.yml2
-rw-r--r--test/integration/targets/includes/include_on_playbook_should_fail.yml2
-rw-r--r--test/integration/targets/includes/roles/test_includes/handlers/main.yml2
-rw-r--r--test/integration/targets/includes/roles/test_includes/tasks/main.yml40
-rw-r--r--test/integration/targets/includes/roles/test_includes_free/tasks/main.yml4
-rw-r--r--test/integration/targets/includes/roles/test_includes_host_pinned/tasks/main.yml2
-rwxr-xr-xtest/integration/targets/includes/runme.sh2
-rw-r--r--test/integration/targets/includes/test_includes2.yml4
-rw-r--r--test/integration/targets/includes/test_includes3.yml2
-rw-r--r--test/integration/targets/inventory/inventory_plugins/contructed_with_hostvars.py2
-rw-r--r--test/integration/targets/inventory_ini/inventory.ini2
-rwxr-xr-xtest/integration/targets/inventory_ini/runme.sh3
-rw-r--r--test/integration/targets/iptables/aliases1
-rw-r--r--test/integration/targets/iptables/tasks/chain_management.yml21
-rw-r--r--test/integration/targets/known_hosts/defaults/main.yml2
-rw-r--r--test/integration/targets/known_hosts/tasks/main.yml2
-rw-r--r--test/integration/targets/lookup_config/tasks/main.yml2
-rw-r--r--test/integration/targets/lookup_fileglob/issue72873/test.yml6
-rw-r--r--test/integration/targets/lookup_first_found/tasks/main.yml53
-rw-r--r--test/integration/targets/lookup_sequence/tasks/main.yml2
-rw-r--r--test/integration/targets/lookup_together/tasks/main.yml2
-rw-r--r--test/integration/targets/lookup_url/aliases9
-rw-r--r--test/integration/targets/lookup_url/meta/main.yml2
-rw-r--r--test/integration/targets/lookup_url/tasks/main.yml32
-rw-r--r--test/integration/targets/lookup_url/tasks/use_netrc.yml8
-rw-r--r--test/integration/targets/loop-connection/collections/ansible_collections/ns/name/meta/runtime.yml2
-rw-r--r--test/integration/targets/loop-connection/main.yml2
-rw-r--r--test/integration/targets/missing_required_lib/library/missing_required_lib.py2
-rw-r--r--test/integration/targets/module_defaults/action_plugins/debug.py2
-rw-r--r--test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/eos.py1
-rw-r--r--test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/ios.py1
-rw-r--r--test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/vyos.py1
-rw-r--r--test/integration/targets/module_no_log/aliases1
-rw-r--r--test/integration/targets/module_no_log/tasks/main.yml38
-rw-r--r--test/integration/targets/module_utils/library/test.py12
-rw-r--r--test/integration/targets/module_utils/library/test_failure.py4
-rw-r--r--test/integration/targets/module_utils/module_utils_test.yml2
-rw-r--r--test/integration/targets/module_utils_Ansible.Basic/library/ansible_basic_tests.ps12
-rw-r--r--test/integration/targets/module_utils_Ansible.ModuleUtils.AddType/library/add_type_test.ps168
-rwxr-xr-xtest/integration/targets/no_log/runme.sh7
-rw-r--r--test/integration/targets/old_style_cache_plugins/aliases1
-rw-r--r--test/integration/targets/old_style_cache_plugins/plugins/cache/configurable_redis.py1
-rw-r--r--test/integration/targets/old_style_cache_plugins/setup_redis_cache.yml3
-rw-r--r--test/integration/targets/old_style_vars_plugins/deprecation_warning/vars.py2
-rwxr-xr-xtest/integration/targets/old_style_vars_plugins/runme.sh38
-rw-r--r--test/integration/targets/omit/75692.yml2
-rw-r--r--test/integration/targets/package/tasks/main.yml2
-rw-r--r--test/integration/targets/package_facts/aliases1
-rw-r--r--test/integration/targets/parsing/roles/test_good_parsing/tasks/main.yml19
-rw-r--r--test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_conditional.yml2
-rwxr-xr-xtest/integration/targets/parsing/runme.sh4
-rw-r--r--test/integration/targets/path_lookups/testplay.yml8
-rwxr-xr-xtest/integration/targets/pause/test-pause.py23
-rw-r--r--test/integration/targets/pip/tasks/main.yml3
-rw-r--r--test/integration/targets/pip/tasks/pip.yml22
-rw-r--r--test/integration/targets/pkg_resources/lookup_plugins/check_pkg_resources.py2
-rw-r--r--test/integration/targets/plugin_filtering/filter_lookup.yml2
-rw-r--r--test/integration/targets/plugin_filtering/filter_modules.yml2
-rw-r--r--test/integration/targets/plugin_filtering/filter_ping.yml2
-rw-r--r--test/integration/targets/plugin_filtering/filter_stat.yml2
-rwxr-xr-xtest/integration/targets/plugin_filtering/runme.sh16
-rw-r--r--test/integration/targets/plugin_loader/override/filters.yml2
-rwxr-xr-xtest/integration/targets/plugin_loader/runme.sh5
-rw-r--r--test/integration/targets/rel_plugin_loading/subdir/inventory_plugins/notyaml.py2
-rw-r--r--test/integration/targets/remote_tmp/playbook.yml43
-rw-r--r--test/integration/targets/replace/tasks/main.yml19
-rwxr-xr-xtest/integration/targets/roles/runme.sh35
-rw-r--r--test/integration/targets/roles_arg_spec/roles/c/meta/main.yml9
-rw-r--r--test/integration/targets/roles_arg_spec/test.yml130
-rw-r--r--test/integration/targets/rpm_key/tasks/rpm_key.yaml26
-rw-r--r--test/integration/targets/script/tasks/main.yml11
-rw-r--r--test/integration/targets/service/aliases1
-rw-r--r--test/integration/targets/service/files/ansible_test_service.py1
-rw-r--r--test/integration/targets/service_facts/aliases1
-rw-r--r--test/integration/targets/setup_deb_repo/tasks/main.yml1
-rw-r--r--test/integration/targets/setup_paramiko/install-Alpine-3-python-3.yml9
-rw-r--r--test/integration/targets/setup_paramiko/uninstall-Alpine-3-python-3.yml4
-rw-r--r--test/integration/targets/setup_rpm_repo/tasks/main.yml15
-rwxr-xr-xtest/integration/targets/strategy_linear/runme.sh2
-rw-r--r--test/integration/targets/subversion/aliases2
-rw-r--r--test/integration/targets/systemd/tasks/test_indirect_service.yml2
-rw-r--r--test/integration/targets/systemd/vars/Debian.yml2
-rwxr-xr-xtest/integration/targets/tags/runme.sh9
-rw-r--r--test/integration/targets/tasks/playbook.yml5
-rwxr-xr-xtest/integration/targets/tasks/runme.sh2
-rwxr-xr-xtest/integration/targets/template/runme.sh7
-rw-r--r--test/integration/targets/template/tasks/main.yml4
-rw-r--r--test/integration/targets/template/unsafe.yml5
-rw-r--r--test/integration/targets/template_jinja2_non_native/macro_override.yml2
-rw-r--r--test/integration/targets/templating/tasks/main.yml11
-rw-r--r--test/integration/targets/test_core/tasks/main.yml13
-rw-r--r--test/integration/targets/unarchive/tasks/main.yml1
-rw-r--r--test/integration/targets/unarchive/tasks/test_different_language_var.yml4
-rw-r--r--test/integration/targets/unarchive/tasks/test_mode.yml23
-rw-r--r--test/integration/targets/unsafe_writes/aliases1
-rw-r--r--test/integration/targets/until/tasks/main.yml34
-rw-r--r--test/integration/targets/unvault/main.yml1
-rwxr-xr-xtest/integration/targets/unvault/runme.sh2
-rw-r--r--test/integration/targets/uri/tasks/main.yml37
-rw-r--r--test/integration/targets/uri/tasks/redirect-none.yml2
-rw-r--r--test/integration/targets/uri/tasks/redirect-urllib2.yml35
-rw-r--r--test/integration/targets/uri/tasks/return-content.yml2
-rw-r--r--test/integration/targets/uri/tasks/use_netrc.yml2
-rw-r--r--test/integration/targets/user/tasks/main.yml2
-rw-r--r--test/integration/targets/user/tasks/test_create_user.yml12
-rw-r--r--test/integration/targets/user/tasks/test_create_user_home.yml18
-rw-r--r--test/integration/targets/user/tasks/test_local.yml40
-rw-r--r--test/integration/targets/user/vars/main.yml2
-rw-r--r--test/integration/targets/var_blending/roles/test_var_blending/tasks/main.yml10
-rwxr-xr-xtest/integration/targets/var_precedence/ansible-var-precedence-check.py5
-rw-r--r--test/integration/targets/var_precedence/test_var_precedence.yml16
-rw-r--r--test/integration/targets/wait_for/tasks/main.yml11
-rw-r--r--test/integration/targets/win_exec_wrapper/tasks/main.yml9
-rw-r--r--test/integration/targets/win_fetch/tasks/main.yml14
-rw-r--r--test/integration/targets/win_script/files/test_script_with_args.ps12
-rw-r--r--test/integration/targets/win_script/files/test_script_with_errors.ps12
-rw-r--r--test/integration/targets/windows-minimal/library/win_ping_set_attr.ps18
-rw-r--r--test/integration/targets/windows-minimal/library/win_ping_strict_mode_error.ps18
-rw-r--r--test/integration/targets/windows-minimal/library/win_ping_syntax_error.ps18
-rw-r--r--test/integration/targets/windows-minimal/library/win_ping_throw.ps18
-rw-r--r--test/integration/targets/windows-minimal/library/win_ping_throw_string.ps18
-rw-r--r--test/integration/targets/yum/aliases1
-rw-r--r--test/integration/targets/yum/filter_plugins/filter_list_of_tuples_by_first_param.py2
275 files changed, 3107 insertions, 960 deletions
diff --git a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/MANIFEST.json b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/MANIFEST.json
index 243a5e43..36f402fc 100644
--- a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/MANIFEST.json
+++ b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/MANIFEST.json
@@ -17,7 +17,7 @@
"version": "0.1.1231",
"readme": "README.md",
"license_file": "COPYING",
- "homepage": "",
+ "homepage": ""
},
"file_manifest_file": {
"format": 1,
diff --git a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py
index caec2ed6..dfc12710 100644
--- a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py
+++ b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py
@@ -20,7 +20,6 @@ DOCUMENTATION = '''
required: True
'''
-from ansible.errors import AnsibleParserError
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable
diff --git a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/lookup/noop.py b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/lookup/noop.py
index d4569869..639d3c6b 100644
--- a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/lookup/noop.py
+++ b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/lookup/noop.py
@@ -32,7 +32,8 @@ RETURN = """
version_added: 1.0.0
"""
-from ansible.module_utils.common._collections_compat import Sequence
+from collections.abc import Sequence
+
from ansible.plugins.lookup import LookupBase
from ansible.errors import AnsibleError
diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/MANIFEST.json b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/MANIFEST.json
index 243a5e43..36f402fc 100644
--- a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/MANIFEST.json
+++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/MANIFEST.json
@@ -17,7 +17,7 @@
"version": "0.1.1231",
"readme": "README.md",
"license_file": "COPYING",
- "homepage": "",
+ "homepage": ""
},
"file_manifest_file": {
"format": 1,
diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py
index cbb8f0fb..1870b8ea 100644
--- a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py
+++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py
@@ -19,7 +19,6 @@ DOCUMENTATION = '''
required: True
'''
-from ansible.errors import AnsibleParserError
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable
diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py
index 79b7a704..aaaecb80 100644
--- a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py
+++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py
@@ -3,12 +3,17 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-DOCUMENTATION = '''
+DOCUMENTATION = r'''
---
module: randommodule
short_description: A random module
description:
- A random module.
+ - See O(foo.bar.baz#role:main:foo=bar) for how this is used in the P(foo.bar.baz#role)'s C(main) entrypoint.
+ - See L(the docsite,https://docs.ansible.com/ansible-core/devel/) for more information on ansible-core.
+ - This module is not related to the M(ansible.builtin.copy) module. HORIZONTALLINE You might also be interested
+ in R(ansible_python_interpreter, ansible_python_interpreter).
+ - Sometimes you have M(broken markup) that will result in error messages.
author:
- Ansible Core Team
version_added: 1.0.0
@@ -18,22 +23,22 @@ deprecated:
removed_in: '3.0.0'
options:
test:
- description: Some text.
+ description: Some text. Consider not using O(ignore:foo=bar).
type: str
version_added: 1.2.0
sub:
- description: Suboptions.
+ description: Suboptions. Contains O(sub.subtest), which can be set to V(123). You can use E(TEST_ENV) to set this.
type: dict
suboptions:
subtest:
- description: A suboption.
+ description: A suboption. Not compatible to O(ansible.builtin.copy#module:path=c:\\foo\(1\).txt).
type: int
version_added: 1.1.0
# The following is the wrong syntax, and should not get processed
# by add_collection_to_versions_and_dates()
options:
subtest2:
- description: Another suboption.
+ description: Another suboption. Useful when P(ansible.builtin.shuffle#filter) is used with value V([a,b,\),d\\]).
type: float
version_added: 1.1.0
# The following is not supported in modules, and should not get processed
@@ -65,7 +70,7 @@ seealso:
EXAMPLES = '''
'''
-RETURN = '''
+RETURN = r'''
z_last:
description: A last result.
type: str
@@ -75,7 +80,8 @@ z_last:
m_middle:
description:
- This should be in the middle.
- - Has some more data
+ - Has some more data.
+ - Check out RV(m_middle.suboption) and compare it to RV(a_first=foo) and RV(community.general.foo#lookup:value).
type: dict
returned: success and 1st of month
contains:
@@ -86,7 +92,7 @@ m_middle:
version_added: 1.4.0
a_first:
- description: A first result.
+ description: A first result. Use RV(a_first=foo\(bar\\baz\)bam).
type: str
returned: success
'''
diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/test/yolo.yml b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/test/yolo.yml
index cc60945e..ebfea2af 100644
--- a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/test/yolo.yml
+++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/test/yolo.yml
@@ -8,6 +8,25 @@ DOCUMENTATION:
description: does not matter
type: raw
required: true
+ seealso:
+ - module: ansible.builtin.test
+ - module: testns.testcol.fakemodule
+ description: A fake module
+ - plugin: testns.testcol.noop
+ plugin_type: lookup
+ - plugin: testns.testcol.grouped
+ plugin_type: filter
+ description: A grouped filter.
+ - plugin: ansible.builtin.combine
+ plugin_type: filter
+ - plugin: ansible.builtin.file
+ plugin_type: lookup
+ description: Read a file on the controller.
+ - link: https://docs.ansible.com
+ name: Ansible docsite
+ description: See also the Ansible docsite.
+ - ref: foo_bar
+ description: Some foo bar.
EXAMPLES: |
{{ 'anything' is yolo }}
diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/MANIFEST.json b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/MANIFEST.json
index 02ec289f..e930d7d8 100644
--- a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/MANIFEST.json
+++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/MANIFEST.json
@@ -17,7 +17,7 @@
"version": "1.2.0",
"readme": "README.md",
"license_file": "COPYING",
- "homepage": "",
+ "homepage": ""
},
"file_manifest_file": {
"format": 1,
diff --git a/test/integration/targets/ansible-doc/randommodule-text.output b/test/integration/targets/ansible-doc/randommodule-text.output
index 602d66ec..ca361346 100644
--- a/test/integration/targets/ansible-doc/randommodule-text.output
+++ b/test/integration/targets/ansible-doc/randommodule-text.output
@@ -1,6 +1,13 @@
> TESTNS.TESTCOL.RANDOMMODULE (./collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py)
- A random module.
+ A random module. See `foo=bar' (of role foo.bar.baz, main
+ entrypoint) for how this is used in the [foo.bar.baz]'s `main'
+ entrypoint. See the docsite <https://docs.ansible.com/ansible-
+ core/devel/> for more information on ansible-core. This module
+ is not related to the [ansible.builtin.copy] module.
+ ------------- You might also be interested in
+ ansible_python_interpreter. Sometimes you have [broken markup]
+ that will result in error messages.
ADDED IN: version 1.0.0 of testns.testcol
@@ -14,7 +21,8 @@ DEPRECATED:
OPTIONS (= is mandatory):
- sub
- Suboptions.
+ Suboptions. Contains `sub.subtest', which can be set to `123'.
+ You can use `TEST_ENV' to set this.
set_via:
env:
- deprecated:
@@ -29,7 +37,8 @@ OPTIONS (= is mandatory):
OPTIONS:
- subtest2
- Another suboption.
+ Another suboption. Useful when [ansible.builtin.shuffle]
+ is used with value `[a,b,),d\]'.
default: null
type: float
added in: version 1.1.0
@@ -39,14 +48,15 @@ OPTIONS (= is mandatory):
SUBOPTIONS:
- subtest
- A suboption.
+ A suboption. Not compatible to `path=c:\foo(1).txt' (of
+ module ansible.builtin.copy).
default: null
type: int
added in: version 1.1.0 of testns.testcol
- test
- Some text.
+ Some text. Consider not using `foo=bar'.
default: null
type: str
added in: version 1.2.0 of testns.testcol
@@ -93,13 +103,15 @@ EXAMPLES:
RETURN VALUES:
- a_first
- A first result.
+ A first result. Use `a_first=foo(bar\baz)bam'.
returned: success
type: str
- m_middle
This should be in the middle.
- Has some more data
+ Has some more data.
+ Check out `m_middle.suboption' and compare it to `a_first=foo'
+ and `value' (of lookup plugin community.general.foo).
returned: success and 1st of month
type: dict
diff --git a/test/integration/targets/ansible-doc/randommodule.output b/test/integration/targets/ansible-doc/randommodule.output
index cf036000..f40202a8 100644
--- a/test/integration/targets/ansible-doc/randommodule.output
+++ b/test/integration/targets/ansible-doc/randommodule.output
@@ -12,14 +12,18 @@
"why": "Test deprecation"
},
"description": [
- "A random module."
+ "A random module.",
+ "See O(foo.bar.baz#role:main:foo=bar) for how this is used in the P(foo.bar.baz#role)'s C(main) entrypoint.",
+ "See L(the docsite,https://docs.ansible.com/ansible-core/devel/) for more information on ansible-core.",
+ "This module is not related to the M(ansible.builtin.copy) module. HORIZONTALLINE You might also be interested in R(ansible_python_interpreter, ansible_python_interpreter).",
+ "Sometimes you have M(broken markup) that will result in error messages."
],
"filename": "./collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py",
"has_action": false,
"module": "randommodule",
"options": {
"sub": {
- "description": "Suboptions.",
+ "description": "Suboptions. Contains O(sub.subtest), which can be set to V(123). You can use E(TEST_ENV) to set this.",
"env": [
{
"deprecated": {
@@ -34,14 +38,14 @@
],
"options": {
"subtest2": {
- "description": "Another suboption.",
+ "description": "Another suboption. Useful when P(ansible.builtin.shuffle#filter) is used with value V([a,b,\\),d\\\\]).",
"type": "float",
"version_added": "1.1.0"
}
},
"suboptions": {
"subtest": {
- "description": "A suboption.",
+ "description": "A suboption. Not compatible to O(ansible.builtin.copy#module:path=c:\\\\foo\\(1\\).txt).",
"type": "int",
"version_added": "1.1.0",
"version_added_collection": "testns.testcol"
@@ -50,7 +54,7 @@
"type": "dict"
},
"test": {
- "description": "Some text.",
+ "description": "Some text. Consider not using O(ignore:foo=bar).",
"type": "str",
"version_added": "1.2.0",
"version_added_collection": "testns.testcol"
@@ -103,7 +107,7 @@
"metadata": null,
"return": {
"a_first": {
- "description": "A first result.",
+ "description": "A first result. Use RV(a_first=foo\\(bar\\\\baz\\)bam).",
"returned": "success",
"type": "str"
},
@@ -123,7 +127,8 @@
},
"description": [
"This should be in the middle.",
- "Has some more data"
+ "Has some more data.",
+ "Check out RV(m_middle.suboption) and compare it to RV(a_first=foo) and RV(community.general.foo#lookup:value)."
],
"returned": "success and 1st of month",
"type": "dict"
diff --git a/test/integration/targets/ansible-doc/runme.sh b/test/integration/targets/ansible-doc/runme.sh
index f51fa8a4..b525766c 100755
--- a/test/integration/targets/ansible-doc/runme.sh
+++ b/test/integration/targets/ansible-doc/runme.sh
@@ -1,36 +1,74 @@
#!/usr/bin/env bash
-set -eux
+# always set sane error behaviors, enable execution tracing later if sufficient verbosity requested
+set -eu
+
+verbosity=0
+
+# default to silent output for naked grep; -vvv+ will adjust this
+export GREP_OPTS=-q
+
+# shell tracing output is very large from this script; only enable if >= -vvv was passed
+while getopts :v opt
+do case "$opt" in
+ v) ((verbosity+=1)) ;;
+ *) ;;
+ esac
+done
+
+if (( verbosity >= 3 ));
+then
+ set -x;
+ export GREP_OPTS= ;
+fi
+
+echo "running playbook-backed docs tests"
ansible-playbook test.yml -i inventory "$@"
# test keyword docs
-ansible-doc -t keyword -l | grep 'vars_prompt: list of variables to prompt for.'
-ansible-doc -t keyword vars_prompt | grep 'description: list of variables to prompt for.'
-ansible-doc -t keyword asldkfjaslidfhals 2>&1 | grep 'Skipping Invalid keyword'
+ansible-doc -t keyword -l | grep $GREP_OPTS 'vars_prompt: list of variables to prompt for.'
+ansible-doc -t keyword vars_prompt | grep $GREP_OPTS 'description: list of variables to prompt for.'
+ansible-doc -t keyword asldkfjaslidfhals 2>&1 | grep $GREP_OPTS 'Skipping Invalid keyword'
# collections testing
(
unset ANSIBLE_PLAYBOOK_DIR
cd "$(dirname "$0")"
-# test module docs from collection
+
+echo "test fakemodule docs from collection"
# we use sed to strip the module path from the first line
current_out="$(ansible-doc --playbook-dir ./ testns.testcol.fakemodule | sed '1 s/\(^> TESTNS\.TESTCOL\.FAKEMODULE\).*(.*)$/\1/')"
expected_out="$(sed '1 s/\(^> TESTNS\.TESTCOL\.FAKEMODULE\).*(.*)$/\1/' fakemodule.output)"
test "$current_out" == "$expected_out"
+echo "test randommodule docs from collection"
# we use sed to strip the plugin path from the first line, and fix-urls.py to unbreak and replace URLs from stable-X branches
current_out="$(ansible-doc --playbook-dir ./ testns.testcol.randommodule | sed '1 s/\(^> TESTNS\.TESTCOL\.RANDOMMODULE\).*(.*)$/\1/' | python fix-urls.py)"
expected_out="$(sed '1 s/\(^> TESTNS\.TESTCOL\.RANDOMMODULE\).*(.*)$/\1/' randommodule-text.output)"
test "$current_out" == "$expected_out"
-# ensure we do work with valid collection name for list
-ansible-doc --list testns.testcol --playbook-dir ./ 2>&1 | grep -v "Invalid collection name"
+echo "test yolo filter docs from collection"
+# we use sed to strip the plugin path from the first line, and fix-urls.py to unbreak and replace URLs from stable-X branches
+current_out="$(ansible-doc --playbook-dir ./ testns.testcol.yolo --type test | sed '1 s/\(^> TESTNS\.TESTCOL\.YOLO\).*(.*)$/\1/' | python fix-urls.py)"
+expected_out="$(sed '1 s/\(^> TESTNS\.TESTCOL\.YOLO\).*(.*)$/\1/' yolo-text.output)"
+test "$current_out" == "$expected_out"
+
+echo "ensure we do work with valid collection name for list"
+ansible-doc --list testns.testcol --playbook-dir ./ 2>&1 | grep $GREP_OPTS -v "Invalid collection name"
-# ensure we dont break on invalid collection name for list
-ansible-doc --list testns.testcol.fakemodule --playbook-dir ./ 2>&1 | grep "Invalid collection name"
+echo "ensure we dont break on invalid collection name for list"
+ansible-doc --list testns.testcol.fakemodule --playbook-dir ./ 2>&1 | grep $GREP_OPTS "Invalid collection name"
-# test listing diff plugin types from collection
+echo "filter list with more than one collection (1/2)"
+output=$(ansible-doc --list testns.testcol3 testns.testcol4 --playbook-dir ./ 2>&1 | wc -l)
+test "$output" -eq 2
+
+echo "filter list with more than one collection (2/2)"
+output=$(ansible-doc --list testns.testcol testns.testcol4 --playbook-dir ./ 2>&1 | wc -l)
+test "$output" -eq 5
+
+echo "testing ansible-doc output for various plugin types"
for ptype in cache inventory lookup vars filter module
do
# each plugin type adds 1 from collection
@@ -50,20 +88,20 @@ do
elif [ "${ptype}" == "lookup" ]; then expected_names=("noop");
elif [ "${ptype}" == "vars" ]; then expected_names=("noop_vars_plugin"); fi
fi
- # ensure we ONLY list from the collection
+ echo "testing collection-filtered list for plugin ${ptype}"
justcol=$(ansible-doc -l -t ${ptype} --playbook-dir ./ testns.testcol|wc -l)
test "$justcol" -eq "$expected"
- # ensure the right names are displayed
+ echo "validate collection plugin name display for plugin ${ptype}"
list_result=$(ansible-doc -l -t ${ptype} --playbook-dir ./ testns.testcol)
metadata_result=$(ansible-doc --metadata-dump --no-fail-on-errors -t ${ptype} --playbook-dir ./ testns.testcol)
for name in "${expected_names[@]}"; do
- echo "${list_result}" | grep "testns.testcol.${name}"
- echo "${metadata_result}" | grep "testns.testcol.${name}"
+ echo "${list_result}" | grep $GREP_OPTS "testns.testcol.${name}"
+ echo "${metadata_result}" | grep $GREP_OPTS "testns.testcol.${name}"
done
- # ensure we get error if passinginvalid collection, much less any plugins
- ansible-doc -l -t ${ptype} testns.testcol 2>&1 | grep "unable to locate collection"
+ # ensure we get error if passing invalid collection, much less any plugins
+ ansible-doc -l -t ${ptype} bogus.boguscoll 2>&1 | grep $GREP_OPTS "unable to locate collection"
# TODO: do we want per namespace?
# ensure we get 1 plugins when restricting namespace
@@ -73,20 +111,28 @@ done
#### test role functionality
-# Test role text output
+echo "testing role text output"
# we use sed to strip the role path from the first line
current_role_out="$(ansible-doc -t role -r ./roles test_role1 | sed '1 s/\(^> TEST_ROLE1\).*(.*)$/\1/')"
expected_role_out="$(sed '1 s/\(^> TEST_ROLE1\).*(.*)$/\1/' fakerole.output)"
test "$current_role_out" == "$expected_role_out"
+echo "testing multiple role entrypoints"
# Two collection roles are defined, but only 1 has a role arg spec with 2 entry points
output=$(ansible-doc -t role -l --playbook-dir . testns.testcol | wc -l)
test "$output" -eq 2
+echo "test listing roles with multiple collection filters"
+# Two collection roles are defined, but only 1 has a role arg spec with 2 entry points
+output=$(ansible-doc -t role -l --playbook-dir . testns.testcol2 testns.testcol | wc -l)
+test "$output" -eq 2
+
+echo "testing standalone roles"
# Include normal roles (no collection filter)
output=$(ansible-doc -t role -l --playbook-dir . | wc -l)
test "$output" -eq 3
+echo "testing role precedence"
# Test that a role in the playbook dir with the same name as a role in the
# 'roles' subdir of the playbook dir does not appear (lower precedence).
output=$(ansible-doc -t role -l --playbook-dir . | grep -c "test_role1 from roles subdir")
@@ -94,7 +140,7 @@ test "$output" -eq 1
output=$(ansible-doc -t role -l --playbook-dir . | grep -c "test_role1 from playbook dir" || true)
test "$output" -eq 0
-# Test entry point filter
+echo "testing role entrypoint filter"
current_role_out="$(ansible-doc -t role --playbook-dir . testns.testcol.testrole -e alternate| sed '1 s/\(^> TESTNS\.TESTCOL\.TESTROLE\).*(.*)$/\1/')"
expected_role_out="$(sed '1 s/\(^> TESTNS\.TESTCOL\.TESTROLE\).*(.*)$/\1/' fakecollrole.output)"
test "$current_role_out" == "$expected_role_out"
@@ -103,10 +149,16 @@ test "$current_role_out" == "$expected_role_out"
#### test add_collection_to_versions_and_dates()
+echo "testing json output"
current_out="$(ansible-doc --json --playbook-dir ./ testns.testcol.randommodule | sed 's/ *$//' | sed 's/ *"filename": "[^"]*",$//')"
expected_out="$(sed 's/ *"filename": "[^"]*",$//' randommodule.output)"
test "$current_out" == "$expected_out"
+echo "testing json output 2"
+current_out="$(ansible-doc --json --playbook-dir ./ testns.testcol.yolo --type test | sed 's/ *$//' | sed 's/ *"filename": "[^"]*",$//')"
+expected_out="$(sed 's/ *"filename": "[^"]*",$//' yolo.output)"
+test "$current_out" == "$expected_out"
+
current_out="$(ansible-doc --json --playbook-dir ./ -t cache testns.testcol.notjsonfile | sed 's/ *$//' | sed 's/ *"filename": "[^"]*",$//')"
expected_out="$(sed 's/ *"filename": "[^"]*",$//' notjsonfile.output)"
test "$current_out" == "$expected_out"
@@ -119,8 +171,9 @@ current_out="$(ansible-doc --json --playbook-dir ./ -t vars testns.testcol.noop_
expected_out="$(sed 's/ *"filename": "[^"]*",$//' noop_vars_plugin.output)"
test "$current_out" == "$expected_out"
+echo "testing metadata dump"
# just ensure it runs
-ANSIBLE_LIBRARY='./nolibrary' ansible-doc --metadata-dump --playbook-dir /dev/null >/dev/null
+ANSIBLE_LIBRARY='./nolibrary' ansible-doc --metadata-dump --playbook-dir /dev/null 1>/dev/null 2>&1
# create broken role argument spec
mkdir -p broken-docs/collections/ansible_collections/testns/testcol/roles/testrole/meta
@@ -144,71 +197,72 @@ argument_specs:
EOF
# ensure that --metadata-dump does not fail when --no-fail-on-errors is supplied
-ANSIBLE_LIBRARY='./nolibrary' ansible-doc --metadata-dump --no-fail-on-errors --playbook-dir broken-docs testns.testcol >/dev/null
+ANSIBLE_LIBRARY='./nolibrary' ansible-doc --metadata-dump --no-fail-on-errors --playbook-dir broken-docs testns.testcol 1>/dev/null 2>&1
# ensure that --metadata-dump does fail when --no-fail-on-errors is not supplied
output=$(ANSIBLE_LIBRARY='./nolibrary' ansible-doc --metadata-dump --playbook-dir broken-docs testns.testcol 2>&1 | grep -c 'ERROR!' || true)
test "${output}" -eq 1
-# ensure we list the 'legacy plugins'
+
+echo "testing legacy plugin listing"
[ "$(ansible-doc -M ./library -l ansible.legacy |wc -l)" -gt "0" ]
-# playbook dir should work the same
+echo "testing legacy plugin list via --playbook-dir"
[ "$(ansible-doc -l ansible.legacy --playbook-dir ./|wc -l)" -gt "0" ]
-# see that we show undocumented when missing docs
+echo "testing undocumented plugin output"
[ "$(ansible-doc -M ./library -l ansible.legacy |grep -c UNDOCUMENTED)" == "6" ]
-# ensure filtering works and does not include any 'test_' modules
+echo "testing filtering does not include any 'test_' modules"
[ "$(ansible-doc -M ./library -l ansible.builtin |grep -c test_)" == 0 ]
[ "$(ansible-doc --playbook-dir ./ -l ansible.builtin |grep -c test_)" == 0 ]
-# ensure filtering still shows modules
+echo "testing filtering still shows modules"
count=$(ANSIBLE_LIBRARY='./nolibrary' ansible-doc -l ansible.builtin |wc -l)
[ "${count}" -gt "0" ]
[ "$(ansible-doc -M ./library -l ansible.builtin |wc -l)" == "${count}" ]
[ "$(ansible-doc --playbook-dir ./ -l ansible.builtin |wc -l)" == "${count}" ]
-# produce 'sidecar' docs for test
+echo "testing sidecar docs for jinja plugins"
[ "$(ansible-doc -t test --playbook-dir ./ testns.testcol.yolo| wc -l)" -gt "0" ]
[ "$(ansible-doc -t filter --playbook-dir ./ donothing| wc -l)" -gt "0" ]
[ "$(ansible-doc -t filter --playbook-dir ./ ansible.legacy.donothing| wc -l)" -gt "0" ]
-# no docs and no sidecar
-ansible-doc -t filter --playbook-dir ./ nodocs 2>&1| grep -c 'missing documentation' || true
+echo "testing no docs and no sidecar"
+ansible-doc -t filter --playbook-dir ./ nodocs 2>&1| grep $GREP_OPTS -c 'missing documentation' || true
-# produce 'sidecar' docs for module
+echo "testing sidecar docs for module"
[ "$(ansible-doc -M ./library test_win_module| wc -l)" -gt "0" ]
[ "$(ansible-doc --playbook-dir ./ test_win_module| wc -l)" -gt "0" ]
-# test 'double DOCUMENTATION' use
+echo "testing duplicate DOCUMENTATION"
[ "$(ansible-doc --playbook-dir ./ double_doc| wc -l)" -gt "0" ]
-# don't break on module dir
+echo "testing don't break on module dir"
ansible-doc --list --module-path ./modules > /dev/null
-# ensure we dedupe by fqcn and not base name
+echo "testing dedupe by fqcn and not base name"
[ "$(ansible-doc -l -t filter --playbook-dir ./ |grep -c 'b64decode')" -eq "3" ]
-# ensure we don't show duplicates for plugins that only exist in ansible.builtin when listing ansible.legacy plugins
+echo "testing no duplicates for plugins that only exist in ansible.builtin when listing ansible.legacy plugins"
[ "$(ansible-doc -l -t filter --playbook-dir ./ |grep -c 'b64encode')" -eq "1" ]
-# with playbook dir, legacy should override
-ansible-doc -t filter split --playbook-dir ./ |grep histerical
+echo "testing with playbook dir, legacy should override"
+ansible-doc -t filter split --playbook-dir ./ |grep $GREP_OPTS histerical
pyc_src="$(pwd)/filter_plugins/other.py"
pyc_1="$(pwd)/filter_plugins/split.pyc"
pyc_2="$(pwd)/library/notaplugin.pyc"
trap 'rm -rf "$pyc_1" "$pyc_2"' EXIT
-# test pyc files are not used as adjacent documentation
+echo "testing pyc files are not used as adjacent documentation"
python -c "import py_compile; py_compile.compile('$pyc_src', cfile='$pyc_1')"
-ansible-doc -t filter split --playbook-dir ./ |grep histerical
+ansible-doc -t filter split --playbook-dir ./ |grep $GREP_OPTS histerical
-# test pyc files are not listed as plugins
+echo "testing pyc files are not listed as plugins"
python -c "import py_compile; py_compile.compile('$pyc_src', cfile='$pyc_2')"
test "$(ansible-doc -l -t module --playbook-dir ./ 2>&1 1>/dev/null |grep -c "notaplugin")" == 0
-# without playbook dir, builtin should return
-ansible-doc -t filter split |grep -v histerical
+echo "testing without playbook dir, builtin should return"
+ansible-doc -t filter split 2>&1 |grep $GREP_OPTS -v histerical
diff --git a/test/integration/targets/ansible-galaxy-collection-cli/files/expected.txt b/test/integration/targets/ansible-galaxy-collection-cli/files/expected.txt
index 110009e3..69218290 100644
--- a/test/integration/targets/ansible-galaxy-collection-cli/files/expected.txt
+++ b/test/integration/targets/ansible-galaxy-collection-cli/files/expected.txt
@@ -1,6 +1,11 @@
MANIFEST.json
FILES.json
README.rst
+GPL
+LICENSES/
+LICENSES/MIT.txt
+.reuse/
+.reuse/dep5
changelogs/
docs/
playbooks/
@@ -88,6 +93,7 @@ plugins/test/bar.yml
plugins/test/baz.yaml
plugins/test/test.py
plugins/vars/bar.yml
+plugins/vars/bar.yml.license
plugins/vars/baz.yaml
plugins/vars/test.py
roles/foo/
diff --git a/test/integration/targets/ansible-galaxy-collection-cli/files/galaxy.yml b/test/integration/targets/ansible-galaxy-collection-cli/files/galaxy.yml
index 8f0ada0b..140bf2a7 100644
--- a/test/integration/targets/ansible-galaxy-collection-cli/files/galaxy.yml
+++ b/test/integration/targets/ansible-galaxy-collection-cli/files/galaxy.yml
@@ -2,6 +2,7 @@ namespace: ns
name: col
version: 1.0.0
readme: README.rst
+license_file: GPL
authors:
- Ansible
manifest:
diff --git a/test/integration/targets/ansible-galaxy-collection-cli/files/make_collection_dir.py b/test/integration/targets/ansible-galaxy-collection-cli/files/make_collection_dir.py
index 913a6f79..60c43cc7 100644
--- a/test/integration/targets/ansible-galaxy-collection-cli/files/make_collection_dir.py
+++ b/test/integration/targets/ansible-galaxy-collection-cli/files/make_collection_dir.py
@@ -5,8 +5,12 @@ paths = [
'ns-col-1.0.0.tar.gz',
'foo.txt',
'README.rst',
+ 'GPL',
+ 'LICENSES/MIT.txt',
+ '.reuse/dep5',
'artifacts/.gitkeep',
'plugins/vars/bar.yml',
+ 'plugins/vars/bar.yml.license',
'plugins/vars/baz.yaml',
'plugins/vars/test.py',
'plugins/vars/docs.md',
diff --git a/test/integration/targets/ansible-galaxy-collection-scm/tasks/main.yml b/test/integration/targets/ansible-galaxy-collection-scm/tasks/main.yml
index dab599b1..f0e78ca0 100644
--- a/test/integration/targets/ansible-galaxy-collection-scm/tasks/main.yml
+++ b/test/integration/targets/ansible-galaxy-collection-scm/tasks/main.yml
@@ -5,7 +5,7 @@
- name: Test installing collections from git repositories
environment:
- ANSIBLE_COLLECTIONS_PATHS: "{{ galaxy_dir }}/collections"
+ ANSIBLE_COLLECTIONS_PATH: "{{ galaxy_dir }}/collections"
vars:
cleanup: True
galaxy_dir: "{{ galaxy_dir }}"
diff --git a/test/integration/targets/ansible-galaxy-collection-scm/tasks/multi_collection_repo_all.yml b/test/integration/targets/ansible-galaxy-collection-scm/tasks/multi_collection_repo_all.yml
index f22f9844..91ed9124 100644
--- a/test/integration/targets/ansible-galaxy-collection-scm/tasks/multi_collection_repo_all.yml
+++ b/test/integration/targets/ansible-galaxy-collection-scm/tasks/multi_collection_repo_all.yml
@@ -14,6 +14,8 @@
command: 'ansible-galaxy collection install {{ artifact_path }} -p {{ alt_install_path }} --no-deps'
vars:
artifact_path: "{{ galaxy_dir }}/ansible_test-collection_1-1.0.0.tar.gz"
+ environment:
+ ANSIBLE_COLLECTIONS_PATH: ""
- name: check if the files and folders in build_ignore were respected
stat:
diff --git a/test/integration/targets/ansible-galaxy-collection-scm/tasks/setup_recursive_scm_dependency.yml b/test/integration/targets/ansible-galaxy-collection-scm/tasks/setup_recursive_scm_dependency.yml
index dd307d72..520dbe5c 100644
--- a/test/integration/targets/ansible-galaxy-collection-scm/tasks/setup_recursive_scm_dependency.yml
+++ b/test/integration/targets/ansible-galaxy-collection-scm/tasks/setup_recursive_scm_dependency.yml
@@ -22,7 +22,12 @@
lineinfile:
path: '{{ scm_path }}/namespace_2/collection_2/galaxy.yml'
regexp: '^dependencies'
- line: "dependencies: {'git+file://{{ scm_path }}/namespace_1/.git#collection_1/': 'master'}"
+ # NOTE: The committish is set to `HEAD` here because Git's default has
+ # NOTE: changed to `main` and it behaves differently in
+ # NOTE: different envs with different Git versions.
+ line: >-
+ dependencies:
+ {'git+file://{{ scm_path }}/namespace_1/.git#collection_1/': 'HEAD'}
- name: Commit the changes
shell: git add ./; git commit -m 'add collection'
diff --git a/test/integration/targets/ansible-galaxy-collection/library/reset_pulp.py b/test/integration/targets/ansible-galaxy-collection/library/reset_pulp.py
index 53c29f77..c1f5e1d7 100644
--- a/test/integration/targets/ansible-galaxy-collection/library/reset_pulp.py
+++ b/test/integration/targets/ansible-galaxy-collection/library/reset_pulp.py
@@ -84,7 +84,8 @@ def invoke_api(module, url, method='GET', data=None, status_codes=None):
resp, info = fetch_url(module, url, method=method, data=data, headers=headers)
if info['status'] not in status_codes:
- module.fail_json(url=url, **info)
+ info['url'] = url
+ module.fail_json(**info)
data = to_text(resp.read())
if data:
@@ -105,7 +106,7 @@ def delete_pulp_distribution(distribution, module):
def delete_pulp_orphans(module):
""" Deletes any orphaned pulp objects. """
- orphan_uri = module.params['pulp_api'] + '/pulp/api/v3/orphans/'
+ orphan_uri = module.params['galaxy_ng_server'] + 'pulp/api/v3/orphans/'
task_info = invoke_api(module, orphan_uri, method='DELETE', status_codes=[202])
wait_pulp_task(task_info['task'], module)
@@ -125,25 +126,39 @@ def get_galaxy_namespaces(module):
return [n['name'] for n in ns_info['data']]
-def get_pulp_distributions(module):
+def get_pulp_distributions(module, distribution):
""" Gets a list of all the pulp distributions. """
- distro_uri = module.params['pulp_api'] + '/pulp/api/v3/distributions/ansible/ansible/'
- distro_info = invoke_api(module, distro_uri)
+ distro_uri = module.params['galaxy_ng_server'] + 'pulp/api/v3/distributions/ansible/ansible/'
+ distro_info = invoke_api(module, distro_uri + '?name=' + distribution)
return [module.params['pulp_api'] + r['pulp_href'] for r in distro_info['results']]
-def get_pulp_repositories(module):
+def get_pulp_repositories(module, repository):
""" Gets a list of all the pulp repositories. """
- repo_uri = module.params['pulp_api'] + '/pulp/api/v3/repositories/ansible/ansible/'
- repo_info = invoke_api(module, repo_uri)
+ repo_uri = module.params['galaxy_ng_server'] + 'pulp/api/v3/repositories/ansible/ansible/'
+ repo_info = invoke_api(module, repo_uri + '?name=' + repository)
return [module.params['pulp_api'] + r['pulp_href'] for r in repo_info['results']]
+def get_repo_collections(repository, module):
+ collections_uri = module.params['galaxy_ng_server'] + 'v3/plugin/ansible/content/' + repository + '/collections/index/'
+ # status code 500 isn't really expected, an unhandled exception is causing this instead of a 404
+ # See https://issues.redhat.com/browse/AAH-2329
+ info = invoke_api(module, collections_uri + '?limit=100&offset=0', status_codes=[200, 500])
+ if not info:
+ return []
+ return [module.params['pulp_api'] + c['href'] for c in info['data']]
+
+
+def delete_repo_collection(collection, module):
+ task_info = invoke_api(module, collection, method='DELETE', status_codes=[202])
+ wait_pulp_task(task_info['task'], module)
+
+
def new_galaxy_namespace(name, module):
""" Creates a new namespace in Galaxy NG. """
- ns_uri = module.params['galaxy_ng_server'] + 'v3/_ui/namespaces/'
- data = {'name': name, 'groups': [{'name': 'system:partner-engineers', 'object_permissions':
- ['add_namespace', 'change_namespace', 'upload_to_namespace']}]}
+ ns_uri = module.params['galaxy_ng_server'] + 'v3/namespaces/ '
+ data = {'name': name, 'groups': []}
ns_info = invoke_api(module, ns_uri, method='POST', data=data, status_codes=[201])
return ns_info['id']
@@ -151,16 +166,17 @@ def new_galaxy_namespace(name, module):
def new_pulp_repository(name, module):
""" Creates a new pulp repository. """
- repo_uri = module.params['pulp_api'] + '/pulp/api/v3/repositories/ansible/ansible/'
- data = {'name': name}
+ repo_uri = module.params['galaxy_ng_server'] + 'pulp/api/v3/repositories/ansible/ansible/'
+ # retain_repo_versions to work around https://issues.redhat.com/browse/AAH-2332
+ data = {'name': name, 'retain_repo_versions': '1024'}
repo_info = invoke_api(module, repo_uri, method='POST', data=data, status_codes=[201])
- return module.params['pulp_api'] + repo_info['pulp_href']
+ return repo_info['pulp_href']
def new_pulp_distribution(name, base_path, repository, module):
""" Creates a new pulp distribution for a repository. """
- distro_uri = module.params['pulp_api'] + '/pulp/api/v3/distributions/ansible/ansible/'
+ distro_uri = module.params['galaxy_ng_server'] + 'pulp/api/v3/distributions/ansible/ansible/'
data = {'name': name, 'base_path': base_path, 'repository': repository}
task_info = invoke_api(module, distro_uri, method='POST', data=data, status_codes=[202])
task_info = wait_pulp_task(task_info['task'], module)
@@ -194,8 +210,15 @@ def main():
)
module.params['force_basic_auth'] = True
- [delete_pulp_distribution(d, module) for d in get_pulp_distributions(module)]
- [delete_pulp_repository(r, module) for r in get_pulp_repositories(module)]
+ # It may be due to the process of cleaning up orphans, but we cannot delete the namespace
+ # while a collection still exists, so this is just a new safety to nuke all collections
+ # first
+ for repository in module.params['repositories']:
+ [delete_repo_collection(c, module) for c in get_repo_collections(repository, module)]
+
+ for repository in module.params['repositories']:
+ [delete_pulp_distribution(d, module) for d in get_pulp_distributions(module, repository)]
+ [delete_pulp_repository(r, module) for r in get_pulp_repositories(module, repository)]
delete_pulp_orphans(module)
[delete_galaxy_namespace(n, module) for n in get_galaxy_namespaces(module)]
diff --git a/test/integration/targets/ansible-galaxy-collection/library/setup_collections.py b/test/integration/targets/ansible-galaxy-collection/library/setup_collections.py
index f4a51c4b..423edd9e 100644
--- a/test/integration/targets/ansible-galaxy-collection/library/setup_collections.py
+++ b/test/integration/targets/ansible-galaxy-collection/library/setup_collections.py
@@ -77,6 +77,7 @@ RETURN = '''
#
'''
+import datetime
import os
import subprocess
import tarfile
@@ -84,13 +85,13 @@ import tempfile
import yaml
from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils._text import to_bytes
+from ansible.module_utils.common.text.converters import to_bytes
from functools import partial
from multiprocessing import dummy as threading
from multiprocessing import TimeoutError
-COLLECTIONS_BUILD_AND_PUBLISH_TIMEOUT = 120
+COLLECTIONS_BUILD_AND_PUBLISH_TIMEOUT = 180
def publish_collection(module, collection):
@@ -104,6 +105,7 @@ def publish_collection(module, collection):
collection_dir = os.path.join(module.tmpdir, "%s-%s-%s" % (namespace, name, version))
b_collection_dir = to_bytes(collection_dir, errors='surrogate_or_strict')
os.mkdir(b_collection_dir)
+ os.mkdir(os.path.join(b_collection_dir, b'meta'))
with open(os.path.join(b_collection_dir, b'README.md'), mode='wb') as fd:
fd.write(b"Collection readme")
@@ -120,6 +122,8 @@ def publish_collection(module, collection):
}
with open(os.path.join(b_collection_dir, b'galaxy.yml'), mode='wb') as fd:
fd.write(to_bytes(yaml.safe_dump(galaxy_meta), errors='surrogate_or_strict'))
+ with open(os.path.join(b_collection_dir, b'meta/runtime.yml'), mode='wb') as fd:
+ fd.write(b'requires_ansible: ">=1.0.0"')
with tempfile.NamedTemporaryFile(mode='wb') as temp_fd:
temp_fd.write(b"data")
@@ -246,7 +250,8 @@ def run_module():
supports_check_mode=False
)
- result = dict(changed=True, results=[])
+ start = datetime.datetime.now()
+ result = dict(changed=True, results=[], start=str(start))
pool = threading.Pool(4)
publish_func = partial(publish_collection, module)
@@ -263,7 +268,9 @@ def run_module():
r['build']['rc'] + r['publish']['rc'] for r in result['results']
))
- module.exit_json(failed=failed, **result)
+ end = datetime.datetime.now()
+ delta = end - start
+ module.exit_json(failed=failed, end=str(end), delta=str(delta), **result)
def main():
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/build.yml b/test/integration/targets/ansible-galaxy-collection/tasks/build.yml
index 8140d468..83e9acc9 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/build.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/build.yml
@@ -1,4 +1,29 @@
---
+- name: create a dangling symbolic link inside collection directory
+ ansible.builtin.file:
+ src: '/non-existent-path/README.md'
+ dest: '{{ galaxy_dir }}/scratch/ansible_test/my_collection/docs/README.md'
+ state: link
+ force: yes
+
+- name: build basic collection based on current directory with dangling symlink
+ command: ansible-galaxy collection build {{ galaxy_verbosity }}
+ args:
+ chdir: '{{ galaxy_dir }}/scratch/ansible_test/my_collection'
+ register: fail_symlink_build
+ ignore_errors: yes
+
+- name: assert that build fails due to dangling symlink
+ assert:
+ that:
+ - fail_symlink_build.failed
+ - '"Failed to find the target path" in fail_symlink_build.stderr'
+
+- name: remove dangling symbolic link
+ ansible.builtin.file:
+ path: '{{ galaxy_dir }}/scratch/ansible_test/my_collection/docs/README.md'
+ state: absent
+
- name: build basic collection based on current directory
command: ansible-galaxy collection build {{ galaxy_verbosity }}
args:
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/download.yml b/test/integration/targets/ansible-galaxy-collection/tasks/download.yml
index b651a73e..a554c277 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/download.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/download.yml
@@ -5,7 +5,7 @@
state: directory
- name: download collection with multiple dependencies with --no-deps
- command: ansible-galaxy collection download parent_dep.parent_collection:1.0.0 --no-deps -s pulp_v2 {{ galaxy_verbosity }}
+ command: ansible-galaxy collection download parent_dep.parent_collection:1.0.0 --no-deps -s galaxy_ng {{ galaxy_verbosity }}
register: download_collection
args:
chdir: '{{ galaxy_dir }}/download'
@@ -34,7 +34,7 @@
- (download_collection_actual.files[1].path | basename) in ['requirements.yml', 'parent_dep-parent_collection-1.0.0.tar.gz']
- name: download collection with multiple dependencies
- command: ansible-galaxy collection download parent_dep.parent_collection:1.0.0 -s pulp_v2 {{ galaxy_verbosity }}
+ command: ansible-galaxy collection download parent_dep.parent_collection:1.0.0 -s galaxy_ng {{ galaxy_verbosity }}
register: download_collection
args:
chdir: '{{ galaxy_dir }}/download'
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/fail_fast_resolvelib.yml b/test/integration/targets/ansible-galaxy-collection/tasks/fail_fast_resolvelib.yml
index eb471f8e..d861cb4d 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/fail_fast_resolvelib.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/fail_fast_resolvelib.yml
@@ -1,5 +1,5 @@
# resolvelib>=0.6.0 added an 'incompatibilities' parameter to find_matches
-# If incompatibilities aren't removed from the viable candidates, this example causes infinite resursion
+# If incompatibilities aren't removed from the viable candidates, this example causes infinite recursion
- name: test resolvelib removes incompatibilites in find_matches and errors quickly (prevent infinite recursion)
block:
- name: create collection dir
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/init.yml b/test/integration/targets/ansible-galaxy-collection/tasks/init.yml
index 17a000db..46198fef 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/init.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/init.yml
@@ -5,6 +5,12 @@
chdir: '{{ galaxy_dir }}/scratch'
register: init_relative
+- name: create required runtime.yml
+ copy:
+ content: |
+ requires_ansible: '>=1.0.0'
+ dest: '{{ galaxy_dir }}/scratch/ansible_test/my_collection/meta/runtime.yml'
+
- name: get result of create default skeleton
find:
path: '{{ galaxy_dir }}/scratch/ansible_test/my_collection'
@@ -92,6 +98,65 @@
- (init_custom_path_actual.files | map(attribute='path') | list)[2] | basename in ['docs', 'plugins', 'roles', 'meta']
- (init_custom_path_actual.files | map(attribute='path') | list)[3] | basename in ['docs', 'plugins', 'roles', 'meta']
+- name: test using a custom skeleton for collection init
+ block:
+ - name: create skeleton directories
+ file:
+ path: "{{ galaxy_dir }}/scratch/skeleton/{{ item }}"
+ state: directory
+ loop:
+ - custom_skeleton
+ - custom_skeleton/plugins
+ - inventory
+
+ - name: create files
+ file:
+ path: "{{ galaxy_dir }}/scratch/skeleton/{{ item }}"
+ state: touch
+ loop:
+ - inventory/foo.py
+ - galaxy.yml
+
+ - name: create symlinks
+ file:
+ path: "{{ galaxy_dir }}/scratch/skeleton/{{ item.link }}"
+ src: "{{ galaxy_dir }}/scratch/skeleton/{{ item.source }}"
+ state: link
+ loop:
+ - link: custom_skeleton/plugins/inventory
+ source: inventory
+ - link: custom_skeleton/galaxy.yml
+ source: galaxy.yml
+
+ - name: initialize a collection using the skeleton
+ command: ansible-galaxy collection init ansible_test.my_collection {{ init_path }} {{ skeleton }}
+ vars:
+ init_path: '--init-path {{ galaxy_dir }}/scratch/skeleton'
+ skeleton: '--collection-skeleton {{ galaxy_dir }}/scratch/skeleton/custom_skeleton'
+
+ - name: stat expected collection contents
+ stat:
+ path: "{{ galaxy_dir }}/scratch/skeleton/ansible_test/my_collection/{{ item }}"
+ register: stat_result
+ loop:
+ - plugins
+ - plugins/inventory
+ - galaxy.yml
+ - plugins/inventory/foo.py
+
+ - assert:
+ that:
+ - stat_result.results[0].stat.isdir
+ - stat_result.results[1].stat.islnk
+ - stat_result.results[2].stat.islnk
+ - stat_result.results[3].stat.isreg
+
+ always:
+ - name: cleanup
+ file:
+ path: "{{ galaxy_dir }}/scratch/skeleton"
+ state: absent
+
- name: create collection for ignored files and folders
command: ansible-galaxy collection init ansible_test.ignore
args:
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/install.yml b/test/integration/targets/ansible-galaxy-collection/tasks/install.yml
index cca83c7b..92378266 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/install.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/install.yml
@@ -165,10 +165,13 @@
failed_when:
- '"Could not satisfy the following requirements" not in fail_dep_mismatch.stderr'
- '" fail_dep2.name:<0.0.5 (dependency of fail_namespace.fail_collection:2.1.2)" not in fail_dep_mismatch.stderr'
+ - 'pre_release_hint not in fail_dep_mismatch.stderr'
+ vars:
+ pre_release_hint: 'Hint: Pre-releases are not installed by default unless the specific version is given. To enable pre-releases, use --pre.'
- name: Find artifact url for namespace3.name
uri:
- url: '{{ test_server }}{{ vX }}collections/namespace3/name/versions/1.0.0/'
+ url: '{{ test_api_server }}v3/plugin/ansible/content/primary/collections/index/namespace3/name/versions/1.0.0/'
user: '{{ pulp_user }}'
password: '{{ pulp_password }}'
force_basic_auth: true
@@ -218,7 +221,7 @@
state: absent
- assert:
- that: error == expected_error
+ that: expected_error in error
vars:
error: "{{ result.stderr | regex_replace('\\n', ' ') }}"
expected_error: >-
@@ -258,12 +261,14 @@
ignore_errors: yes
register: result
- - debug: msg="Actual - {{ error }}"
+ - debug:
+ msg: "Actual - {{ error }}"
- - debug: msg="Expected - {{ expected_error }}"
+ - debug:
+ msg: "Expected - {{ expected_error }}"
- assert:
- that: error == expected_error
+ that: expected_error in error
always:
- name: clean up collection skeleton and artifact
file:
@@ -295,7 +300,7 @@
- name: Find artifact url for namespace4.name
uri:
- url: '{{ test_server }}{{ vX }}collections/namespace4/name/versions/1.0.0/'
+ url: '{{ test_api_server }}v3/plugin/ansible/content/primary/collections/index/namespace4/name/versions/1.0.0/'
user: '{{ pulp_user }}'
password: '{{ pulp_password }}'
force_basic_auth: true
@@ -325,10 +330,11 @@
environment:
ANSIBLE_GALAXY_SERVER_LIST: undefined
-- when: not requires_auth
+# pulp_v2 doesn't require auth
+- when: v2|default(false)
block:
- name: install a collection with an empty server list - {{ test_id }}
- command: ansible-galaxy collection install namespace5.name -s '{{ test_server }}' {{ galaxy_verbosity }}
+ command: ansible-galaxy collection install namespace5.name -s '{{ test_server }}' --api-version 2 {{ galaxy_verbosity }}
register: install_empty_server_list
environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
@@ -571,7 +577,6 @@
- namespace8
- namespace9
-# SIVEL
- name: assert invalid signature is not fatal with ansible-galaxy install --ignore-errors - {{ test_id }}
assert:
that:
@@ -646,6 +651,7 @@
- namespace8
- namespace9
+# test --ignore-signature-status-code extends ANSIBLE_GALAXY_IGNORE_SIGNATURE_STATUS_CODES env var
- name: install collections with only one valid signature by ignoring the other errors
command: ansible-galaxy install -r {{ req_file }} {{ cli_opts }} {{ galaxy_verbosity }} --ignore-signature-status-code FAILURE
register: install_req
@@ -686,6 +692,60 @@
vars:
install_stderr: "{{ install_req.stderr | regex_replace('\\n', ' ') }}"
+# test --ignore-signature-status-code passed multiple times
+- name: reinstall collections with only one valid signature by ignoring the other errors
+ command: ansible-galaxy install -r {{ req_file }} {{ cli_opts }} {{ galaxy_verbosity }} {{ ignore_errors }}
+ register: install_req
+ vars:
+ req_file: "{{ galaxy_dir }}/ansible_collections/requirements.yaml"
+ cli_opts: "-s {{ test_name }} --keyring {{ keyring }} --force"
+ keyring: "{{ gpg_homedir }}/pubring.kbx"
+ ignore_errors: "--ignore-signature-status-code BADSIG --ignore-signature-status-code FAILURE"
+ environment:
+ ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
+ ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: all
+ ANSIBLE_NOCOLOR: True
+ ANSIBLE_FORCE_COLOR: False
+
+- name: assert invalid signature is not fatal with ansible-galaxy install - {{ test_name }}
+ assert:
+ that:
+ - install_req is success
+ - '"Installing ''namespace7.name:1.0.0'' to" in install_req.stdout'
+ - '"Signature verification failed for ''namespace7.name'' (return code 1)" not in install_req.stdout'
+ - '"Not installing namespace7.name because GnuPG signature verification failed." not in install_stderr'
+ - '"Installing ''namespace8.name:1.0.0'' to" in install_req.stdout'
+ - '"Installing ''namespace9.name:1.0.0'' to" in install_req.stdout'
+ vars:
+ install_stderr: "{{ install_req.stderr | regex_replace('\\n', ' ') }}"
+
+# test --ignore-signature-status-code passed once with a list
+- name: reinstall collections with only one valid signature by ignoring the other errors
+ command: ansible-galaxy install -r {{ req_file }} {{ cli_opts }} {{ galaxy_verbosity }} {{ ignore_errors }}
+ register: install_req
+ vars:
+ req_file: "{{ galaxy_dir }}/ansible_collections/requirements.yaml"
+ cli_opts: "-s {{ test_name }} --keyring {{ keyring }} --force"
+ keyring: "{{ gpg_homedir }}/pubring.kbx"
+ ignore_errors: "--ignore-signature-status-codes BADSIG FAILURE"
+ environment:
+ ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
+ ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: all
+ ANSIBLE_NOCOLOR: True
+ ANSIBLE_FORCE_COLOR: False
+
+- name: assert invalid signature is not fatal with ansible-galaxy install - {{ test_name }}
+ assert:
+ that:
+ - install_req is success
+ - '"Installing ''namespace7.name:1.0.0'' to" in install_req.stdout'
+ - '"Signature verification failed for ''namespace7.name'' (return code 1)" not in install_req.stdout'
+ - '"Not installing namespace7.name because GnuPG signature verification failed." not in install_stderr'
+ - '"Installing ''namespace8.name:1.0.0'' to" in install_req.stdout'
+ - '"Installing ''namespace9.name:1.0.0'' to" in install_req.stdout'
+ vars:
+ install_stderr: "{{ install_req.stderr | regex_replace('\\n', ' ') }}"
+
- name: clean up collections from last test
file:
path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name'
@@ -697,44 +757,45 @@
- namespace8
- namespace9
-# Uncomment once pulp container is at pulp>=0.5.0
-#- name: install cache.cache at the current latest version
-# command: ansible-galaxy collection install cache.cache -s '{{ test_name }}' -vvv
-# environment:
-# ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
-#
-#- set_fact:
-# cache_version_build: '{{ (cache_version_build | int) + 1 }}'
-#
-#- name: publish update for cache.cache test
-# setup_collections:
-# server: galaxy_ng
-# collections:
-# - namespace: cache
-# name: cache
-# version: 1.0.{{ cache_version_build }}
-#
-#- name: make sure the cache version list is ignored on a collection version change - {{ test_id }}
-# command: ansible-galaxy collection install cache.cache -s '{{ test_name }}' --force -vvv
-# register: install_cached_update
-# environment:
-# ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
-#
-#- name: get result of cache version list is ignored on a collection version change - {{ test_id }}
-# slurp:
-# path: '{{ galaxy_dir }}/ansible_collections/cache/cache/MANIFEST.json'
-# register: install_cached_update_actual
-#
-#- name: assert cache version list is ignored on a collection version change - {{ test_id }}
-# assert:
-# that:
-# - '"Installing ''cache.cache:1.0.{{ cache_version_build }}'' to" in install_cached_update.stdout'
-# - (install_cached_update_actual.content | b64decode | from_json).collection_info.version == '1.0.' ~ cache_version_build
+- when: not v2|default(false)
+ block:
+ - name: install cache.cache at the current latest version
+ command: ansible-galaxy collection install cache.cache -s '{{ test_name }}' -vvv
+ environment:
+ ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
+
+ - set_fact:
+ cache_version_build: '{{ (cache_version_build | int) + 1 }}'
+
+ - name: publish update for cache.cache test
+ setup_collections:
+ server: galaxy_ng
+ collections:
+ - namespace: cache
+ name: cache
+ version: 1.0.{{ cache_version_build }}
+
+ - name: make sure the cache version list is ignored on a collection version change - {{ test_id }}
+ command: ansible-galaxy collection install cache.cache -s '{{ test_name }}' --force -vvv
+ register: install_cached_update
+ environment:
+ ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
+
+ - name: get result of cache version list is ignored on a collection version change - {{ test_id }}
+ slurp:
+ path: '{{ galaxy_dir }}/ansible_collections/cache/cache/MANIFEST.json'
+ register: install_cached_update_actual
+
+ - name: assert cache version list is ignored on a collection version change - {{ test_id }}
+ assert:
+ that:
+ - '"Installing ''cache.cache:1.0.{{ cache_version_build }}'' to" in install_cached_update.stdout'
+ - (install_cached_update_actual.content | b64decode | from_json).collection_info.version == '1.0.' ~ cache_version_build
- name: install collection with symlink - {{ test_id }}
command: ansible-galaxy collection install symlink.symlink -s '{{ test_name }}' {{ galaxy_verbosity }}
environment:
- ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections'
+ ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
register: install_symlink
- find:
@@ -772,6 +833,56 @@
- install_symlink_actual.results[5].stat.islnk
- install_symlink_actual.results[5].stat.lnk_target == '../REÅDMÈ.md'
+
+# Testing an install from source to check that symlinks to directories
+# are preserved (see issue https://github.com/ansible/ansible/issues/78442)
+- name: symlink_dirs collection install from source test
+ block:
+
+ - name: create symlink_dirs collection
+ command: ansible-galaxy collection init symlink_dirs.symlink_dirs --init-path "{{ galaxy_dir }}/scratch"
+
+ - name: create directory in collection
+ file:
+ path: "{{ galaxy_dir }}/scratch/symlink_dirs/symlink_dirs/folderA"
+ state: directory
+
+ - name: create symlink to folderA
+ file:
+ dest: "{{ galaxy_dir }}/scratch/symlink_dirs/symlink_dirs/folderB"
+ src: ./folderA
+ state: link
+ force: yes
+
+ - name: install symlink_dirs collection from source
+ command: ansible-galaxy collection install {{ galaxy_dir }}/scratch/symlink_dirs/symlink_dirs/
+ environment:
+ ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
+ register: install_symlink_dirs
+
+ - name: get result of install collection with symlink_dirs - {{ test_id }}
+ stat:
+ path: '{{ galaxy_dir }}/ansible_collections/symlink_dirs/symlink_dirs/{{ path }}'
+ register: install_symlink_dirs_actual
+ loop_control:
+ loop_var: path
+ loop:
+ - folderA
+ - folderB
+
+ - name: assert install collection with symlink_dirs - {{ test_id }}
+ assert:
+ that:
+ - '"Installing ''symlink_dirs.symlink_dirs:1.0.0'' to" in install_symlink_dirs.stdout'
+ - install_symlink_dirs_actual.results[0].stat.isdir
+ - install_symlink_dirs_actual.results[1].stat.islnk
+ - install_symlink_dirs_actual.results[1].stat.lnk_target == './folderA'
+ always:
+ - name: clean up symlink_dirs collection directory
+ file:
+ path: "{{ galaxy_dir }}/scratch/symlink_dirs"
+ state: absent
+
- name: remove install directory for the next test because parent_dep.parent_collection was installed - {{ test_id }}
file:
path: '{{ galaxy_dir }}/ansible_collections'
@@ -780,7 +891,7 @@
- name: install collection and dep compatible with multiple requirements - {{ test_id }}
command: ansible-galaxy collection install parent_dep.parent_collection parent_dep2.parent_collection
environment:
- ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections'
+ ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
register: install_req
- name: assert install collections with ansible-galaxy install - {{ test_id }}
@@ -802,7 +913,7 @@
- name: install a collection to the same installation directory - {{ test_id }}
command: ansible-galaxy collection install namespace1.name1
environment:
- ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections'
+ ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
register: install_req
- name: assert installed collections with ansible-galaxy install - {{ test_id }}
@@ -1009,7 +1120,7 @@
args:
chdir: '{{ galaxy_dir }}/scratch'
environment:
- ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections'
+ ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
register: install_concrete_pre
- name: get result of install collections with concrete pre-release dep - {{ test_id }}
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/install_offline.yml b/test/integration/targets/ansible-galaxy-collection/tasks/install_offline.yml
index 74c99838..f3b9777c 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/install_offline.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/install_offline.yml
@@ -25,6 +25,14 @@
regexp: "^dependencies:*"
line: "dependencies: {'ns.coll2': '>=1.0.0'}"
+ - name: create required runtime.yml
+ copy:
+ dest: "{{ galaxy_dir }}/offline/setup/ns/{{ item }}/meta/runtime.yml"
+ content: "requires_ansible: '>=1.0.0'"
+ loop:
+ - coll1
+ - coll2
+
- name: build both collections
command: ansible-galaxy collection build {{ init_dir }}/ns/{{ item }}
args:
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/list.yml b/test/integration/targets/ansible-galaxy-collection/tasks/list.yml
index b8d63492..1c93d54b 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/list.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/list.yml
@@ -1,4 +1,4 @@
-- name: initialize collection structure
+- name: initialize dev collection structure
command: ansible-galaxy collection init {{ item }} --init-path "{{ galaxy_dir }}/dev/ansible_collections" {{ galaxy_verbosity }}
loop:
- 'dev.collection1'
@@ -8,6 +8,13 @@
- 'dev.collection5'
- 'dev.collection6'
+- name: initialize prod collection structure
+ command: ansible-galaxy collection init {{ item }} --init-path "{{ galaxy_dir }}/prod/ansible_collections" {{ galaxy_verbosity }}
+ loop:
+ - 'prod.collection1'
+ - 'prod.collection2'
+ - 'prod.collection3'
+
- name: replace the default version of the collections
lineinfile:
path: "{{ galaxy_dir }}/dev/ansible_collections/dev/{{ item.name }}/galaxy.yml"
@@ -53,13 +60,13 @@
- assert:
that:
- - "'dev.collection1 *' in list_result.stdout"
+ - "'dev.collection1 *' in list_result.stdout"
# Note the version displayed is the 'placeholder' string rather than "*" since it is not falsey
- - "'dev.collection2 placeholder' in list_result.stdout"
- - "'dev.collection3 *' in list_result.stdout"
- - "'dev.collection4 *' in list_result.stdout"
- - "'dev.collection5 *' in list_result.stdout"
- - "'dev.collection6 *' in list_result.stdout"
+ - "'dev.collection2 placeholder' in list_result.stdout"
+ - "'dev.collection3 *' in list_result.stdout"
+ - "'dev.collection4 *' in list_result.stdout"
+ - "'dev.collection5 *' in list_result.stdout"
+ - "'dev.collection6 *' in list_result.stdout"
- name: list collections in human format
command: ansible-galaxy collection list --format human
@@ -69,12 +76,12 @@
- assert:
that:
- - "'dev.collection1 *' in list_result_human.stdout"
+ - "'dev.collection1 *' in list_result_human.stdout"
# Note the version displayed is the 'placeholder' string rather than "*" since it is not falsey
- - "'dev.collection2 placeholder' in list_result_human.stdout"
- - "'dev.collection3 *' in list_result_human.stdout"
- - "'dev.collection5 *' in list_result.stdout"
- - "'dev.collection6 *' in list_result.stdout"
+ - "'dev.collection2 placeholder' in list_result_human.stdout"
+ - "'dev.collection3 *' in list_result_human.stdout"
+ - "'dev.collection5 *' in list_result.stdout"
+ - "'dev.collection6 *' in list_result.stdout"
- name: list collections in yaml format
command: ansible-galaxy collection list --format yaml
@@ -84,6 +91,12 @@
- assert:
that:
+ - yaml_result[galaxy_dir ~ '/dev/ansible_collections'] != yaml_result[galaxy_dir ~ '/prod/ansible_collections']
+ vars:
+ yaml_result: '{{ list_result_yaml.stdout | from_yaml }}'
+
+- assert:
+ that:
- "item.value | length == 6"
- "item.value['dev.collection1'].version == '*'"
- "item.value['dev.collection2'].version == 'placeholder'"
@@ -91,6 +104,7 @@
- "item.value['dev.collection5'].version == '*'"
- "item.value['dev.collection6'].version == '*'"
with_dict: "{{ list_result_yaml.stdout | from_yaml }}"
+ when: "'dev' in item.key"
- name: list collections in json format
command: ansible-galaxy collection list --format json
@@ -107,6 +121,7 @@
- "item.value['dev.collection5'].version == '*'"
- "item.value['dev.collection6'].version == '*'"
with_dict: "{{ list_result_json.stdout | from_json }}"
+ when: "'dev' in item.key"
- name: list single collection in json format
command: "ansible-galaxy collection list {{ item.key }} --format json"
@@ -137,7 +152,7 @@
register: list_result_error
ignore_errors: True
environment:
- ANSIBLE_COLLECTIONS_PATH: ""
+ ANSIBLE_COLLECTIONS_PATH: "i_dont_exist"
- assert:
that:
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/main.yml b/test/integration/targets/ansible-galaxy-collection/tasks/main.yml
index 724c861e..e17d6aa1 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/main.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/main.yml
@@ -72,13 +72,12 @@
vars:
test_name: '{{ item.name }}'
test_server: '{{ item.server }}'
- vX: '{{ "v3/" if item.v3|default(false) else "v2/" }}'
+ test_api_server: '{{ item.api_server|default(item.server) }}'
loop:
- name: pulp_v2
- server: '{{ pulp_server }}published/api/'
- - name: pulp_v3
- server: '{{ pulp_server }}published/api/'
- v3: true
+ api_server: '{{ galaxy_ng_server }}'
+ server: '{{ pulp_server }}primary/api/'
+ v2: true
- name: galaxy_ng
server: '{{ galaxy_ng_server }}'
v3: true
@@ -108,8 +107,9 @@
test_id: '{{ item.name }}'
test_name: '{{ item.name }}'
test_server: '{{ item.server }}'
- vX: '{{ "v3/" if item.v3|default(false) else "v2/" }}'
+ test_api_server: '{{ item.api_server|default(item.server) }}'
requires_auth: '{{ item.requires_auth|default(false) }}'
+ v2: '{{ item.v2|default(false) }}'
args:
apply:
environment:
@@ -120,10 +120,9 @@
v3: true
requires_auth: true
- name: pulp_v2
- server: '{{ pulp_server }}published/api/'
- - name: pulp_v3
- server: '{{ pulp_server }}published/api/'
- v3: true
+ server: '{{ pulp_server }}primary/api/'
+ api_server: '{{ galaxy_ng_server }}'
+ v2: true
- name: test installing and downloading collections with the range of supported resolvelib versions
include_tasks: supported_resolvelib.yml
@@ -135,6 +134,17 @@
loop_control:
loop_var: resolvelib_version
+- name: test choosing pinned pre-releases anywhere in the dependency tree
+ # This is a regression test for the case when the end-user does not
+ # explicitly allow installing pre-release collection versions, but their
+ # precise pins are still selected if met among the dependencies, either
+ # direct or transitive.
+ include_tasks: pinned_pre_releases_in_deptree.yml
+
+- name: test installing prereleases via scm direct requests
+ # In this test suite because the bug relies on the dep having versions on a Galaxy server
+ include_tasks: virtual_direct_requests.yml
+
- name: publish collection with a dep on another server
setup_collections:
server: secondary
@@ -176,13 +186,13 @@
in install_cross_dep.stdout
# pulp_v2 is highest in the list so it will find it there first
- >-
- "'parent_dep.parent_collection:1.0.0' obtained from server pulp_v2"
+ "'parent_dep.parent_collection:1.0.0' obtained from server galaxy_ng"
in install_cross_dep.stdout
- >-
- "'child_dep.child_collection:0.9.9' obtained from server pulp_v2"
+ "'child_dep.child_collection:0.9.9' obtained from server galaxy_ng"
in install_cross_dep.stdout
- >-
- "'child_dep.child_dep2:1.2.2' obtained from server pulp_v2"
+ "'child_dep.child_dep2:1.2.2' obtained from server galaxy_ng"
in install_cross_dep.stdout
- (install_cross_dep_actual.results[0].content | b64decode | from_json).collection_info.version == '1.0.0'
- (install_cross_dep_actual.results[1].content | b64decode | from_json).collection_info.version == '1.0.0'
@@ -204,10 +214,9 @@
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}'
ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg'
vars:
- test_api_fallback: 'pulp_v2'
- test_api_fallback_versions: 'v1, v2'
- test_name: 'galaxy_ng'
- test_server: '{{ galaxy_ng_server }}'
+ test_api_fallback: 'galaxy_ng'
+ test_api_fallback_versions: 'v3, pulp-v3, v1'
+ test_name: 'pulp_v2'
- name: run ansible-galaxy collection list tests
include_tasks: list.yml
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/publish.yml b/test/integration/targets/ansible-galaxy-collection/tasks/publish.yml
index 241eae60..1be16ae9 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/publish.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/publish.yml
@@ -5,9 +5,12 @@
chdir: '{{ galaxy_dir }}'
register: publish_collection
+- name: ensure we can download the published collection - {{ test_name }}
+ command: ansible-galaxy collection install -s {{ test_name }} -p "{{ remote_tmp_dir }}/publish/{{ test_name }}" ansible_test.my_collection==1.0.0 {{ galaxy_verbosity }}
+
- name: get result of publish collection - {{ test_name }}
uri:
- url: '{{ test_server }}{{ vX }}collections/ansible_test/my_collection/versions/1.0.0/'
+ url: '{{ test_api_server }}v3/plugin/ansible/content/primary/collections/index/ansible_test/my_collection/versions/1.0.0/'
return_content: yes
user: '{{ pulp_user }}'
password: '{{ pulp_password }}'
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/supported_resolvelib.yml b/test/integration/targets/ansible-galaxy-collection/tasks/supported_resolvelib.yml
index 763c5a19..bff36892 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/supported_resolvelib.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/supported_resolvelib.yml
@@ -20,11 +20,11 @@
- include_tasks: install.yml
vars:
- test_name: pulp_v3
+ test_name: galaxy_ng
test_id: '{{ test_name }} (resolvelib {{ resolvelib_version }})'
- test_server: '{{ pulp_server }}published/api/'
- vX: "v3/"
- requires_auth: false
+ test_server: '{{ galaxy_ng_server }}'
+ test_api_server: '{{ galaxy_ng_server }}'
+ requires_auth: true
args:
apply:
environment:
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/upgrade.yml b/test/integration/targets/ansible-galaxy-collection/tasks/upgrade.yml
index 893ea803..debd70bc 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/upgrade.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/upgrade.yml
@@ -142,7 +142,7 @@
- directory
- name: install a collection
- command: ansible-galaxy collection install namespace1.name1:0.0.1 {{ galaxy_verbosity }}
+ command: ansible-galaxy collection install namespace1.name1==0.0.1 {{ galaxy_verbosity }}
register: result
failed_when:
- '"namespace1.name1:0.0.1 was installed successfully" not in result.stdout_lines'
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/verify.yml b/test/integration/targets/ansible-galaxy-collection/tasks/verify.yml
index dfe3d0f7..0fe2f82d 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/verify.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/verify.yml
@@ -3,6 +3,11 @@
args:
chdir: '{{ galaxy_dir }}/scratch'
+- name: created required runtime.yml
+ copy:
+ content: 'requires_ansible: ">=1.0.0"'
+ dest: '{{ galaxy_dir }}/scratch/ansible_test/verify/meta/runtime.yml'
+
- name: build the collection
command: ansible-galaxy collection build scratch/ansible_test/verify
args:
@@ -31,6 +36,9 @@
- name: verify the collection against the first valid server
command: ansible-galaxy collection verify ansible_test.verify:1.0.0 -vvvv {{ galaxy_verbosity }}
register: verify
+ vars:
+ # This sets a specific precedence that the tests are expecting
+ ANSIBLE_GALAXY_SERVER_LIST: offline,secondary,pulp_v2,galaxy_ng
- assert:
that:
diff --git a/test/integration/targets/ansible-galaxy-collection/templates/ansible.cfg.j2 b/test/integration/targets/ansible-galaxy-collection/templates/ansible.cfg.j2
index 9bff527b..a242979d 100644
--- a/test/integration/targets/ansible-galaxy-collection/templates/ansible.cfg.j2
+++ b/test/integration/targets/ansible-galaxy-collection/templates/ansible.cfg.j2
@@ -1,28 +1,22 @@
[galaxy]
# Ensures subsequent unstable reruns don't use the cached information causing another failure
cache_dir={{ remote_tmp_dir }}/galaxy_cache
-server_list=offline,pulp_v2,pulp_v3,galaxy_ng,secondary
+server_list=offline,galaxy_ng,secondary,pulp_v2
[galaxy_server.offline]
url={{ offline_server }}
[galaxy_server.pulp_v2]
-url={{ pulp_server }}published/api/
-username={{ pulp_user }}
-password={{ pulp_password }}
-
-[galaxy_server.pulp_v3]
-url={{ pulp_server }}published/api/
-v3=true
+url={{ pulp_server }}primary/api/
username={{ pulp_user }}
password={{ pulp_password }}
+api_version=2
[galaxy_server.galaxy_ng]
-url={{ galaxy_ng_server }}
+url={{ galaxy_ng_server }}content/primary/
token={{ galaxy_ng_token.json.token }}
[galaxy_server.secondary]
-url={{ pulp_server }}secondary/api/
-v3=true
+url={{ galaxy_ng_server }}content/secondary/
username={{ pulp_user }}
password={{ pulp_password }}
diff --git a/test/integration/targets/ansible-galaxy-collection/vars/main.yml b/test/integration/targets/ansible-galaxy-collection/vars/main.yml
index 175d6696..066d2678 100644
--- a/test/integration/targets/ansible-galaxy-collection/vars/main.yml
+++ b/test/integration/targets/ansible-galaxy-collection/vars/main.yml
@@ -9,17 +9,20 @@ supported_resolvelib_versions:
- "0.6.0"
- "0.7.0"
- "0.8.0"
+ - "0.9.0"
+ - "1.0.1"
unsupported_resolvelib_versions:
- "0.2.0" # Fails on import
- "0.5.1"
pulp_repositories:
- - published
+ - primary
- secondary
publish_namespaces:
- ansible_test
+ - secondary
collection_list:
# Scenario to test out pre-release being ignored unless explicitly set and version pagination.
@@ -162,3 +165,41 @@ collection_list:
name: parent
dependencies:
namespace1.name1: '*'
+
+ # non-prerelease is published to test that installing
+ # the pre-release from SCM doesn't accidentally prefer indirect
+ # dependencies from Galaxy
+ - namespace: test_prereleases
+ name: collection2
+ version: 1.0.0
+
+ - namespace: dev_and_stables_ns
+ name: dev_and_stables_name
+ version: 1.2.3-dev0
+ - namespace: dev_and_stables_ns
+ name: dev_and_stables_name
+ version: 1.2.4
+
+ - namespace: ns_with_wildcard_dep
+ name: name_with_wildcard_dep
+ version: 5.6.7-beta.3
+ dependencies:
+ dev_and_stables_ns.dev_and_stables_name: >-
+ *
+ - namespace: ns_with_dev_dep
+ name: name_with_dev_dep
+ version: 6.7.8
+ dependencies:
+ dev_and_stables_ns.dev_and_stables_name: 1.2.3-dev0
+
+ - namespace: rc_meta_ns_with_transitive_dev_dep
+ name: rc_meta_name_with_transitive_dev_dep
+ version: 2.4.5-rc5
+ dependencies:
+ ns_with_dev_dep.name_with_dev_dep: >-
+ *
+ - namespace: meta_ns_with_transitive_wildcard_dep
+ name: meta_name_with_transitive_wildcard_dep
+ version: 4.5.6
+ dependencies:
+ ns_with_wildcard_dep.name_with_wildcard_dep: 5.6.7-beta.3
diff --git a/test/integration/targets/ansible-galaxy-role/files/create-role-archive.py b/test/integration/targets/ansible-galaxy-role/files/create-role-archive.py
index cfd908c1..48766638 100755
--- a/test/integration/targets/ansible-galaxy-role/files/create-role-archive.py
+++ b/test/integration/targets/ansible-galaxy-role/files/create-role-archive.py
@@ -2,6 +2,7 @@
"""Create a role archive which overwrites an arbitrary file."""
import argparse
+import os
import pathlib
import tarfile
import tempfile
@@ -18,6 +19,15 @@ def main() -> None:
create_archive(args.archive, args.content, args.target)
+def generate_files_from_path(path):
+ if os.path.isdir(path):
+ for subpath in os.listdir(path):
+ _path = os.path.join(path, subpath)
+ yield from generate_files_from_path(_path)
+ elif os.path.isfile(path):
+ yield pathlib.Path(path)
+
+
def create_archive(archive_path: pathlib.Path, content_path: pathlib.Path, target_path: pathlib.Path) -> None:
with (
tarfile.open(name=archive_path, mode='w') as role_archive,
@@ -35,10 +45,15 @@ def create_archive(archive_path: pathlib.Path, content_path: pathlib.Path, targe
role_archive.add(meta_main_path)
role_archive.add(symlink_path)
- content_tarinfo = role_archive.gettarinfo(content_path, str(symlink_path))
+ for path in generate_files_from_path(content_path):
+ if path == content_path:
+ arcname = str(symlink_path)
+ else:
+ arcname = os.path.join(temp_dir_path, path)
- with content_path.open('rb') as content_file:
- role_archive.addfile(content_tarinfo, content_file)
+ content_tarinfo = role_archive.gettarinfo(path, arcname)
+ with path.open('rb') as file_content:
+ role_archive.addfile(content_tarinfo, file_content)
if __name__ == '__main__':
diff --git a/test/integration/targets/ansible-galaxy-role/tasks/dir-traversal.yml b/test/integration/targets/ansible-galaxy-role/tasks/dir-traversal.yml
index c70e8998..1c17daf7 100644
--- a/test/integration/targets/ansible-galaxy-role/tasks/dir-traversal.yml
+++ b/test/integration/targets/ansible-galaxy-role/tasks/dir-traversal.yml
@@ -23,6 +23,9 @@
command:
cmd: ansible-galaxy role install --roles-path '{{ remote_tmp_dir }}/dir-traversal/roles' dangerous.tar
chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
+ environment:
+ ANSIBLE_NOCOLOR: True
+ ANSIBLE_FORCE_COLOR: False
ignore_errors: true
register: galaxy_install_dangerous
@@ -42,3 +45,86 @@
- dangerous_overwrite_content.content|default('')|b64decode == ''
- not dangerous_overwrite_stat.stat.exists
- galaxy_install_dangerous is failed
+ - "'is not a subpath of the role' in (galaxy_install_dangerous.stderr | regex_replace('\n', ' '))"
+
+- name: remove tarfile for next test
+ file:
+ path: '{{ item }}'
+ state: absent
+ loop:
+ - '{{ remote_tmp_dir }}/dir-traversal/source/dangerous.tar'
+ - '{{ remote_tmp_dir }}/dir-traversal/roles/dangerous.tar'
+
+- name: build dangerous dir traversal role that includes .. in the symlink path
+ script:
+ chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
+ cmd: create-role-archive.py dangerous.tar content.txt {{ remote_tmp_dir }}/dir-traversal/source/../target/target-file-to-overwrite.txt
+ executable: '{{ ansible_playbook_python }}'
+
+- name: install dangerous role
+ command:
+ cmd: 'ansible-galaxy role install --roles-path {{ remote_tmp_dir }}/dir-traversal/roles dangerous.tar'
+ chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
+ environment:
+ ANSIBLE_NOCOLOR: True
+ ANSIBLE_FORCE_COLOR: False
+ ignore_errors: true
+ register: galaxy_install_dangerous
+
+- name: check for overwritten file
+ stat:
+ path: '{{ remote_tmp_dir }}/dir-traversal/target/target-file-to-overwrite.txt'
+ register: dangerous_overwrite_stat
+
+- name: get overwritten content
+ slurp:
+ path: '{{ remote_tmp_dir }}/dir-traversal/target/target-file-to-overwrite.txt'
+ register: dangerous_overwrite_content
+ when: dangerous_overwrite_stat.stat.exists
+
+- assert:
+ that:
+ - dangerous_overwrite_content.content|default('')|b64decode == ''
+ - not dangerous_overwrite_stat.stat.exists
+ - galaxy_install_dangerous is failed
+ - "'is not a subpath of the role' in (galaxy_install_dangerous.stderr | regex_replace('\n', ' '))"
+
+- name: remove tarfile for next test
+ file:
+ path: '{{ remote_tmp_dir }}/dir-traversal/source/dangerous.tar'
+ state: absent
+
+- name: build dangerous dir traversal role that includes .. in the relative symlink path
+ script:
+ chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
+ cmd: create-role-archive.py dangerous_rel.tar content.txt ../context.txt
+
+- name: install dangerous role with relative symlink
+ command:
+ cmd: 'ansible-galaxy role install --roles-path {{ remote_tmp_dir }}/dir-traversal/roles dangerous_rel.tar'
+ chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
+ environment:
+ ANSIBLE_NOCOLOR: True
+ ANSIBLE_FORCE_COLOR: False
+ ignore_errors: true
+ register: galaxy_install_dangerous
+
+- name: check for symlink outside role
+ stat:
+ path: "{{ remote_tmp_dir | realpath }}/dir-traversal/roles/symlink"
+ register: symlink_outside_role
+
+- assert:
+ that:
+ - not symlink_outside_role.stat.exists
+ - galaxy_install_dangerous is failed
+ - "'is not a subpath of the role' in (galaxy_install_dangerous.stderr | regex_replace('\n', ' '))"
+
+- name: remove test directories
+ file:
+ path: '{{ remote_tmp_dir }}/dir-traversal/{{ item }}'
+ state: absent
+ loop:
+ - source
+ - target
+ - roles
diff --git a/test/integration/targets/ansible-galaxy-role/tasks/main.yml b/test/integration/targets/ansible-galaxy-role/tasks/main.yml
index b39df11c..5f88a557 100644
--- a/test/integration/targets/ansible-galaxy-role/tasks/main.yml
+++ b/test/integration/targets/ansible-galaxy-role/tasks/main.yml
@@ -25,10 +25,18 @@
- name: Valid role archive
command: "tar cf {{ remote_tmp_dir }}/valid-role.tar {{ remote_tmp_dir }}/role.d"
-- name: Invalid file
- copy:
- content: ""
+- name: Add invalid symlink
+ file:
+ state: link
+ src: "~/invalid"
dest: "{{ remote_tmp_dir }}/role.d/tasks/~invalid.yml"
+ force: yes
+
+- name: Add another invalid symlink
+ file:
+ state: link
+ src: "/"
+ dest: "{{ remote_tmp_dir }}/role.d/tasks/invalid$name.yml"
- name: Valid requirements file
copy:
@@ -61,3 +69,4 @@
command: ansible-galaxy role remove invalid-testrole
- import_tasks: dir-traversal.yml
+- import_tasks: valid-role-symlinks.yml
diff --git a/test/integration/targets/ansible-galaxy/files/testserver.py b/test/integration/targets/ansible-galaxy/files/testserver.py
index 13598507..8cca6a83 100644
--- a/test/integration/targets/ansible-galaxy/files/testserver.py
+++ b/test/integration/targets/ansible-galaxy/files/testserver.py
@@ -1,20 +1,15 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-import sys
+import http.server
+import socketserver
import ssl
if __name__ == '__main__':
- if sys.version_info[0] >= 3:
- import http.server
- import socketserver
- Handler = http.server.SimpleHTTPRequestHandler
- httpd = socketserver.TCPServer(("", 4443), Handler)
- else:
- import BaseHTTPServer
- import SimpleHTTPServer
- Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
- httpd = BaseHTTPServer.HTTPServer(("", 4443), Handler)
+ Handler = http.server.SimpleHTTPRequestHandler
+ context = ssl.SSLContext()
+ context.load_cert_chain(certfile='./cert.pem', keyfile='./key.pem')
+ httpd = socketserver.TCPServer(("", 4443), Handler)
+ httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
- httpd.socket = ssl.wrap_socket(httpd.socket, certfile='./cert.pem', keyfile='./key.pem', server_side=True)
httpd.serve_forever()
diff --git a/test/integration/targets/ansible-galaxy/runme.sh b/test/integration/targets/ansible-galaxy/runme.sh
index 7d966e29..fcd826c3 100755
--- a/test/integration/targets/ansible-galaxy/runme.sh
+++ b/test/integration/targets/ansible-galaxy/runme.sh
@@ -61,10 +61,13 @@ f_ansible_galaxy_create_role_repo_post()
git add .
git commit -m "local testing ansible galaxy role"
+ # NOTE: `HEAD` is used because the newer Git versions create
+ # NOTE: `main` by default and the older ones differ. We
+ # NOTE: want to avoid hardcoding them.
git archive \
--format=tar \
--prefix="${repo_name}/" \
- master > "${repo_tar}"
+ HEAD > "${repo_tar}"
# Configure basic (insecure) HTTPS-accessible repository
galaxy_local_test_role_http_repo="${galaxy_webserver_root}/${galaxy_local_test_role}.git"
if [[ ! -d "${galaxy_local_test_role_http_repo}" ]]; then
@@ -354,7 +357,7 @@ pushd "${galaxy_testdir}"
popd # ${galaxy_testdir}
f_ansible_galaxy_status \
- "role info non-existant role"
+ "role info non-existent role"
mkdir -p "${role_testdir}"
pushd "${role_testdir}"
diff --git a/test/integration/targets/ansible-inventory/files/valid_sample.yml b/test/integration/targets/ansible-inventory/files/valid_sample.yml
index 477f82f2..b8e7b882 100644
--- a/test/integration/targets/ansible-inventory/files/valid_sample.yml
+++ b/test/integration/targets/ansible-inventory/files/valid_sample.yml
@@ -4,4 +4,4 @@ all:
hosts:
something:
foo: bar
- ungrouped: {} \ No newline at end of file
+ ungrouped: {}
diff --git a/test/integration/targets/ansible-inventory/tasks/main.yml b/test/integration/targets/ansible-inventory/tasks/main.yml
index 84ac2c3c..c3459c12 100644
--- a/test/integration/targets/ansible-inventory/tasks/main.yml
+++ b/test/integration/targets/ansible-inventory/tasks/main.yml
@@ -145,3 +145,10 @@
loop_control:
loop_var: toml_package
when: toml_package is not contains 'tomllib' or (toml_package is contains 'tomllib' and ansible_facts.python.version_info >= [3, 11])
+
+
+- include_tasks: "{{item}}_output.yml"
+ loop:
+ - json
+ - yaml
+ - toml
diff --git a/test/integration/targets/ansible-pull/runme.sh b/test/integration/targets/ansible-pull/runme.sh
index 582e8099..b591b283 100755
--- a/test/integration/targets/ansible-pull/runme.sh
+++ b/test/integration/targets/ansible-pull/runme.sh
@@ -36,7 +36,8 @@ function pass_tests {
fi
# test for https://github.com/ansible/ansible/issues/13681
- if grep -E '127\.0\.0\.1.*ok' "${temp_log}"; then
+ # match play default output stats, was matching limit + docker
+ if grep -E '127\.0\.0\.1\s*: ok=' "${temp_log}"; then
cat "${temp_log}"
echo "Found host 127.0.0.1 in output. Only localhost should be present."
exit 1
@@ -86,5 +87,7 @@ ANSIBLE_CONFIG='' ansible-pull -d "${pull_dir}" -U "${repo_dir}" "$@" multi_play
pass_tests_multi
+ANSIBLE_CONFIG='' ansible-pull -d "${pull_dir}" -U "${repo_dir}" conn_secret.yml --connection-password-file "${repo_dir}/secret_connection_password" "$@"
+
# fail if we try do delete /var/tmp
ANSIBLE_CONFIG='' ansible-pull -d var/tmp -U "${repo_dir}" --purge "$@"
diff --git a/test/integration/targets/ansible-runner/aliases b/test/integration/targets/ansible-runner/aliases
index 13e7d785..f4caffd1 100644
--- a/test/integration/targets/ansible-runner/aliases
+++ b/test/integration/targets/ansible-runner/aliases
@@ -1,5 +1,4 @@
shippable/posix/group5
context/controller
-skip/osx
skip/macos
skip/freebsd
diff --git a/test/integration/targets/ansible-runner/files/adhoc_example1.py b/test/integration/targets/ansible-runner/files/adhoc_example1.py
index ab24bcad..fe7f9446 100644
--- a/test/integration/targets/ansible-runner/files/adhoc_example1.py
+++ b/test/integration/targets/ansible-runner/files/adhoc_example1.py
@@ -2,7 +2,6 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import json
-import os
import sys
import ansible_runner
diff --git a/test/integration/targets/ansible-test-cloud-openshift/aliases b/test/integration/targets/ansible-test-cloud-openshift/aliases
index 6e32db7b..b714e82c 100644
--- a/test/integration/targets/ansible-test-cloud-openshift/aliases
+++ b/test/integration/targets/ansible-test-cloud-openshift/aliases
@@ -1,4 +1,4 @@
cloud/openshift
shippable/generic/group1
-disabled # disabled due to requirements conflict: botocore 1.20.6 has requirement urllib3<1.27,>=1.25.4, but you have urllib3 1.24.3.
+disabled # the container crashes when using a non-default network on some docker hosts (such as Ubuntu 20.04)
context/controller
diff --git a/test/integration/targets/ansible-test-cloud-openshift/tasks/main.yml b/test/integration/targets/ansible-test-cloud-openshift/tasks/main.yml
index c3b51904..6acb67dc 100644
--- a/test/integration/targets/ansible-test-cloud-openshift/tasks/main.yml
+++ b/test/integration/targets/ansible-test-cloud-openshift/tasks/main.yml
@@ -1,6 +1,13 @@
+- name: Load kubeconfig
+ include_vars: "{{ lookup('env', 'K8S_AUTH_KUBECONFIG') }}"
+
+- name: Verify endpoints exist
+ assert:
+ that: clusters
+
- name: Verify endpoints respond
uri:
- url: "{{ item }}"
+ url: "{{ item.cluster.server }}"
validate_certs: no
with_items:
- - https://openshift-origin:8443/
+ - "{{ clusters }}"
diff --git a/test/integration/targets/ansible-test-container/runme.py b/test/integration/targets/ansible-test-container/runme.py
index 8ff48e0d..3c86b6dd 100755
--- a/test/integration/targets/ansible-test-container/runme.py
+++ b/test/integration/targets/ansible-test-container/runme.py
@@ -996,7 +996,7 @@ class AptBootstrapper(Bootstrapper):
@classmethod
def install_podman(cls) -> bool:
"""Return True if podman will be installed."""
- return not (os_release.id == 'ubuntu' and os_release.version_id == '20.04')
+ return not (os_release.id == 'ubuntu' and os_release.version_id in {'20.04', '22.04'})
@classmethod
def install_docker(cls) -> bool:
@@ -1053,13 +1053,14 @@ class ApkBootstrapper(Bootstrapper):
# crun added as podman won't install it as dep if runc is present
# but we don't want runc as it fails
# The edge `crun` package installed below requires ip6tables, and in
- # edge, the `iptables` package includes `ip6tables`, but in 3.16 they
- # are separate.
+ # edge, the `iptables` package includes `ip6tables`, but in 3.18 they
+ # are separate. Remove `ip6tables` once we update to 3.19.
packages = ['docker', 'podman', 'openssl', 'crun', 'ip6tables']
run_command('apk', 'add', *packages)
- # 3.16 only contains crun 1.4.5, to get 1.9.2 to resolve the run/shm issue, install crun from edge
- run_command('apk', 'upgrade', '-U', '--repository=http://dl-cdn.alpinelinux.org/alpine/edge/community', 'crun')
+ # 3.18 only contains crun 1.8.4, to get 1.9.2 to resolve the run/shm issue, install crun from 3.19
+ # Remove once we update to 3.19
+ run_command('apk', 'upgrade', '-U', '--repository=http://dl-cdn.alpinelinux.org/alpine/v3.19/community', 'crun')
run_command('service', 'docker', 'start')
run_command('modprobe', 'tun')
diff --git a/test/integration/targets/ansible-test-sanity-import/ansible_collections/ns/col/plugins/lookup/vendor1.py b/test/integration/targets/ansible-test-sanity-import/ansible_collections/ns/col/plugins/lookup/vendor1.py
index f59b9091..f662b97d 100644
--- a/test/integration/targets/ansible-test-sanity-import/ansible_collections/ns/col/plugins/lookup/vendor1.py
+++ b/test/integration/targets/ansible-test-sanity-import/ansible_collections/ns/col/plugins/lookup/vendor1.py
@@ -16,10 +16,10 @@ RETURN = '''#'''
from ansible.plugins.lookup import LookupBase
# noinspection PyUnresolvedReferences
-from ansible.plugins import loader # import the loader to verify it works when the collection loader has already been loaded
+from ansible.plugins import loader # import the loader to verify it works when the collection loader has already been loaded # pylint: disable=unused-import
try:
- import demo
+ import demo # pylint: disable=unused-import
except ImportError:
pass
else:
diff --git a/test/integration/targets/ansible-test-sanity-import/ansible_collections/ns/col/plugins/lookup/vendor2.py b/test/integration/targets/ansible-test-sanity-import/ansible_collections/ns/col/plugins/lookup/vendor2.py
index 22b4236a..38860b03 100644
--- a/test/integration/targets/ansible-test-sanity-import/ansible_collections/ns/col/plugins/lookup/vendor2.py
+++ b/test/integration/targets/ansible-test-sanity-import/ansible_collections/ns/col/plugins/lookup/vendor2.py
@@ -16,10 +16,10 @@ RETURN = '''#'''
from ansible.plugins.lookup import LookupBase
# noinspection PyUnresolvedReferences
-from ansible.plugins import loader # import the loader to verify it works when the collection loader has already been loaded
+from ansible.plugins import loader # import the loader to verify it works when the collection loader has already been loaded # pylint: disable=unused-import
try:
- import demo
+ import demo # pylint: disable=unused-import
except ImportError:
pass
else:
diff --git a/test/integration/targets/ansible-test-sanity-import/runme.sh b/test/integration/targets/ansible-test-sanity-import/runme.sh
index a12e3e3f..a49a71a0 100755
--- a/test/integration/targets/ansible-test-sanity-import/runme.sh
+++ b/test/integration/targets/ansible-test-sanity-import/runme.sh
@@ -1,7 +1,29 @@
#!/usr/bin/env bash
+set -eu
+
+# Create test scenarios at runtime that do not pass sanity tests.
+# This avoids the need to create ignore entries for the tests.
+
+mkdir -p ansible_collections/ns/col/plugins/lookup
+
+(
+ cd ansible_collections/ns/col/plugins/lookup
+
+ echo "import sys; sys.stdout.write('unwanted stdout')" > stdout.py # stdout: unwanted stdout
+ echo "import sys; sys.stderr.write('unwanted stderr')" > stderr.py # stderr: unwanted stderr
+)
+
source ../collection/setup.sh
+# Run regular import sanity tests.
+
+ansible-test sanity --test import --color --failure-ok --lint --python "${ANSIBLE_TEST_PYTHON_VERSION}" "${@}" 1> actual-stdout.txt 2> actual-stderr.txt
+diff -u "${TEST_DIR}/expected.txt" actual-stdout.txt
+grep -f "${TEST_DIR}/expected.txt" actual-stderr.txt
+
+# Run import sanity tests which require modifications to the source directory.
+
vendor_dir="$(python -c 'import pathlib, ansible._vendor; print(pathlib.Path(ansible._vendor.__file__).parent)')"
cleanup() {
diff --git a/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/col/plugins/modules/sidecar.yaml b/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/col/plugins/modules/sidecar.yaml
index c2575422..4ca20efb 100644
--- a/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/col/plugins/modules/sidecar.yaml
+++ b/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/col/plugins/modules/sidecar.yaml
@@ -17,6 +17,9 @@ DOCUMENTATION:
default: foo
author:
- Ansible Core Team
+ seealso:
+ - plugin: ns.col.import_order_lookup
+ plugin_type: lookup
EXAMPLES: |
- name: example for sidecar
diff --git a/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/failure/README.md b/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/failure/README.md
index bf1003fa..d158a987 100644
--- a/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/failure/README.md
+++ b/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/failure/README.md
@@ -1,3 +1,4 @@
README
------
+
This is a simple collection used to test failures with ``ansible-test sanity --test validate-modules``.
diff --git a/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/ps_only/README.md b/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/ps_only/README.md
index bbdd5138..9c1c1c34 100644
--- a/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/ps_only/README.md
+++ b/test/integration/targets/ansible-test-sanity-validate-modules/ansible_collections/ns/ps_only/README.md
@@ -1,3 +1,4 @@
README
------
+
This is a simple PowerShell-only collection used to verify that ``ansible-test`` works on a collection.
diff --git a/test/integration/targets/ansible-test-sanity-validate-modules/expected.txt b/test/integration/targets/ansible-test-sanity-validate-modules/expected.txt
index 95f12f39..ca6e52a3 100644
--- a/test/integration/targets/ansible-test-sanity-validate-modules/expected.txt
+++ b/test/integration/targets/ansible-test-sanity-validate-modules/expected.txt
@@ -1,5 +1,26 @@
+plugins/lookup/import_order_lookup.py:5:0: import-before-documentation: Import found before documentation variables. All imports must appear below DOCUMENTATION/EXAMPLES/RETURN.
+plugins/modules/check_mode_attribute_1.py:0:0: attributes-check-mode: The module does not declare support for check mode, but the check_mode attribute's support value is 'full' and not 'none'
+plugins/modules/check_mode_attribute_2.py:0:0: attributes-check-mode: The module does not declare support for check mode, but the check_mode attribute's support value is 'partial' and not 'none'
+plugins/modules/check_mode_attribute_3.py:0:0: attributes-check-mode: The module does declare support for check mode, but the check_mode attribute's support value is 'none'
+plugins/modules/check_mode_attribute_4.py:0:0: attributes-check-mode-details: The module declares it does not fully support check mode, but has no details on what exactly that means
+plugins/modules/import_order.py:8:0: import-before-documentation: Import found before documentation variables. All imports must appear below DOCUMENTATION/EXAMPLES/RETURN.
plugins/modules/invalid_yaml_syntax.py:0:0: deprecation-mismatch: "meta/runtime.yml" and DOCUMENTATION.deprecation do not agree.
plugins/modules/invalid_yaml_syntax.py:0:0: missing-documentation: No DOCUMENTATION provided
plugins/modules/invalid_yaml_syntax.py:8:15: documentation-syntax-error: DOCUMENTATION is not valid YAML
plugins/modules/invalid_yaml_syntax.py:12:15: invalid-examples: EXAMPLES is not valid YAML
plugins/modules/invalid_yaml_syntax.py:16:15: return-syntax-error: RETURN is not valid YAML
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.a11.suboptions.b1.description.0: While parsing "V(C\(" at index 1: Unnecessarily escaped "(" @ data['options']['a11']['suboptions']['b1']['description'][0]. Got 'V(C\\(foo\\)).'
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.a11.suboptions.b1.description.2: While parsing "P(foo.bar#baz)" at index 1: Plugin name "foo.bar" is not a FQCN @ data['options']['a11']['suboptions']['b1']['description'][2]. Got 'P(foo.bar#baz).'
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.a11.suboptions.b1.description.3: While parsing "P(foo.bar.baz)" at index 1: Parameter "foo.bar.baz" is not of the form FQCN#type @ data['options']['a11']['suboptions']['b1']['description'][3]. Got 'P(foo.bar.baz).'
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.a11.suboptions.b1.description.4: Directive "P(foo.bar.baz#woof)" must contain a valid plugin type; found "woof" @ data['options']['a11']['suboptions']['b1']['description'][4]. Got 'P(foo.bar.baz#woof).'
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.a11.suboptions.b1.description.5: While parsing "E(foo\(" at index 1: Unnecessarily escaped "(" @ data['options']['a11']['suboptions']['b1']['description'][5]. Got 'E(foo\\(bar).'
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.a2.description: While parsing "V(C\(" at index 1: Unnecessarily escaped "(" for dictionary value @ data['options']['a2']['description']. Got 'V(C\\(foo\\)).'
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.a4.description: While parsing "P(foo.bar#baz)" at index 1: Plugin name "foo.bar" is not a FQCN for dictionary value @ data['options']['a4']['description']. Got 'P(foo.bar#baz).'
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.a5.description: While parsing "P(foo.bar.baz)" at index 1: Parameter "foo.bar.baz" is not of the form FQCN#type for dictionary value @ data['options']['a5']['description']. Got 'P(foo.bar.baz).'
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.a6.description: Directive "P(foo.bar.baz#woof)" must contain a valid plugin type; found "woof" for dictionary value @ data['options']['a6']['description']. Got 'P(foo.bar.baz#woof).'
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.a7.description: While parsing "E(foo\(" at index 1: Unnecessarily escaped "(" for dictionary value @ data['options']['a7']['description']. Got 'E(foo\\(bar).'
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: Directive "O(bar)" contains a non-existing option "bar"
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: Directive "O(bar=bam)" contains a non-existing option "bar"
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: Directive "O(foo.bar=1)" contains a non-existing option "foo.bar"
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: Directive "RV(bam)" contains a non-existing return value "bam"
+plugins/modules/semantic_markup.py:0:0: invalid-documentation-markup: Directive "RV(does.not.exist=true)" contains a non-existing return value "does.not.exist"
diff --git a/test/integration/targets/ansible-test-sanity-validate-modules/runme.sh b/test/integration/targets/ansible-test-sanity-validate-modules/runme.sh
index e0299969..5e2365ab 100755
--- a/test/integration/targets/ansible-test-sanity-validate-modules/runme.sh
+++ b/test/integration/targets/ansible-test-sanity-validate-modules/runme.sh
@@ -6,7 +6,17 @@ set -eux
ansible-test sanity --test validate-modules --color --truncate 0 --failure-ok --lint "${@}" 1> actual-stdout.txt 2> actual-stderr.txt
diff -u "${TEST_DIR}/expected.txt" actual-stdout.txt
-grep -f "${TEST_DIR}/expected.txt" actual-stderr.txt
+grep -F -f "${TEST_DIR}/expected.txt" actual-stderr.txt
+
+cd ../col
+ansible-test sanity --test runtime-metadata
+
+cd ../failure
+if ansible-test sanity --test runtime-metadata 2>&1 | tee out.txt; then
+ echo "runtime-metadata in failure should be invalid"
+ exit 1
+fi
+grep out.txt -e 'extra keys not allowed'
cd ../ps_only
diff --git a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/README.md b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/README.md
index d8138d3b..67b8a83b 100644
--- a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/README.md
+++ b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/README.md
@@ -1,3 +1,4 @@
README
------
+
This is a simple collection used to verify that ``ansible-test`` works on a collection.
diff --git a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/meta/runtime.yml b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/meta/runtime.yml
index fee22ad8..76ead137 100644
--- a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/meta/runtime.yml
+++ b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/meta/runtime.yml
@@ -2,4 +2,11 @@ requires_ansible: '>=2.11' # force ansible-doc to check the Ansible version (re
plugin_routing:
modules:
hi:
- redirect: hello
+ redirect: ns.col2.hello
+ hiya:
+ redirect: ns.col2.package.subdir.hiya
+ module_utils:
+ hi:
+ redirect: ansible_collections.ns.col2.plugins.module_utils
+ hello:
+ redirect: ns.col2.hiya
diff --git a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/lookup/bad.py b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/lookup/bad.py
index 580f9d87..16e0bc88 100644
--- a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/lookup/bad.py
+++ b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/lookup/bad.py
@@ -19,9 +19,9 @@ EXAMPLES = '''
RETURN = ''' # '''
from ansible.plugins.lookup import LookupBase
-from ansible import constants
+from ansible import constants # pylint: disable=unused-import
-import lxml
+import lxml # pylint: disable=unused-import
class LookupModule(LookupBase):
diff --git a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/lookup/world.py b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/lookup/world.py
index dbb479a7..5cdd0966 100644
--- a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/lookup/world.py
+++ b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/lookup/world.py
@@ -19,7 +19,7 @@ EXAMPLES = '''
RETURN = ''' # '''
from ansible.plugins.lookup import LookupBase
-from ansible import constants
+from ansible import constants # pylint: disable=unused-import
class LookupModule(LookupBase):
diff --git a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/modules/bad.py b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/modules/bad.py
index e79613bb..8780e356 100644
--- a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/modules/bad.py
+++ b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/modules/bad.py
@@ -19,7 +19,7 @@ EXAMPLES = '''
RETURN = ''''''
from ansible.module_utils.basic import AnsibleModule
-from ansible import constants # intentionally trigger pylint ansible-bad-module-import error
+from ansible import constants # intentionally trigger pylint ansible-bad-module-import error # pylint: disable=unused-import
def main():
diff --git a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/random_directory/bad.py b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/random_directory/bad.py
index 2e35cf85..e34d1c37 100644
--- a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/random_directory/bad.py
+++ b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/plugins/random_directory/bad.py
@@ -5,4 +5,4 @@ __metaclass__ = type
# This is not an allowed import, but since this file is in a plugins/ subdirectory that is not checked,
# the import sanity test will not complain.
-import lxml
+import lxml # pylint: disable=unused-import
diff --git a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/integration/targets/hello/files/bad.py b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/integration/targets/hello/files/bad.py
index 82215438..a5d896f7 100644
--- a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/integration/targets/hello/files/bad.py
+++ b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/integration/targets/hello/files/bad.py
@@ -4,12 +4,12 @@ __metaclass__ = type
import tempfile
try:
- import urllib2 # intentionally trigger pylint ansible-bad-import error
+ import urllib2 # intentionally trigger pylint ansible-bad-import error # pylint: disable=unused-import
except ImportError:
urllib2 = None
try:
- from urllib2 import Request # intentionally trigger pylint ansible-bad-import-from error
+ from urllib2 import Request # intentionally trigger pylint ansible-bad-import-from error # pylint: disable=unused-import
except ImportError:
Request = None
diff --git a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/sanity/ignore.txt b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/sanity/ignore.txt
index e1b3f4ca..dcbe827c 100644
--- a/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/sanity/ignore.txt
+++ b/test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/sanity/ignore.txt
@@ -1,6 +1,7 @@
plugins/modules/bad.py import
plugins/modules/bad.py pylint:ansible-bad-module-import
plugins/lookup/bad.py import
+plugins/plugin_utils/check_pylint.py pylint:disallowed-name
tests/integration/targets/hello/files/bad.py pylint:ansible-bad-function
tests/integration/targets/hello/files/bad.py pylint:ansible-bad-import
tests/integration/targets/hello/files/bad.py pylint:ansible-bad-import-from
diff --git a/test/integration/targets/ansible-test-sanity/runme.sh b/test/integration/targets/ansible-test-sanity/runme.sh
index 233db741..92584958 100755
--- a/test/integration/targets/ansible-test-sanity/runme.sh
+++ b/test/integration/targets/ansible-test-sanity/runme.sh
@@ -1,5 +1,11 @@
#!/usr/bin/env bash
+set -eux
+
+ansible-test sanity --color --allow-disabled -e "${@}"
+
+set +x
+
source ../collection/setup.sh
set -x
diff --git a/test/integration/targets/ansible-test/venv-pythons.py b/test/integration/targets/ansible-test/venv-pythons.py
index b380f147..97998bcd 100755
--- a/test/integration/targets/ansible-test/venv-pythons.py
+++ b/test/integration/targets/ansible-test/venv-pythons.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
"""Return target Python options for use with ansible-test."""
+import argparse
import os
import shutil
import subprocess
@@ -10,6 +11,11 @@ from ansible import release
def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--only-versions', action='store_true')
+
+ options = parser.parse_args()
+
ansible_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(release.__file__))))
source_root = os.path.join(ansible_root, 'test', 'lib')
@@ -33,6 +39,10 @@ def main():
print(f'{executable} - {"fail" if process.returncode else "pass"}', file=sys.stderr)
if not process.returncode:
+ if options.only_versions:
+ args.append(python_version)
+ continue
+
args.extend(['--target-python', f'venv/{python_version}'])
print(' '.join(args))
diff --git a/test/integration/targets/ansible-vault/invalid_format/broken-group-vars-tasks.yml b/test/integration/targets/ansible-vault/invalid_format/broken-group-vars-tasks.yml
index 71dbacc0..2365d47d 100644
--- a/test/integration/targets/ansible-vault/invalid_format/broken-group-vars-tasks.yml
+++ b/test/integration/targets/ansible-vault/invalid_format/broken-group-vars-tasks.yml
@@ -20,4 +20,4 @@
# 3366323866663763660a323766383531396433663861656532373663373134376263383263316261
# 3137
-# $ ansible-playbook -i inventory --vault-password-file=vault-secret tasks.yml
+# $ ansible-playbook -i inventory --vault-password-file=vault-secret tasks.yml
diff --git a/test/integration/targets/ansible-vault/runme.sh b/test/integration/targets/ansible-vault/runme.sh
index 50720ea9..98399eca 100755
--- a/test/integration/targets/ansible-vault/runme.sh
+++ b/test/integration/targets/ansible-vault/runme.sh
@@ -47,6 +47,18 @@ echo $?
# view the vault encrypted password file
ansible-vault view "$@" --vault-id vault-password encrypted-vault-password
+# check if ansible-vault fails when destination is not writable
+NOT_WRITABLE_DIR="${MYTMPDIR}/not_writable"
+TEST_FILE_EDIT4="${NOT_WRITABLE_DIR}/testfile"
+mkdir "${NOT_WRITABLE_DIR}"
+touch "${TEST_FILE_EDIT4}"
+chmod ugo-w "${NOT_WRITABLE_DIR}"
+ansible-vault encrypt "$@" --vault-password-file vault-password "${TEST_FILE_EDIT4}" < /dev/null > log 2>&1 && :
+grep "not writable" log && :
+WRONG_RC=$?
+echo "rc was $WRONG_RC (1 is expected)"
+[ $WRONG_RC -eq 1 ]
+
# encrypt with a password from a vault encrypted password file and multiple vault-ids
# should fail because we dont know which vault id to use to encrypt with
ansible-vault encrypt "$@" --vault-id vault-password --vault-id encrypted-vault-password "${TEST_FILE_ENC_PASSWORD}" && :
@@ -574,3 +586,23 @@ ansible-playbook realpath.yml "$@" --vault-password-file symlink/get-password-sy
# using symlink
ansible-playbook symlink.yml "$@" --vault-password-file script/vault-secret.sh 2>&1 |grep "${ER}"
+
+### SALT TESTING ###
+# prep files for encryption
+for salted in test1 test2 test3
+do
+ echo 'this is salty' > "salted_${salted}"
+done
+
+# encrypt files
+ANSIBLE_VAULT_ENCRYPT_SALT=salty ansible-vault encrypt salted_test1 --vault-password-file example1_password "$@"
+ANSIBLE_VAULT_ENCRYPT_SALT=salty ansible-vault encrypt salted_test2 --vault-password-file example1_password "$@"
+ansible-vault encrypt salted_test3 --vault-password-file example1_password "$@"
+
+# should be the same
+out=$(diff salted_test1 salted_test2)
+[ "${out}" == "" ]
+
+# shoudl be diff
+out=$(diff salted_test1 salted_test3 || true)
+[ "${out}" != "" ]
diff --git a/test/integration/targets/ansible-vault/test_vault.yml b/test/integration/targets/ansible-vault/test_vault.yml
index 7f8ed115..c21d49a6 100644
--- a/test/integration/targets/ansible-vault/test_vault.yml
+++ b/test/integration/targets/ansible-vault/test_vault.yml
@@ -1,6 +1,6 @@
- hosts: testhost
gather_facts: False
vars:
- - output_dir: .
+ output_dir: .
roles:
- { role: test_vault, tags: test_vault}
diff --git a/test/integration/targets/ansible-vault/test_vaulted_template.yml b/test/integration/targets/ansible-vault/test_vaulted_template.yml
index b495211d..6a16ec86 100644
--- a/test/integration/targets/ansible-vault/test_vaulted_template.yml
+++ b/test/integration/targets/ansible-vault/test_vaulted_template.yml
@@ -1,6 +1,6 @@
- hosts: testhost
gather_facts: False
vars:
- - output_dir: .
+ output_dir: .
roles:
- { role: test_vaulted_template, tags: test_vaulted_template}
diff --git a/test/integration/targets/ansible/aliases b/test/integration/targets/ansible/aliases
index 8278ec8b..c7f2050a 100644
--- a/test/integration/targets/ansible/aliases
+++ b/test/integration/targets/ansible/aliases
@@ -1,2 +1,3 @@
shippable/posix/group3
context/controller
+needs/target/support-callback_plugins
diff --git a/test/integration/targets/ansible/ansible-testé.cfg b/test/integration/targets/ansible/ansible-testé.cfg
index 09af947f..a0e4e8d7 100644
--- a/test/integration/targets/ansible/ansible-testé.cfg
+++ b/test/integration/targets/ansible/ansible-testé.cfg
@@ -1,3 +1,3 @@
[defaults]
remote_user = admin
-collections_paths = /tmp/collections
+collections_path = /tmp/collections
diff --git a/test/integration/targets/ansible/runme.sh b/test/integration/targets/ansible/runme.sh
index e9e72a9f..d6780214 100755
--- a/test/integration/targets/ansible/runme.sh
+++ b/test/integration/targets/ansible/runme.sh
@@ -14,9 +14,9 @@ ANSIBLE_REMOTE_USER=administrator ansible-config dump| grep 'DEFAULT_REMOTE_USER
ansible-config list | grep 'DEFAULT_REMOTE_USER'
# Collection
-ansible-config view -c ./ansible-testé.cfg | grep 'collections_paths = /tmp/collections'
+ansible-config view -c ./ansible-testé.cfg | grep 'collections_path = /tmp/collections'
ansible-config dump -c ./ansible-testé.cfg | grep 'COLLECTIONS_PATHS([^)]*) ='
-ANSIBLE_COLLECTIONS_PATHS=/tmp/collections ansible-config dump| grep 'COLLECTIONS_PATHS([^)]*) ='
+ANSIBLE_COLLECTIONS_PATH=/tmp/collections ansible-config dump| grep 'COLLECTIONS_PATHS([^)]*) ='
ansible-config list | grep 'COLLECTIONS_PATHS'
# 'view' command must fail when config file is missing or has an invalid file extension
@@ -34,7 +34,7 @@ ansible localhost -m debug -a var=playbook_dir --playbook-dir=/doesnotexist/tmp
env -u ANSIBLE_PLAYBOOK_DIR ANSIBLE_CONFIG=./playbookdir_cfg.ini ansible localhost -m debug -a var=playbook_dir | grep '"playbook_dir": "/doesnotexist/tmp"'
# test adhoc callback triggers
-ANSIBLE_STDOUT_CALLBACK=callback_debug ANSIBLE_LOAD_CALLBACK_PLUGINS=1 ansible --playbook-dir . testhost -i ../../inventory -m ping | grep -E '^v2_' | diff -u adhoc-callback.stdout -
+ANSIBLE_CALLBACK_PLUGINS=../support-callback_plugins/callback_plugins ANSIBLE_STDOUT_CALLBACK=callback_debug ANSIBLE_LOAD_CALLBACK_PLUGINS=1 ansible --playbook-dir . testhost -i ../../inventory -m ping | grep -E '^v2_' | diff -u adhoc-callback.stdout -
# CB_WANTS_IMPLICIT isn't anything in Ansible itself.
# Our test cb plugin just accepts it. It lets us avoid copypasting the whole
diff --git a/test/integration/targets/apt/aliases b/test/integration/targets/apt/aliases
index 5f892f9c..20c87093 100644
--- a/test/integration/targets/apt/aliases
+++ b/test/integration/targets/apt/aliases
@@ -1,6 +1,5 @@
shippable/posix/group2
destructive
skip/freebsd
-skip/osx
skip/macos
skip/rhel
diff --git a/test/integration/targets/apt/tasks/apt.yml b/test/integration/targets/apt/tasks/apt.yml
index d273eda7..a0bc1992 100644
--- a/test/integration/targets/apt/tasks/apt.yml
+++ b/test/integration/targets/apt/tasks/apt.yml
@@ -372,7 +372,7 @@
- libcaca-dev
- libslang2-dev
-# https://github.com/ansible/ansible/issues/38995
+# # https://github.com/ansible/ansible/issues/38995
- name: build-dep for a package
apt:
name: tree
@@ -524,6 +524,55 @@
- "allow_change_held_packages_no_update is not changed"
- "allow_change_held_packages_hello_version.stdout == allow_change_held_packages_hello_version_again.stdout"
+# Remove pkg on hold
+- name: Put hello on hold
+ shell: apt-mark hold hello
+
+- name: Get hold list
+ shell: apt-mark showhold
+ register: hello_hold
+
+- name: Check that the package hello is on the hold list
+ assert:
+ that:
+ - "'hello' in hello_hold.stdout"
+
+- name: Try removing package hello
+ apt:
+ name: hello
+ state: absent
+ register: package_removed
+ ignore_errors: true
+
+- name: verify the package is not removed with dpkg
+ shell: dpkg -l hello
+ register: dpkg_result
+
+- name: Verify that package was not removed
+ assert:
+ that:
+ - package_removed is failed
+ - dpkg_result is success
+
+- name: Try removing package (allow_change_held_packages=yes)
+ apt:
+ name: hello
+ state: absent
+ allow_change_held_packages: yes
+ register: package_removed
+
+- name: verify the package is removed with dpkg
+ shell: dpkg -l hello
+ register: dpkg_result
+ ignore_errors: true
+
+- name: Verify that package removal was succesfull
+ assert:
+ that:
+ - package_removed is success
+ - dpkg_result is failed
+ - package_removed.changed
+
# Virtual package
- name: Install a virtual package
apt:
diff --git a/test/integration/targets/apt/tasks/repo.yml b/test/integration/targets/apt/tasks/repo.yml
index d4cce78a..b1d08afa 100644
--- a/test/integration/targets/apt/tasks/repo.yml
+++ b/test/integration/targets/apt/tasks/repo.yml
@@ -400,6 +400,8 @@
- { upgrade_type: safe, force_apt_get: True }
- { upgrade_type: full, force_apt_get: True }
+ - include_tasks: "upgrade_scenarios.yml"
+
- name: Remove aptitude if not originally present
apt:
pkg: aptitude
diff --git a/test/integration/targets/apt_key/aliases b/test/integration/targets/apt_key/aliases
index a820ec90..97f534a8 100644
--- a/test/integration/targets/apt_key/aliases
+++ b/test/integration/targets/apt_key/aliases
@@ -1,5 +1,4 @@
shippable/posix/group1
skip/freebsd
-skip/osx
skip/macos
skip/rhel
diff --git a/test/integration/targets/apt_key/tasks/main.yml b/test/integration/targets/apt_key/tasks/main.yml
index ffb89b22..7aee56a7 100644
--- a/test/integration/targets/apt_key/tasks/main.yml
+++ b/test/integration/targets/apt_key/tasks/main.yml
@@ -21,7 +21,7 @@
- import_tasks: 'apt_key_inline_data.yml'
when: ansible_distribution in ('Ubuntu', 'Debian')
-
+
- import_tasks: 'file.yml'
when: ansible_distribution in ('Ubuntu', 'Debian')
diff --git a/test/integration/targets/apt_repository/aliases b/test/integration/targets/apt_repository/aliases
index 34e2b540..b4fe8dba 100644
--- a/test/integration/targets/apt_repository/aliases
+++ b/test/integration/targets/apt_repository/aliases
@@ -1,6 +1,5 @@
destructive
shippable/posix/group1
skip/freebsd
-skip/osx
skip/macos
skip/rhel
diff --git a/test/integration/targets/apt_repository/tasks/apt.yml b/test/integration/targets/apt_repository/tasks/apt.yml
index 9c15e647..2ddf4140 100644
--- a/test/integration/targets/apt_repository/tasks/apt.yml
+++ b/test/integration/targets/apt_repository/tasks/apt.yml
@@ -152,6 +152,11 @@
- 'result.changed'
- 'result.state == "present"'
- 'result.repo == test_ppa_spec'
+ - '"sources_added" in result'
+ - 'result.sources_added | length == 1'
+ - '"git" in result.sources_added[0]'
+ - '"sources_removed" in result'
+ - 'result.sources_removed | length == 0'
- result_cache is not changed
- name: 'examine apt cache mtime'
@@ -167,6 +172,17 @@
apt_repository: repo='{{test_ppa_spec}}' state=absent
register: result
+- assert:
+ that:
+ - 'result.changed'
+ - 'result.state == "absent"'
+ - 'result.repo == test_ppa_spec'
+ - '"sources_added" in result'
+ - 'result.sources_added | length == 0'
+ - '"sources_removed" in result'
+ - 'result.sources_removed | length == 1'
+ - '"git" in result.sources_removed[0]'
+
# When installing a repo with the spec, the key is *NOT* added
- name: 'ensure ppa key is absent (expect: pass)'
apt_key: id='{{test_ppa_key}}' state=absent
@@ -224,7 +240,7 @@
- assert:
that:
- result is failed
- - result.msg == 'Please set argument \'repo\' to a non-empty value'
+ - result.msg.startswith("argument 'repo' is of type <class 'NoneType'> and we were unable to convert to str")
- name: Test apt_repository with an empty value for repo
apt_repository:
diff --git a/test/integration/targets/apt_repository/tasks/mode_cleanup.yaml b/test/integration/targets/apt_repository/tasks/mode_cleanup.yaml
index 726de111..62960ccd 100644
--- a/test/integration/targets/apt_repository/tasks/mode_cleanup.yaml
+++ b/test/integration/targets/apt_repository/tasks/mode_cleanup.yaml
@@ -4,4 +4,4 @@
- name: Delete existing repo
file:
path: "{{ test_repo_path }}"
- state: absent \ No newline at end of file
+ state: absent
diff --git a/test/integration/targets/argspec/library/argspec.py b/test/integration/targets/argspec/library/argspec.py
index b6d6d110..2d86d77b 100644
--- a/test/integration/targets/argspec/library/argspec.py
+++ b/test/integration/targets/argspec/library/argspec.py
@@ -23,6 +23,10 @@ def main():
'type': 'str',
'choices': ['absent', 'present'],
},
+ 'default_value': {
+ 'type': 'bool',
+ 'default': True,
+ },
'path': {},
'content': {},
'mapping': {
@@ -246,7 +250,7 @@ def main():
('state', 'present', ('path', 'content'), True),
),
mutually_exclusive=(
- ('path', 'content'),
+ ('path', 'content', 'default_value',),
),
required_one_of=(
('required_one_of_one', 'required_one_of_two'),
diff --git a/test/integration/targets/become/tasks/main.yml b/test/integration/targets/become/tasks/main.yml
index 4a2ce64b..c05824d7 100644
--- a/test/integration/targets/become/tasks/main.yml
+++ b/test/integration/targets/become/tasks/main.yml
@@ -11,8 +11,8 @@
ansible_become_user: "{{ become_test_config.user }}"
ansible_become_method: "{{ become_test_config.method }}"
ansible_become_password: "{{ become_test_config.password | default(None) }}"
- loop: "{{
- (become_methods | selectattr('skip', 'undefined') | list)+
+ loop: "{{
+ (become_methods | selectattr('skip', 'undefined') | list)+
(become_methods | selectattr('skip', 'defined') | rejectattr('skip') | list)
}}"
loop_control:
diff --git a/test/integration/targets/blockinfile/tasks/main.yml b/test/integration/targets/blockinfile/tasks/main.yml
index 054e5549..f26cb165 100644
--- a/test/integration/targets/blockinfile/tasks/main.yml
+++ b/test/integration/targets/blockinfile/tasks/main.yml
@@ -31,6 +31,7 @@
- import_tasks: add_block_to_existing_file.yml
- import_tasks: create_file.yml
+- import_tasks: create_dir.yml
- import_tasks: preserve_line_endings.yml
- import_tasks: block_without_trailing_newline.yml
- import_tasks: file_without_trailing_newline.yml
@@ -39,3 +40,5 @@
- import_tasks: insertafter.yml
- import_tasks: insertbefore.yml
- import_tasks: multiline_search.yml
+- import_tasks: append_newline.yml
+- import_tasks: prepend_newline.yml
diff --git a/test/integration/targets/blocks/unsafe_failed_task.yml b/test/integration/targets/blocks/unsafe_failed_task.yml
index adfa492a..e74327b9 100644
--- a/test/integration/targets/blocks/unsafe_failed_task.yml
+++ b/test/integration/targets/blocks/unsafe_failed_task.yml
@@ -1,7 +1,7 @@
- hosts: localhost
gather_facts: false
vars:
- - data: {}
+ data: {}
tasks:
- block:
- name: template error
diff --git a/test/integration/targets/callback_default/callback_default.out.result_format_yaml_lossy_verbose.stdout b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_lossy_verbose.stdout
index 71a4ef9e..ed455756 100644
--- a/test/integration/targets/callback_default/callback_default.out.result_format_yaml_lossy_verbose.stdout
+++ b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_lossy_verbose.stdout
@@ -43,6 +43,7 @@ fatal: [testhost]: FAILED! =>
TASK [Skipped task] ************************************************************
skipping: [testhost] =>
changed: false
+ false_condition: false
skip_reason: Conditional result was False
TASK [Task with var in name (foo bar)] *****************************************
@@ -120,6 +121,7 @@ ok: [testhost] => (item=debug-3) =>
msg: debug-3
skipping: [testhost] => (item=debug-4) =>
ansible_loop_var: item
+ false_condition: item != 4
item: 4
fatal: [testhost]: FAILED! =>
msg: One or more items failed
@@ -199,9 +201,11 @@ skipping: [testhost] =>
TASK [debug] *******************************************************************
skipping: [testhost] => (item=1) =>
ansible_loop_var: item
+ false_condition: false
item: 1
skipping: [testhost] => (item=2) =>
ansible_loop_var: item
+ false_condition: false
item: 2
skipping: [testhost] =>
msg: All items skipped
diff --git a/test/integration/targets/callback_default/callback_default.out.result_format_yaml_verbose.stdout b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_verbose.stdout
index 7a99cc74..3a121a5f 100644
--- a/test/integration/targets/callback_default/callback_default.out.result_format_yaml_verbose.stdout
+++ b/test/integration/targets/callback_default/callback_default.out.result_format_yaml_verbose.stdout
@@ -45,6 +45,7 @@ fatal: [testhost]: FAILED! =>
TASK [Skipped task] ************************************************************
skipping: [testhost] =>
changed: false
+ false_condition: false
skip_reason: Conditional result was False
TASK [Task with var in name (foo bar)] *****************************************
@@ -126,6 +127,7 @@ ok: [testhost] => (item=debug-3) =>
msg: debug-3
skipping: [testhost] => (item=debug-4) =>
ansible_loop_var: item
+ false_condition: item != 4
item: 4
fatal: [testhost]: FAILED! =>
msg: One or more items failed
@@ -206,9 +208,11 @@ skipping: [testhost] =>
TASK [debug] *******************************************************************
skipping: [testhost] => (item=1) =>
ansible_loop_var: item
+ false_condition: false
item: 1
skipping: [testhost] => (item=2) =>
ansible_loop_var: item
+ false_condition: false
item: 2
skipping: [testhost] =>
msg: All items skipped
diff --git a/test/integration/targets/check_mode/check_mode.yml b/test/integration/targets/check_mode/check_mode.yml
index a5777506..ebf1c5b5 100644
--- a/test/integration/targets/check_mode/check_mode.yml
+++ b/test/integration/targets/check_mode/check_mode.yml
@@ -1,7 +1,7 @@
- name: Test that check works with check_mode specified in roles
hosts: testhost
vars:
- - output_dir: .
+ output_dir: .
roles:
- { role: test_always_run, tags: test_always_run }
- { role: test_check_mode, tags: test_check_mode }
diff --git a/test/integration/targets/check_mode/roles/test_check_mode/tasks/main.yml b/test/integration/targets/check_mode/roles/test_check_mode/tasks/main.yml
index f926d144..ce9ecbf4 100644
--- a/test/integration/targets/check_mode/roles/test_check_mode/tasks/main.yml
+++ b/test/integration/targets/check_mode/roles/test_check_mode/tasks/main.yml
@@ -25,8 +25,8 @@
register: foo
- name: verify that the file was marked as changed in check mode
- assert:
- that:
+ assert:
+ that:
- "template_result is changed"
- "not foo.stat.exists"
@@ -44,7 +44,7 @@
check_mode: no
- name: verify that the file was not changed
- assert:
- that:
+ assert:
+ that:
- "checkmode_disabled is changed"
- "template_result2 is not changed"
diff --git a/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/connection/localconn.py b/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/connection/localconn.py
index fc19a99d..77f80502 100644
--- a/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/connection/localconn.py
+++ b/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/connection/localconn.py
@@ -1,7 +1,7 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-from ansible.module_utils._text import to_native
+from ansible.module_utils.common.text.converters import to_native
from ansible.plugins.connection import ConnectionBase
DOCUMENTATION = """
diff --git a/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing.py b/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing.py
index b945eb68..6f3a19d7 100644
--- a/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing.py
+++ b/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing.py
@@ -2,10 +2,7 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-import json
-import sys
-
-from ..module_utils import bogusmu # pylint: disable=relative-beyond-top-level
+from ..module_utils import bogusmu # pylint: disable=relative-beyond-top-level,unused-import
def main():
diff --git a/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing_redirect_collection.py b/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing_redirect_collection.py
index 59cb3c5e..6f2320d3 100644
--- a/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing_redirect_collection.py
+++ b/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing_redirect_collection.py
@@ -2,10 +2,7 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-import json
-import sys
-
-from ..module_utils import missing_redirect_target_collection # pylint: disable=relative-beyond-top-level
+from ..module_utils import missing_redirect_target_collection # pylint: disable=relative-beyond-top-level,unused-import
def main():
diff --git a/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing_redirect_module.py b/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing_redirect_module.py
index 31ffd17c..de5c2e58 100644
--- a/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing_redirect_module.py
+++ b/test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/modules/uses_mu_missing_redirect_module.py
@@ -2,10 +2,7 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-import json
-import sys
-
-from ..module_utils import missing_redirect_target_module # pylint: disable=relative-beyond-top-level
+from ..module_utils import missing_redirect_target_module # pylint: disable=relative-beyond-top-level,unused-import
def main():
diff --git a/test/integration/targets/collections/collections/ansible_collections/testns/content_adj/plugins/inventory/statichost.py b/test/integration/targets/collections/collections/ansible_collections/testns/content_adj/plugins/inventory/statichost.py
index ae6941f3..92696481 100644
--- a/test/integration/targets/collections/collections/ansible_collections/testns/content_adj/plugins/inventory/statichost.py
+++ b/test/integration/targets/collections/collections/ansible_collections/testns/content_adj/plugins/inventory/statichost.py
@@ -19,7 +19,6 @@ DOCUMENTATION = '''
required: True
'''
-from ansible.errors import AnsibleParserError
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable
diff --git a/test/integration/targets/collections/test_task_resolved_plugin/callback_plugins/display_resolved_action.py b/test/integration/targets/collections/test_task_resolved_plugin/callback_plugins/display_resolved_action.py
index 23cce104..f1242e14 100644
--- a/test/integration/targets/collections/test_task_resolved_plugin/callback_plugins/display_resolved_action.py
+++ b/test/integration/targets/collections/test_task_resolved_plugin/callback_plugins/display_resolved_action.py
@@ -14,7 +14,6 @@ DOCUMENTATION = '''
- Enable in configuration.
'''
-from ansible import constants as C
from ansible.plugins.callback import CallbackBase
diff --git a/test/integration/targets/command_nonexisting/tasks/main.yml b/test/integration/targets/command_nonexisting/tasks/main.yml
index d21856e7..e54ecb3f 100644
--- a/test/integration/targets/command_nonexisting/tasks/main.yml
+++ b/test/integration/targets/command_nonexisting/tasks/main.yml
@@ -1,4 +1,4 @@
- command: commandthatdoesnotexist --would-be-awkward
register: res
changed_when: "'changed' in res.stdout"
- failed_when: "res.stdout != '' or res.stderr != ''" \ No newline at end of file
+ failed_when: "res.stdout != '' or res.stderr != ''"
diff --git a/test/integration/targets/command_shell/tasks/main.yml b/test/integration/targets/command_shell/tasks/main.yml
index 1f4aa5d7..2cc365db 100644
--- a/test/integration/targets/command_shell/tasks/main.yml
+++ b/test/integration/targets/command_shell/tasks/main.yml
@@ -284,6 +284,30 @@
that:
- "command_result6.stdout == '9cd0697c6a9ff6689f0afb9136fa62e0b3fee903'"
+- name: check default var expansion
+ command: /bin/sh -c 'echo "\$TEST"'
+ environment:
+ TEST: z
+ register: command_result7
+
+- name: assert vars were expanded
+ assert:
+ that:
+ - command_result7.stdout == '\\z'
+
+- name: check disabled var expansion
+ command: /bin/sh -c 'echo "\$TEST"'
+ args:
+ expand_argument_vars: false
+ environment:
+ TEST: z
+ register: command_result8
+
+- name: assert vars were not expanded
+ assert:
+ that:
+ - command_result8.stdout == '$TEST'
+
##
## shell
##
@@ -546,3 +570,21 @@
- command_strip.stderr == 'hello \n '
- command_no_strip.stdout== 'hello \n \r\n'
- command_no_strip.stderr == 'hello \n \r\n'
+
+- name: run shell with expand_argument_vars
+ shell: echo 'hi'
+ args:
+ expand_argument_vars: false
+ register: shell_expand_failure
+ ignore_errors: true
+
+- name: assert shell with expand_arguments_vars failed
+ assert:
+ that:
+ - shell_expand_failure is failed
+ - "shell_expand_failure.msg == 'Unsupported parameters for (shell) module: expand_argument_vars'"
+
+- name: Run command that backgrounds, to ensure no hang
+ shell: '{{ role_path }}/scripts/yoink.sh &'
+ delegate_to: localhost
+ timeout: 5
diff --git a/test/integration/targets/conditionals/play.yml b/test/integration/targets/conditionals/play.yml
index 455818c9..56ec8438 100644
--- a/test/integration/targets/conditionals/play.yml
+++ b/test/integration/targets/conditionals/play.yml
@@ -665,3 +665,29 @@
- item
loop:
- 1 == 1
+
+ - set_fact:
+ sentinel_file: '{{ lookup("env", "OUTPUT_DIR")}}/LOOKUP_SIDE_EFFECT.txt'
+
+ - name: ensure sentinel file is absent
+ file:
+ path: '{{ sentinel_file }}'
+ state: absent
+ - name: get an untrusted var that's a valid Jinja expression with a side-effect
+ shell: |
+ echo "lookup('pipe', 'echo bang > \"$SENTINEL_FILE\" && cat \"$SENTINEL_FILE\"')"
+ environment:
+ SENTINEL_FILE: '{{ sentinel_file }}'
+ register: untrusted_expr
+ - name: use a conditional with an inline template that refers to the untrusted expression
+ debug:
+ msg: look at some seemingly innocuous stuff
+ when: '"foo" in {{ untrusted_expr.stdout }}'
+ ignore_errors: true
+ - name: ensure the untrusted expression side-effect has not executed
+ stat:
+ path: '{{ sentinel_file }}'
+ register: sentinel_stat
+ - assert:
+ that:
+ - not sentinel_stat.stat.exists
diff --git a/test/integration/targets/connection_delegation/aliases b/test/integration/targets/connection_delegation/aliases
index 6c965663..0ce76011 100644
--- a/test/integration/targets/connection_delegation/aliases
+++ b/test/integration/targets/connection_delegation/aliases
@@ -1,6 +1,5 @@
shippable/posix/group3
context/controller
skip/freebsd # No sshpass
-skip/osx # No sshpass
skip/macos # No sshpass
skip/rhel # No sshpass
diff --git a/test/integration/targets/connection_paramiko_ssh/test_connection.inventory b/test/integration/targets/connection_paramiko_ssh/test_connection.inventory
index a3f34ab7..cd17c090 100644
--- a/test/integration/targets/connection_paramiko_ssh/test_connection.inventory
+++ b/test/integration/targets/connection_paramiko_ssh/test_connection.inventory
@@ -2,6 +2,6 @@
paramiko_ssh-pipelining ansible_ssh_pipelining=true
paramiko_ssh-no-pipelining ansible_ssh_pipelining=false
[paramiko_ssh:vars]
-ansible_host=localhost
+ansible_host={{ 'localhost'|string }}
ansible_connection=paramiko_ssh
ansible_python_interpreter="{{ ansible_playbook_python }}"
diff --git a/test/integration/targets/connection_psrp/tests.yml b/test/integration/targets/connection_psrp/tests.yml
index dabbf407..08832b14 100644
--- a/test/integration/targets/connection_psrp/tests.yml
+++ b/test/integration/targets/connection_psrp/tests.yml
@@ -6,6 +6,9 @@
gather_facts: no
tasks:
+ - name: reboot the host
+ ansible.windows.win_reboot:
+
- name: test complex objects in raw output
# until PyYAML is upgraded to 4.x we need to use the \U escape for a unicode codepoint
# and enclose in a quote to it translates the \U
@@ -29,15 +32,8 @@
- raw_out.stdout_lines[4] == "winrm"
- raw_out.stdout_lines[5] == "string - \U0001F4A9"
- # Become only works on Server 2008 when running with basic auth, skip this host for now as it is too complicated to
- # override the auth protocol in the tests.
- - name: check if we running on Server 2008
- win_shell: '[System.Environment]::OSVersion.Version -ge [Version]"6.1"'
- register: os_version
-
- name: test out become with psrp
win_whoami:
- when: os_version|bool
register: whoami_out
become: yes
become_method: runas
@@ -47,7 +43,6 @@
assert:
that:
- whoami_out.account.sid == "S-1-5-18"
- when: os_version|bool
- name: test out async with psrp
win_shell: Start-Sleep -Seconds 2; Write-Output abc
diff --git a/test/integration/targets/connection_winrm/tests.yml b/test/integration/targets/connection_winrm/tests.yml
index 78f92a49..b086a3ad 100644
--- a/test/integration/targets/connection_winrm/tests.yml
+++ b/test/integration/targets/connection_winrm/tests.yml
@@ -6,6 +6,9 @@
gather_facts: no
tasks:
+ - name: reboot the host
+ ansible.windows.win_reboot:
+
- name: setup remote tmp dir
import_role:
name: ../../setup_remote_tmp_dir
diff --git a/test/integration/targets/copy/tasks/main.yml b/test/integration/targets/copy/tasks/main.yml
index b86c56ac..601312fa 100644
--- a/test/integration/targets/copy/tasks/main.yml
+++ b/test/integration/targets/copy/tasks/main.yml
@@ -84,6 +84,7 @@
- import_tasks: check_mode.yml
# https://github.com/ansible/ansible/issues/57618
+ # https://github.com/ansible/ansible/issues/79749
- name: Test diff contents
copy:
content: 'Ansible managed\n'
@@ -95,6 +96,7 @@
that:
- 'diff_output.diff[0].before == ""'
- '"Ansible managed" in diff_output.diff[0].after'
+ - '"file.txt" in diff_output.diff[0].after_header'
- name: tests with remote_src and non files
import_tasks: src_remote_file_is_not_file.yml
diff --git a/test/integration/targets/copy/tasks/tests.yml b/test/integration/targets/copy/tasks/tests.yml
index d6c8e63c..40ea9de3 100644
--- a/test/integration/targets/copy/tasks/tests.yml
+++ b/test/integration/targets/copy/tasks/tests.yml
@@ -420,6 +420,80 @@
- "stat_results2.stat.mode == '0547'"
#
+# test copying an empty dir to a dest dir with remote_src=True
+#
+
+- name: create empty test dir
+ file:
+ path: '{{ remote_dir }}/testcase_empty_dir'
+ state: directory
+
+- name: test copying an empty dir to a dir that does not exist (dest ends with slash)
+ copy:
+ src: '{{ remote_dir }}/testcase_empty_dir/'
+ remote_src: yes
+ dest: '{{ remote_dir }}/testcase_empty_dir_dest/'
+ register: copy_result
+
+- name: get stat of newly created dir
+ stat:
+ path: '{{ remote_dir }}/testcase_empty_dir_dest'
+ register: stat_result
+
+- assert:
+ that:
+ - copy_result.changed
+ - stat_result.stat.exists
+ - stat_result.stat.isdir
+
+- name: test no change is made running the task twice
+ copy:
+ src: '{{ remote_dir }}/testcase_empty_dir/'
+ remote_src: yes
+ dest: '{{ remote_dir }}/testcase_empty_dir_dest/'
+ register: copy_result
+ failed_when: copy_result is changed
+
+- name: remove to test dest with no trailing slash
+ file:
+ path: '{{ remote_dir }}/testcase_empty_dir_dest/'
+ state: absent
+
+- name: test copying an empty dir to a dir that does not exist (both src/dest have no trailing slash)
+ copy:
+ src: '{{ remote_dir }}/testcase_empty_dir'
+ remote_src: yes
+ dest: '{{ remote_dir }}/testcase_empty_dir_dest'
+ register: copy_result
+
+- name: get stat of newly created dir
+ stat:
+ path: '{{ remote_dir }}/testcase_empty_dir_dest'
+ register: stat_result
+
+- assert:
+ that:
+ - copy_result.changed
+ - stat_result.stat.exists
+ - stat_result.stat.isdir
+
+- name: test no change is made running the task twice
+ copy:
+ src: '{{ remote_dir }}/testcase_empty_dir/'
+ remote_src: yes
+ dest: '{{ remote_dir }}/testcase_empty_dir_dest/'
+ register: copy_result
+ failed_when: copy_result is changed
+
+- name: clean up src and dest
+ file:
+ path: "{{ item }}"
+ state: absent
+ loop:
+ - '{{ remote_dir }}/testcase_empty_dir'
+ - '{{ remote_dir }}/testcase_empty_dir_dest'
+
+#
# test recursive copy local_follow=False, no trailing slash
#
@@ -2284,3 +2358,81 @@
that:
- fail_copy_directory_with_enc_file is failed
- fail_copy_directory_with_enc_file.msg == 'A vault password or secret must be specified to decrypt {{role_path}}/files-different/vault/vault-file'
+
+#
+# Test for issue 74536: recursively copy all nested directories with remote_src=yes and src='dir/' when dest exists
+#
+- vars:
+ src: '{{ remote_dir }}/testcase_74536'
+ block:
+ - name: create source dir with 3 nested subdirs
+ file:
+ path: '{{ src }}/a/b1/c1'
+ state: directory
+
+ - name: copy the source dir with a trailing slash
+ copy:
+ src: '{{ src }}/'
+ remote_src: yes
+ dest: '{{ src }}_dest/'
+ register: copy_result
+ failed_when: copy_result is not changed
+
+ - name: remove the source dir to recreate with different subdirs
+ file:
+ path: '{{ src }}'
+ state: absent
+
+ - name: recreate source dir
+ file:
+ path: "{{ item }}"
+ state: directory
+ loop:
+ - '{{ src }}/a/b1/c2'
+ - '{{ src }}/a/b2/c3'
+
+ - name: copy the source dir containing new subdirs into the existing dest dir
+ copy:
+ src: '{{ src }}/'
+ remote_src: yes
+ dest: '{{ src }}_dest/'
+ register: copy_result
+
+ - name: stat each directory that should exist
+ stat:
+ path: '{{ item }}'
+ register: stat_result
+ loop:
+ - '{{ src }}_dest'
+ - '{{ src }}_dest/a'
+ - '{{ src }}_dest/a/b1'
+ - '{{ src }}_dest/a/b2'
+ - '{{ src }}_dest/a/b1/c1'
+ - '{{ src }}_dest/a/b1/c2'
+ - '{{ src }}_dest/a/b2/c3'
+
+ - debug: msg="{{ stat_result }}"
+
+ - assert:
+ that:
+ - copy_result is changed
+ # all paths exist
+ - stat_result.results | map(attribute='stat') | map(attribute='exists') | unique == [true]
+ # all paths are dirs
+ - stat_result.results | map(attribute='stat') | map(attribute='isdir') | unique == [true]
+
+ - name: copy the src again to verify no changes will be made
+ copy:
+ src: '{{ src }}/'
+ remote_src: yes
+ dest: '{{ src }}_dest/'
+ register: copy_result
+ failed_when: copy_result is changed
+
+ - name: clean up src and dest
+ file:
+ path: '{{ item }}'
+ state: absent
+ loop:
+ - '{{ src }}'
+ - '{{ src }}_dest'
diff --git a/test/integration/targets/cron/aliases b/test/integration/targets/cron/aliases
index f2f9ac9d..f3703f85 100644
--- a/test/integration/targets/cron/aliases
+++ b/test/integration/targets/cron/aliases
@@ -1,4 +1,3 @@
destructive
shippable/posix/group1
-skip/osx
skip/macos
diff --git a/test/integration/targets/debconf/tasks/main.yml b/test/integration/targets/debconf/tasks/main.yml
index d3d63cdf..f9236268 100644
--- a/test/integration/targets/debconf/tasks/main.yml
+++ b/test/integration/targets/debconf/tasks/main.yml
@@ -33,4 +33,44 @@
- 'debconf_test0.current is defined'
- '"tzdata/Zones/Etc" in debconf_test0.current'
- 'debconf_test0.current["tzdata/Zones/Etc"] == "UTC"'
- when: ansible_distribution in ('Ubuntu', 'Debian')
+
+ - name: install debconf-utils
+ apt:
+ name: debconf-utils
+ state: present
+ register: debconf_utils_deb_install
+
+ - name: Check if password is set
+ debconf:
+ name: ddclient
+ question: ddclient/password
+ value: "MySecretValue"
+ vtype: password
+ register: debconf_test1
+
+ - name: validate results for test 1
+ assert:
+ that:
+ - debconf_test1.changed
+
+ - name: Change password again
+ debconf:
+ name: ddclient
+ question: ddclient/password
+ value: "MySecretValue"
+ vtype: password
+ no_log: yes
+ register: debconf_test2
+
+ - name: validate results for test 1
+ assert:
+ that:
+ - not debconf_test2.changed
+ always:
+ - name: uninstall debconf-utils
+ apt:
+ name: debconf-utils
+ state: absent
+ when: debconf_utils_deb_install is changed
+
+ when: ansible_distribution in ('Ubuntu', 'Debian') \ No newline at end of file
diff --git a/test/integration/targets/delegate_to/delegate_local_from_root.yml b/test/integration/targets/delegate_to/delegate_local_from_root.yml
index c9be4ff2..b44f83bd 100644
--- a/test/integration/targets/delegate_to/delegate_local_from_root.yml
+++ b/test/integration/targets/delegate_to/delegate_local_from_root.yml
@@ -3,7 +3,7 @@
gather_facts: false
remote_user: root
tasks:
- - name: ensure we copy w/o errors due to remote user not being overriden
+ - name: ensure we copy w/o errors due to remote user not being overridden
copy:
src: testfile
dest: "{{ playbook_dir }}"
diff --git a/test/integration/targets/delegate_to/runme.sh b/test/integration/targets/delegate_to/runme.sh
index 1bdf27cf..e0dcc746 100755
--- a/test/integration/targets/delegate_to/runme.sh
+++ b/test/integration/targets/delegate_to/runme.sh
@@ -76,3 +76,7 @@ ansible-playbook test_delegate_to_lookup_context.yml -i inventory -v "$@"
ansible-playbook delegate_local_from_root.yml -i inventory -v "$@" -e 'ansible_user=root'
ansible-playbook delegate_with_fact_from_delegate_host.yml "$@"
ansible-playbook delegate_facts_loop.yml -i inventory -v "$@"
+ansible-playbook test_random_delegate_to_with_loop.yml -i inventory -v "$@"
+
+# Run playbook multiple times to ensure there are no false-negatives
+for i in $(seq 0 10); do ansible-playbook test_random_delegate_to_without_loop.yml -i inventory -v "$@"; done;
diff --git a/test/integration/targets/delegate_to/test_delegate_to.yml b/test/integration/targets/delegate_to/test_delegate_to.yml
index dcfa9d03..eb601e02 100644
--- a/test/integration/targets/delegate_to/test_delegate_to.yml
+++ b/test/integration/targets/delegate_to/test_delegate_to.yml
@@ -1,9 +1,9 @@
- hosts: testhost3
vars:
- - template_role: ./roles/test_template
- - output_dir: "{{ playbook_dir }}"
- - templated_var: foo
- - templated_dict: { 'hello': 'world' }
+ template_role: ./roles/test_template
+ output_dir: "{{ playbook_dir }}"
+ templated_var: foo
+ templated_dict: { 'hello': 'world' }
tasks:
- name: Test no delegate_to
setup:
@@ -57,6 +57,25 @@
- name: remove test file
file: path={{ output_dir }}/tmp.txt state=absent
+ - name: Use omit to thwart delegation
+ ping:
+ delegate_to: "{{ jenkins_install_key_on|default(omit) }}"
+ register: d_omitted
+
+ - name: Use empty to thwart delegation should fail
+ ping:
+ delegate_to: "{{ jenkins_install_key_on }}"
+ when: jenkins_install_key_on != ""
+ vars:
+ jenkins_install_key_on: ''
+ ignore_errors: true
+ register: d_empty
+
+ - name: Ensure previous 2 tests actually did what was expected
+ assert:
+ that:
+ - d_omitted is success
+ - d_empty is failed
- name: verify delegation with per host vars
hosts: testhost6
diff --git a/test/integration/targets/dnf/aliases b/test/integration/targets/dnf/aliases
index d6f27b8e..b12f3547 100644
--- a/test/integration/targets/dnf/aliases
+++ b/test/integration/targets/dnf/aliases
@@ -1,6 +1,4 @@
destructive
shippable/posix/group1
-skip/power/centos
skip/freebsd
-skip/osx
skip/macos
diff --git a/test/integration/targets/dnf/tasks/dnf.yml b/test/integration/targets/dnf/tasks/dnf.yml
index ec1c36f8..9845f3db 100644
--- a/test/integration/targets/dnf/tasks/dnf.yml
+++ b/test/integration/targets/dnf/tasks/dnf.yml
@@ -224,7 +224,7 @@
- assert:
that:
- dnf_result is success
- - dnf_result.results|length == 2
+ - dnf_result.results|length >= 2
- "dnf_result.results[0].startswith('Removed: ')"
- "dnf_result.results[1].startswith('Removed: ')"
@@ -427,6 +427,10 @@
- shell: 'dnf -y group install "Custom Group" && dnf -y group remove "Custom Group"'
register: shell_dnf_result
+- dnf:
+ name: "@Custom Group"
+ state: absent
+
# GROUP UPGRADE - this will go to the same method as group install
# but through group_update - it is its invocation we're testing here
# see commit 119c9e5d6eb572c4a4800fbe8136095f9063c37b
@@ -446,6 +450,10 @@
# cleanup until https://github.com/ansible/ansible/issues/27377 is resolved
- shell: dnf -y group install "Custom Group" && dnf -y group remove "Custom Group"
+- dnf:
+ name: "@Custom Group"
+ state: absent
+
- name: try to install non existing group
dnf:
name: "@non-existing-group"
@@ -551,30 +559,35 @@
- "'No package non-existent-rpm available' in dnf_result['failures'][0]"
- "'Failed to install some of the specified packages' in dnf_result['msg']"
-- name: use latest to install httpd
+- name: ensure sos isn't installed
dnf:
- name: httpd
+ name: sos
+ state: absent
+
+- name: use latest to install sos
+ dnf:
+ name: sos
state: latest
register: dnf_result
-- name: verify httpd was installed
+- name: verify sos was installed
assert:
that:
- - "'changed' in dnf_result"
+ - dnf_result is changed
-- name: uninstall httpd
+- name: uninstall sos
dnf:
- name: httpd
+ name: sos
state: removed
-- name: update httpd only if it exists
+- name: update sos only if it exists
dnf:
- name: httpd
+ name: sos
state: latest
update_only: yes
register: dnf_result
-- name: verify httpd not installed
+- name: verify sos not installed
assert:
that:
- "not dnf_result is changed"
@@ -655,6 +668,28 @@
- "'changed' in dnf_result"
- "'results' in dnf_result"
+# Install RPM from url with update_only
+- name: install from url with update_only
+ dnf:
+ name: "file://{{ pkg_path }}"
+ state: latest
+ update_only: true
+ disable_gpg_check: true
+ register: dnf_result
+
+- name: verify installation
+ assert:
+ that:
+ - "dnf_result is success"
+ - "not dnf_result is changed"
+ - "dnf_result is not failed"
+
+- name: verify dnf module outputs
+ assert:
+ that:
+ - "'changed' in dnf_result"
+ - "'results' in dnf_result"
+
- name: Create a temp RPM file which does not contain nevra information
file:
name: "/tmp/non_existent_pkg.rpm"
diff --git a/test/integration/targets/dnf/tasks/main.yml b/test/integration/targets/dnf/tasks/main.yml
index 65b77ceb..4941e2c3 100644
--- a/test/integration/targets/dnf/tasks/main.yml
+++ b/test/integration/targets/dnf/tasks/main.yml
@@ -61,6 +61,7 @@
when:
- (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('29', '>=')) or
(ansible_distribution in ['RedHat', 'CentOS'] and ansible_distribution_major_version is version('8', '>='))
+ - not dnf5|default(false)
tags:
- dnf_modularity
@@ -69,5 +70,6 @@
(ansible_distribution in ['RedHat', 'CentOS'] and ansible_distribution_major_version is version('8', '>='))
- include_tasks: cacheonly.yml
- when: (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('23', '>=')) or
- (ansible_distribution in ['RedHat', 'CentOS'] and ansible_distribution_major_version is version('8', '>='))
+ when:
+ - (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('23', '>=')) or
+ (ansible_distribution in ['RedHat', 'CentOS'] and ansible_distribution_major_version is version('8', '>='))
diff --git a/test/integration/targets/dnf/tasks/skip_broken_and_nobest.yml b/test/integration/targets/dnf/tasks/skip_broken_and_nobest.yml
index 503cb4c3..f54c0a83 100644
--- a/test/integration/targets/dnf/tasks/skip_broken_and_nobest.yml
+++ b/test/integration/targets/dnf/tasks/skip_broken_and_nobest.yml
@@ -240,7 +240,8 @@
- name: Do an "upgrade" to an older version of broken-a, allow_downgrade=false
dnf:
name:
- - broken-a-1.2.3-1*
+ #- broken-a-1.2.3-1*
+ - broken-a-1.2.3-1.el7.x86_64
state: latest
allow_downgrade: false
check_mode: true
diff --git a/test/integration/targets/dnf/tasks/test_sos_removal.yml b/test/integration/targets/dnf/tasks/test_sos_removal.yml
index 0d70cf78..5e161dbb 100644
--- a/test/integration/targets/dnf/tasks/test_sos_removal.yml
+++ b/test/integration/targets/dnf/tasks/test_sos_removal.yml
@@ -15,5 +15,5 @@
that:
- sos_rm is successful
- sos_rm is changed
- - "'Removed: sos-' ~ sos_version ~ '-' ~ sos_release in sos_rm.results[0]"
- - sos_rm.results|length == 1
+ - sos_rm.results|select("contains", "Removed: sos-{{ sos_version }}-{{ sos_release }}")|length > 0
+ - sos_rm.results|length > 0
diff --git a/test/integration/targets/dpkg_selections/aliases b/test/integration/targets/dpkg_selections/aliases
index c0d5684b..9c44d752 100644
--- a/test/integration/targets/dpkg_selections/aliases
+++ b/test/integration/targets/dpkg_selections/aliases
@@ -1,6 +1,5 @@
shippable/posix/group1
destructive
skip/freebsd
-skip/osx
skip/macos
skip/rhel
diff --git a/test/integration/targets/dpkg_selections/tasks/dpkg_selections.yaml b/test/integration/targets/dpkg_selections/tasks/dpkg_selections.yaml
index 080db262..016d7716 100644
--- a/test/integration/targets/dpkg_selections/tasks/dpkg_selections.yaml
+++ b/test/integration/targets/dpkg_selections/tasks/dpkg_selections.yaml
@@ -87,3 +87,15 @@
apt:
name: hello
state: absent
+
+- name: Try to select non-existent package
+ dpkg_selections:
+ name: kernel
+ selection: hold
+ ignore_errors: yes
+ register: result
+
+- name: Check that module fails for non-existent package
+ assert:
+ that:
+ - "'Failed to find package' in result.msg"
diff --git a/test/integration/targets/egg-info/lookup_plugins/import_pkg_resources.py b/test/integration/targets/egg-info/lookup_plugins/import_pkg_resources.py
index c0c5ccd5..28227fce 100644
--- a/test/integration/targets/egg-info/lookup_plugins/import_pkg_resources.py
+++ b/test/integration/targets/egg-info/lookup_plugins/import_pkg_resources.py
@@ -1,7 +1,7 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-import pkg_resources
+import pkg_resources # pylint: disable=unused-import
from ansible.plugins.lookup import LookupBase
diff --git a/test/integration/targets/environment/test_environment.yml b/test/integration/targets/environment/test_environment.yml
index 43f9c74e..f295cf3c 100644
--- a/test/integration/targets/environment/test_environment.yml
+++ b/test/integration/targets/environment/test_environment.yml
@@ -7,8 +7,8 @@
- hosts: testhost
vars:
- - test1:
- key1: val1
+ test1:
+ key1: val1
environment:
PATH: '{{ansible_env.PATH + ":/lola"}}'
lola: 'ido'
@@ -41,9 +41,9 @@
- hosts: testhost
vars:
- - test1:
- key1: val1
- - test2:
+ test1:
+ key1: val1
+ test2:
key1: not1
other1: val2
environment: "{{test1}}"
diff --git a/test/integration/targets/error_from_connection/connection_plugins/dummy.py b/test/integration/targets/error_from_connection/connection_plugins/dummy.py
index 59a81a1b..d322fe0d 100644
--- a/test/integration/targets/error_from_connection/connection_plugins/dummy.py
+++ b/test/integration/targets/error_from_connection/connection_plugins/dummy.py
@@ -11,7 +11,6 @@ DOCUMENTATION = """
version_added: "2.0"
options: {}
"""
-import ansible.constants as C
from ansible.errors import AnsibleError
from ansible.plugins.connection import ConnectionBase
diff --git a/test/integration/targets/expect/tasks/main.yml b/test/integration/targets/expect/tasks/main.yml
index 7bf18c5e..2aef5957 100644
--- a/test/integration/targets/expect/tasks/main.yml
+++ b/test/integration/targets/expect/tasks/main.yml
@@ -148,6 +148,15 @@
- "echo_result.stdout_lines[-2] == 'foobar'"
- "echo_result.stdout_lines[-1] == 'bar'"
+- name: test timeout is valid as null
+ expect:
+ command: "{{ansible_python_interpreter}} {{test_command_file}}"
+ responses:
+ foo: bar
+ echo: true
+ timeout: null # wait indefinitely
+ timeout: 2 # but shouldn't be waiting long
+
- name: test response list
expect:
command: "{{ansible_python_interpreter}} {{test_command_file}} foo foo"
diff --git a/test/integration/targets/facts_linux_network/aliases b/test/integration/targets/facts_linux_network/aliases
index 100ce23a..c9e1dc55 100644
--- a/test/integration/targets/facts_linux_network/aliases
+++ b/test/integration/targets/facts_linux_network/aliases
@@ -1,7 +1,6 @@
needs/privileged
shippable/posix/group1
skip/freebsd
-skip/osx
skip/macos
context/target
destructive
diff --git a/test/integration/targets/fetch/roles/fetch_tests/tasks/failures.yml b/test/integration/targets/fetch/roles/fetch_tests/tasks/failures.yml
index 8a6b5b7b..d0bf9bdc 100644
--- a/test/integration/targets/fetch/roles/fetch_tests/tasks/failures.yml
+++ b/test/integration/targets/fetch/roles/fetch_tests/tasks/failures.yml
@@ -28,6 +28,15 @@
register: failed_fetch_dest_dir
ignore_errors: true
+- name: Test unreachable
+ fetch:
+ src: "{{ remote_tmp_dir }}/orig"
+ dest: "{{ output_dir }}"
+ register: unreachable_fetch
+ ignore_unreachable: true
+ vars:
+ ansible_user: wrong
+
- name: Ensure fetch failed
assert:
that:
@@ -39,3 +48,4 @@
- failed_fetch_no_access.msg is search('file is not readable')
- failed_fetch_dest_dir is failed
- failed_fetch_dest_dir.msg is search('dest is an existing directory')
+ - unreachable_fetch is unreachable
diff --git a/test/integration/targets/file/tasks/link_rewrite.yml b/test/integration/targets/file/tasks/link_rewrite.yml
index b0e1af3e..2416c2ca 100644
--- a/test/integration/targets/file/tasks/link_rewrite.yml
+++ b/test/integration/targets/file/tasks/link_rewrite.yml
@@ -16,11 +16,11 @@
dest: "{{ tempdir.path }}/somelink"
state: link
-- stat:
+- stat:
path: "{{ tempdir.path }}/somelink"
register: link
-- stat:
+- stat:
path: "{{ tempdir.path }}/somefile"
register: file
@@ -32,12 +32,12 @@
- file:
path: "{{ tempdir.path }}/somelink"
mode: 0644
-
-- stat:
+
+- stat:
path: "{{ tempdir.path }}/somelink"
register: link
-- stat:
+- stat:
path: "{{ tempdir.path }}/somefile"
register: file
diff --git a/test/integration/targets/file/tasks/main.yml b/test/integration/targets/file/tasks/main.yml
index a5bd68d7..c1b4c791 100644
--- a/test/integration/targets/file/tasks/main.yml
+++ b/test/integration/targets/file/tasks/main.yml
@@ -779,7 +779,7 @@
register: touch_result_in_check_mode_fails_not_existing_group
- assert:
- that:
+ that:
- touch_result_in_check_mode_not_existing.changed
- touch_result_in_check_mode_preserve_access_time.changed
- touch_result_in_check_mode_change_only_mode.changed
diff --git a/test/integration/targets/filter_core/tasks/main.yml b/test/integration/targets/filter_core/tasks/main.yml
index 2d084191..9d287a18 100644
--- a/test/integration/targets/filter_core/tasks/main.yml
+++ b/test/integration/targets/filter_core/tasks/main.yml
@@ -454,6 +454,38 @@
- password_hash_2 is failed
- "'not support' in password_hash_2.msg"
+- name: install passlib if needed
+ pip:
+ name: passlib
+ state: present
+ register: installed_passlib
+
+- name: test using passlib with an unsupported hash type
+ set_fact:
+ foo: '{{"hey"|password_hash("msdcc")}}'
+ ignore_errors: yes
+ register: unsupported_hash_type
+
+- name: remove passlib if it was installed
+ pip:
+ name: passlib
+ state: absent
+ when: installed_passlib.changed
+
+- assert:
+ that:
+ - unsupported_hash_type.msg == msg
+ vars:
+ msg: "msdcc is not in the list of supported passlib algorithms: md5, blowfish, sha256, sha512"
+
+- name: test password_hash can work with bcrypt without passlib installed
+ debug:
+ msg: "{{ 'somestring'|password_hash('bcrypt') }}"
+ register: crypt_bcrypt
+ # Some implementations of crypt do not fail outright and return some short value.
+ failed_when: crypt_bcrypt is failed or (crypt_bcrypt.msg|length|int) != 60
+ when: ansible_facts.os_family in ['RedHat', 'Debian']
+
- name: Verify to_uuid throws on weird namespace
set_fact:
foo: '{{"hey"|to_uuid(namespace=22)}}'
diff --git a/test/integration/targets/filter_encryption/base.yml b/test/integration/targets/filter_encryption/base.yml
index 8bf25f77..1479f734 100644
--- a/test/integration/targets/filter_encryption/base.yml
+++ b/test/integration/targets/filter_encryption/base.yml
@@ -2,6 +2,7 @@
gather_facts: true
vars:
data: secret
+ data2: 'foo: bar\n'
dvault: '{{ "secret"|vault("test")}}'
password: test
s_32: '{{(2**31-1)}}'
@@ -21,6 +22,15 @@
is_64: '{{ "64" in ansible_facts["architecture"] }}'
salt: '{{ is_64|bool|ternary(s_64, s_32)|random(seed=inventory_hostname)}}'
vaultedstring: '{{ is_64|bool|ternary(vaultedstring_64, vaultedstring_32) }}'
+ # command line vaulted data2
+ vaulted_id: !vault |
+ $ANSIBLE_VAULT;1.2;AES256;test1
+ 36383733336533656264393332663131613335333332346439356164383935656234663631356430
+ 3533353537343834333538356366376233326364613362640a623832636339363966336238393039
+ 35316562626335306534356162623030613566306235623863373036626531346364626166656134
+ 3063376436656635330a363636376131663362633731313964353061663661376638326461393736
+ 3863
+ vaulted_to_id: "{{data2|vault('test1@secret', vault_id='test1')}}"
tasks:
- name: check vaulting
@@ -35,3 +45,5 @@
that:
- vaultedstring|unvault(password) == data
- vault|unvault(password) == data
+ - vaulted_id|unvault('test1@secret', vault_id='test1')
+ - vaulted_to_id|unvault('test1@secret', vault_id='test1')
diff --git a/test/integration/targets/filter_mathstuff/tasks/main.yml b/test/integration/targets/filter_mathstuff/tasks/main.yml
index 019f00e4..33fcae82 100644
--- a/test/integration/targets/filter_mathstuff/tasks/main.yml
+++ b/test/integration/targets/filter_mathstuff/tasks/main.yml
@@ -64,44 +64,44 @@
that:
- '[1,2,3]|intersect([4,5,6]) == []'
- '[1,2,3]|intersect([3,4,5,6]) == [3]'
- - '[1,2,3]|intersect([3,2,1]) == [1,2,3]'
- - '(1,2,3)|intersect((4,5,6))|list == []'
- - '(1,2,3)|intersect((3,4,5,6))|list == [3]'
+ - '[1,2,3]|intersect([3,2,1]) | sort == [1,2,3]'
+ - '(1,2,3)|intersect((4,5,6)) == []'
+ - '(1,2,3)|intersect((3,4,5,6)) == [3]'
- '["a","A","b"]|intersect(["B","c","C"]) == []'
- '["a","A","b"]|intersect(["b","B","c","C"]) == ["b"]'
- - '["a","A","b"]|intersect(["b","A","a"]) == ["a","A","b"]'
- - '("a","A","b")|intersect(("B","c","C"))|list == []'
- - '("a","A","b")|intersect(("b","B","c","C"))|list == ["b"]'
+ - '["a","A","b"]|intersect(["b","A","a"]) | sort(case_sensitive=True) == ["A","a","b"]'
+ - '("a","A","b")|intersect(("B","c","C")) == []'
+ - '("a","A","b")|intersect(("b","B","c","C")) == ["b"]'
- name: Verify difference
tags: difference
assert:
that:
- - '[1,2,3]|difference([4,5,6]) == [1,2,3]'
- - '[1,2,3]|difference([3,4,5,6]) == [1,2]'
+ - '[1,2,3]|difference([4,5,6]) | sort == [1,2,3]'
+ - '[1,2,3]|difference([3,4,5,6]) | sort == [1,2]'
- '[1,2,3]|difference([3,2,1]) == []'
- - '(1,2,3)|difference((4,5,6))|list == [1,2,3]'
- - '(1,2,3)|difference((3,4,5,6))|list == [1,2]'
- - '["a","A","b"]|difference(["B","c","C"]) == ["a","A","b"]'
- - '["a","A","b"]|difference(["b","B","c","C"]) == ["a","A"]'
+ - '(1,2,3)|difference((4,5,6)) | sort == [1,2,3]'
+ - '(1,2,3)|difference((3,4,5,6)) | sort == [1,2]'
+ - '["a","A","b"]|difference(["B","c","C"]) | sort(case_sensitive=True) == ["A","a","b"]'
+ - '["a","A","b"]|difference(["b","B","c","C"]) | sort(case_sensitive=True) == ["A","a"]'
- '["a","A","b"]|difference(["b","A","a"]) == []'
- - '("a","A","b")|difference(("B","c","C"))|list|sort(case_sensitive=True) == ["A","a","b"]'
- - '("a","A","b")|difference(("b","B","c","C"))|list|sort(case_sensitive=True) == ["A","a"]'
+ - '("a","A","b")|difference(("B","c","C")) | sort(case_sensitive=True) == ["A","a","b"]'
+ - '("a","A","b")|difference(("b","B","c","C")) | sort(case_sensitive=True) == ["A","a"]'
- name: Verify symmetric_difference
tags: symmetric_difference
assert:
that:
- - '[1,2,3]|symmetric_difference([4,5,6]) == [1,2,3,4,5,6]'
- - '[1,2,3]|symmetric_difference([3,4,5,6]) == [1,2,4,5,6]'
+ - '[1,2,3]|symmetric_difference([4,5,6]) | sort == [1,2,3,4,5,6]'
+ - '[1,2,3]|symmetric_difference([3,4,5,6]) | sort == [1,2,4,5,6]'
- '[1,2,3]|symmetric_difference([3,2,1]) == []'
- - '(1,2,3)|symmetric_difference((4,5,6))|list == [1,2,3,4,5,6]'
- - '(1,2,3)|symmetric_difference((3,4,5,6))|list == [1,2,4,5,6]'
- - '["a","A","b"]|symmetric_difference(["B","c","C"]) == ["a","A","b","B","c","C"]'
- - '["a","A","b"]|symmetric_difference(["b","B","c","C"]) == ["a","A","B","c","C"]'
+ - '(1,2,3)|symmetric_difference((4,5,6)) | sort == [1,2,3,4,5,6]'
+ - '(1,2,3)|symmetric_difference((3,4,5,6)) | sort == [1,2,4,5,6]'
+ - '["a","A","b"]|symmetric_difference(["B","c","C"]) | sort(case_sensitive=True) == ["A","B","C","a","b","c"]'
+ - '["a","A","b"]|symmetric_difference(["b","B","c","C"]) | sort(case_sensitive=True) == ["A","B","C","a","c"]'
- '["a","A","b"]|symmetric_difference(["b","A","a"]) == []'
- - '("a","A","b")|symmetric_difference(("B","c","C"))|list|sort(case_sensitive=True) == ["A","B","C","a","b","c"]'
- - '("a","A","b")|symmetric_difference(("b","B","c","C"))|list|sort(case_sensitive=True) == ["A","B","C","a","c"]'
+ - '("a","A","b")|symmetric_difference(("B","c","C")) | sort(case_sensitive=True) == ["A","B","C","a","b","c"]'
+ - '("a","A","b")|symmetric_difference(("b","B","c","C")) | sort(case_sensitive=True) == ["A","B","C","a","c"]'
- name: Verify union
tags: union
@@ -112,11 +112,11 @@
- '[1,2,3]|union([3,2,1]) == [1,2,3]'
- '(1,2,3)|union((4,5,6))|list == [1,2,3,4,5,6]'
- '(1,2,3)|union((3,4,5,6))|list == [1,2,3,4,5,6]'
- - '["a","A","b"]|union(["B","c","C"]) == ["a","A","b","B","c","C"]'
- - '["a","A","b"]|union(["b","B","c","C"]) == ["a","A","b","B","c","C"]'
- - '["a","A","b"]|union(["b","A","a"]) == ["a","A","b"]'
- - '("a","A","b")|union(("B","c","C"))|list|sort(case_sensitive=True) == ["A","B","C","a","b","c"]'
- - '("a","A","b")|union(("b","B","c","C"))|list|sort(case_sensitive=True) == ["A","B","C","a","b","c"]'
+ - '["a","A","b"]|union(["B","c","C"]) | sort(case_sensitive=True) == ["A","B","C","a","b","c"]'
+ - '["a","A","b"]|union(["b","B","c","C"]) | sort(case_sensitive=True) == ["A","B","C","a","b","c"]'
+ - '["a","A","b"]|union(["b","A","a"]) | sort(case_sensitive=True) == ["A","a","b"]'
+ - '("a","A","b")|union(("B","c","C")) | sort(case_sensitive=True) == ["A","B","C","a","b","c"]'
+ - '("a","A","b")|union(("b","B","c","C")) | sort(case_sensitive=True) == ["A","B","C","a","b","c"]'
- name: Verify min
tags: min
diff --git a/test/integration/targets/find/tasks/main.yml b/test/integration/targets/find/tasks/main.yml
index 89c62b9b..9c4a960f 100644
--- a/test/integration/targets/find/tasks/main.yml
+++ b/test/integration/targets/find/tasks/main.yml
@@ -374,3 +374,6 @@
- 'remote_tmp_dir_test ~ "/astest/old.txt" in astest_list'
- 'remote_tmp_dir_test ~ "/astest/.hidden.txt" in astest_list'
- '"checksum" in result.files[0]'
+
+- name: Run mode tests
+ import_tasks: mode.yml
diff --git a/test/integration/targets/fork_safe_stdio/aliases b/test/integration/targets/fork_safe_stdio/aliases
index e968db72..7761837e 100644
--- a/test/integration/targets/fork_safe_stdio/aliases
+++ b/test/integration/targets/fork_safe_stdio/aliases
@@ -1,3 +1,3 @@
shippable/posix/group3
context/controller
-skip/macos
+needs/target/test_utils
diff --git a/test/integration/targets/fork_safe_stdio/runme.sh b/test/integration/targets/fork_safe_stdio/runme.sh
index 4438c3fe..863582f3 100755
--- a/test/integration/targets/fork_safe_stdio/runme.sh
+++ b/test/integration/targets/fork_safe_stdio/runme.sh
@@ -7,7 +7,7 @@ echo "testing for stdio deadlock on forked workers (10s timeout)..."
# Enable a callback that trips deadlocks on forked-child stdout, time out after 10s; forces running
# in a pty, since that tends to be much slower than raw file I/O and thus more likely to trigger the deadlock.
# Redirect stdout to /dev/null since it's full of non-printable garbage we don't want to display unless it failed
-ANSIBLE_CALLBACKS_ENABLED=spewstdio SPEWSTDIO_ENABLED=1 python run-with-pty.py timeout 10s ansible-playbook -i hosts -f 5 test.yml > stdout.txt && RC=$? || RC=$?
+ANSIBLE_CALLBACKS_ENABLED=spewstdio SPEWSTDIO_ENABLED=1 python run-with-pty.py ../test_utils/scripts/timeout.py -- 10 ansible-playbook -i hosts -f 5 test.yml > stdout.txt && RC=$? || RC=$?
if [ $RC != 0 ]; then
echo "failed; likely stdout deadlock. dumping raw output (may be very large)"
diff --git a/test/integration/targets/gathering_facts/library/file_utils.py b/test/integration/targets/gathering_facts/library/file_utils.py
index 58538029..38fa9265 100644
--- a/test/integration/targets/gathering_facts/library/file_utils.py
+++ b/test/integration/targets/gathering_facts/library/file_utils.py
@@ -1,9 +1,6 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-import json
-import sys
-
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.facts.utils import (
get_file_content,
diff --git a/test/integration/targets/gathering_facts/runme.sh b/test/integration/targets/gathering_facts/runme.sh
index c1df560c..a90de0f0 100755
--- a/test/integration/targets/gathering_facts/runme.sh
+++ b/test/integration/targets/gathering_facts/runme.sh
@@ -25,3 +25,17 @@ ansible-playbook test_module_defaults.yml "$@" --tags default_fact_module
ANSIBLE_FACTS_MODULES='ansible.legacy.setup' ansible-playbook test_module_defaults.yml "$@" --tags custom_fact_module
ansible-playbook test_module_defaults.yml "$@" --tags networking
+
+# test it works by default
+ANSIBLE_FACTS_MODULES='ansible.legacy.slow' ansible -m gather_facts localhost --playbook-dir ./ "$@"
+
+# test that gather_facts will timeout parallel modules that dont support gather_timeout when using gather_Timeout
+ANSIBLE_FACTS_MODULES='ansible.legacy.slow' ansible -m gather_facts localhost --playbook-dir ./ -a 'gather_timeout=1 parallel=true' "$@" 2>&1 |grep 'Timeout exceeded'
+
+# test that gather_facts parallel w/o timing out
+ANSIBLE_FACTS_MODULES='ansible.legacy.slow' ansible -m gather_facts localhost --playbook-dir ./ -a 'gather_timeout=30 parallel=true' "$@" 2>&1 |grep -v 'Timeout exceeded'
+
+
+# test parallelism
+ANSIBLE_FACTS_MODULES='dummy1,dummy2,dummy3' ansible -m gather_facts localhost --playbook-dir ./ -a 'gather_timeout=30 parallel=true' "$@" 2>&1
+rm "${OUTPUT_DIR}/canary.txt"
diff --git a/test/integration/targets/get_url/tasks/main.yml b/test/integration/targets/get_url/tasks/main.yml
index 09814c70..c26cc08b 100644
--- a/test/integration/targets/get_url/tasks/main.yml
+++ b/test/integration/targets/get_url/tasks/main.yml
@@ -398,6 +398,8 @@
port: '{{ http_port }}'
state: started
+- include_tasks: hashlib.yml
+
- name: download src with sha1 checksum url in check mode
get_url:
url: 'http://localhost:{{ http_port }}/27617.txt'
diff --git a/test/integration/targets/get_url/tasks/use_netrc.yml b/test/integration/targets/get_url/tasks/use_netrc.yml
index e1852a81..234c904a 100644
--- a/test/integration/targets/get_url/tasks/use_netrc.yml
+++ b/test/integration/targets/get_url/tasks/use_netrc.yml
@@ -22,7 +22,7 @@
register: response_failed
- name: Parse token from msg.txt
- set_fact:
+ set_fact:
token: "{{ (response_failed['content'] | b64decode | from_json).token }}"
- name: assert Test Bearer authorization is failed with netrc
@@ -48,7 +48,7 @@
register: response
- name: Parse token from msg.txt
- set_fact:
+ set_fact:
token: "{{ (response['content'] | b64decode | from_json).token }}"
- name: assert Test Bearer authorization is successfull with use_netrc=False
@@ -64,4 +64,4 @@
state: absent
with_items:
- "{{ remote_tmp_dir }}/netrc"
- - "{{ remote_tmp_dir }}/msg.txt" \ No newline at end of file
+ - "{{ remote_tmp_dir }}/msg.txt"
diff --git a/test/integration/targets/git/tasks/depth.yml b/test/integration/targets/git/tasks/depth.yml
index e0585ca3..20f1b4e9 100644
--- a/test/integration/targets/git/tasks/depth.yml
+++ b/test/integration/targets/git/tasks/depth.yml
@@ -95,14 +95,16 @@
repo: 'file://{{ repo_dir|expanduser }}/shallow'
dest: '{{ checkout_dir }}'
depth: 1
- version: master
+ version: >-
+ {{ git_default_branch }}
- name: DEPTH | run a second time (now fetch, not clone)
git:
repo: 'file://{{ repo_dir|expanduser }}/shallow'
dest: '{{ checkout_dir }}'
depth: 1
- version: master
+ version: >-
+ {{ git_default_branch }}
register: git_fetch
- name: DEPTH | ensure the fetch succeeded
@@ -120,7 +122,8 @@
repo: 'file://{{ repo_dir|expanduser }}/shallow'
dest: '{{ checkout_dir }}'
depth: 1
- version: master
+ version: >-
+ {{ git_default_branch }}
- name: DEPTH | switch to older branch with depth=1 (uses fetch)
git:
diff --git a/test/integration/targets/git/tasks/forcefully-fetch-tag.yml b/test/integration/targets/git/tasks/forcefully-fetch-tag.yml
index 47c37478..db35e048 100644
--- a/test/integration/targets/git/tasks/forcefully-fetch-tag.yml
+++ b/test/integration/targets/git/tasks/forcefully-fetch-tag.yml
@@ -11,7 +11,7 @@
git add leet;
git commit -m uh-oh;
git tag -f herewego;
- git push --tags origin master
+ git push --tags origin '{{ git_default_branch }}'
args:
chdir: "{{ repo_dir }}/tag_force_push_clone1"
@@ -26,7 +26,7 @@
git add leet;
git commit -m uh-oh;
git tag -f herewego;
- git push -f --tags origin master
+ git push -f --tags origin '{{ git_default_branch }}'
args:
chdir: "{{ repo_dir }}/tag_force_push_clone1"
diff --git a/test/integration/targets/git/tasks/gpg-verification.yml b/test/integration/targets/git/tasks/gpg-verification.yml
index 8c8834a9..bd57ed1d 100644
--- a/test/integration/targets/git/tasks/gpg-verification.yml
+++ b/test/integration/targets/git/tasks/gpg-verification.yml
@@ -37,8 +37,10 @@
environment:
- GNUPGHOME: "{{ git_gpg_gpghome }}"
shell: |
- set -e
+ set -eEu
+
git init
+
touch an_empty_file
git add an_empty_file
git commit --no-gpg-sign --message "Commit, and don't sign"
@@ -48,11 +50,11 @@
git tag --annotate --message "This is not a signed tag" unsigned_annotated_tag HEAD
git commit --allow-empty --gpg-sign --message "Commit, and sign"
git tag --sign --message "This is a signed tag" signed_annotated_tag HEAD
- git checkout -b some_branch/signed_tip master
+ git checkout -b some_branch/signed_tip '{{ git_default_branch }}'
git commit --allow-empty --gpg-sign --message "Commit, and sign"
- git checkout -b another_branch/unsigned_tip master
+ git checkout -b another_branch/unsigned_tip '{{ git_default_branch }}'
git commit --allow-empty --no-gpg-sign --message "Commit, and don't sign"
- git checkout master
+ git checkout '{{ git_default_branch }}'
args:
chdir: "{{ git_gpg_source }}"
diff --git a/test/integration/targets/git/tasks/localmods.yml b/test/integration/targets/git/tasks/localmods.yml
index 0e0cf684..409bbae2 100644
--- a/test/integration/targets/git/tasks/localmods.yml
+++ b/test/integration/targets/git/tasks/localmods.yml
@@ -1,6 +1,17 @@
# test for https://github.com/ansible/ansible-modules-core/pull/5505
- name: LOCALMODS | prepare old git repo
- shell: rm -rf localmods; mkdir localmods; cd localmods; git init; echo "1" > a; git add a; git commit -m "1"
+ shell: |
+ set -eEu
+
+ rm -rf localmods
+ mkdir localmods
+ cd localmods
+
+ git init
+
+ echo "1" > a
+ git add a
+ git commit -m "1"
args:
chdir: "{{repo_dir}}"
@@ -55,7 +66,18 @@
# localmods and shallow clone
- name: LOCALMODS | prepare old git repo
- shell: rm -rf localmods; mkdir localmods; cd localmods; git init; echo "1" > a; git add a; git commit -m "1"
+ shell: |
+ set -eEu
+
+ rm -rf localmods
+ mkdir localmods
+ cd localmods
+
+ git init
+
+ echo "1" > a
+ git add a
+ git commit -m "1"
args:
chdir: "{{repo_dir}}"
diff --git a/test/integration/targets/git/tasks/main.yml b/test/integration/targets/git/tasks/main.yml
index ed06eab5..c990251f 100644
--- a/test/integration/targets/git/tasks/main.yml
+++ b/test/integration/targets/git/tasks/main.yml
@@ -16,27 +16,37 @@
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
-- import_tasks: setup.yml
-- import_tasks: setup-local-repos.yml
+# NOTE: Moving `$HOME` to tmp dir allows this integration test be
+# NOTE: non-destructive. There is no other way to instruct Git use a custom
+# NOTE: config path. There are new `$GIT_CONFIG_KEY_{COUNT,KEY,VALUE}` vars
+# NOTE: for setting specific configuration values but those are only available
+# NOTE: since Git v2.31 which is why we cannot rely on them yet.
-- import_tasks: formats.yml
-- import_tasks: missing_hostkey.yml
-- import_tasks: missing_hostkey_acceptnew.yml
-- import_tasks: no-destination.yml
-- import_tasks: specific-revision.yml
-- import_tasks: submodules.yml
-- import_tasks: change-repo-url.yml
-- import_tasks: depth.yml
-- import_tasks: single-branch.yml
-- import_tasks: checkout-new-tag.yml
-- include_tasks: gpg-verification.yml
- when:
+- block:
+ - import_tasks: setup.yml
+ - import_tasks: setup-local-repos.yml
+
+ - import_tasks: formats.yml
+ - import_tasks: missing_hostkey.yml
+ - import_tasks: missing_hostkey_acceptnew.yml
+ - import_tasks: no-destination.yml
+ - import_tasks: specific-revision.yml
+ - import_tasks: submodules.yml
+ - import_tasks: change-repo-url.yml
+ - import_tasks: depth.yml
+ - import_tasks: single-branch.yml
+ - import_tasks: checkout-new-tag.yml
+ - include_tasks: gpg-verification.yml
+ when:
- not gpg_version.stderr
- gpg_version.stdout
- not (ansible_os_family == 'RedHat' and ansible_distribution_major_version is version('7', '<'))
-- import_tasks: localmods.yml
-- import_tasks: reset-origin.yml
-- import_tasks: ambiguous-ref.yml
-- import_tasks: archive.yml
-- import_tasks: separate-git-dir.yml
-- import_tasks: forcefully-fetch-tag.yml
+ - import_tasks: localmods.yml
+ - import_tasks: reset-origin.yml
+ - import_tasks: ambiguous-ref.yml
+ - import_tasks: archive.yml
+ - import_tasks: separate-git-dir.yml
+ - import_tasks: forcefully-fetch-tag.yml
+ environment:
+ HOME: >-
+ {{ remote_tmp_dir }}
diff --git a/test/integration/targets/git/tasks/missing_hostkey.yml b/test/integration/targets/git/tasks/missing_hostkey.yml
index 136c5d5d..d8a2a818 100644
--- a/test/integration/targets/git/tasks/missing_hostkey.yml
+++ b/test/integration/targets/git/tasks/missing_hostkey.yml
@@ -35,7 +35,8 @@
git:
repo: '{{ repo_format3 }}'
dest: '{{ checkout_dir }}'
- version: 'master'
+ version: >-
+ {{ git_default_branch }}
accept_hostkey: false # should already have been accepted
key_file: '{{ github_ssh_private_key }}'
ssh_opts: '-o UserKnownHostsFile={{ remote_tmp_dir }}/known_hosts'
diff --git a/test/integration/targets/git/tasks/missing_hostkey_acceptnew.yml b/test/integration/targets/git/tasks/missing_hostkey_acceptnew.yml
index 3fd19067..338ae081 100644
--- a/test/integration/targets/git/tasks/missing_hostkey_acceptnew.yml
+++ b/test/integration/targets/git/tasks/missing_hostkey_acceptnew.yml
@@ -55,7 +55,8 @@
git:
repo: '{{ repo_format3 }}'
dest: '{{ checkout_dir }}'
- version: 'master'
+ version: >-
+ {{ git_default_branch }}
accept_newhostkey: false # should already have been accepted
key_file: '{{ github_ssh_private_key }}'
ssh_opts: '-o UserKnownHostsFile={{ remote_tmp_dir }}/known_hosts'
diff --git a/test/integration/targets/git/tasks/reset-origin.yml b/test/integration/targets/git/tasks/reset-origin.yml
index 8fddd4b1..cb497c44 100644
--- a/test/integration/targets/git/tasks/reset-origin.yml
+++ b/test/integration/targets/git/tasks/reset-origin.yml
@@ -12,7 +12,14 @@
state: directory
- name: RESET-ORIGIN | Initialise the repo with a file named origin,see github.com/ansible/ansible/pull/22502
- shell: git init; echo "PR 22502" > origin; git add origin; git commit -m "PR 22502"
+ shell: |
+ set -eEu
+
+ git init
+
+ echo "PR 22502" > origin
+ git add origin
+ git commit -m "PR 22502"
args:
chdir: "{{ repo_dir }}/origin"
diff --git a/test/integration/targets/git/tasks/setup-local-repos.yml b/test/integration/targets/git/tasks/setup-local-repos.yml
index 584a1693..4626f102 100644
--- a/test/integration/targets/git/tasks/setup-local-repos.yml
+++ b/test/integration/targets/git/tasks/setup-local-repos.yml
@@ -9,15 +9,32 @@
- "{{ repo_dir }}/tag_force_push"
- name: SETUP-LOCAL-REPOS | prepare minimal git repo
- shell: git init; echo "1" > a; git add a; git commit -m "1"
+ shell: |
+ set -eEu
+
+ git init
+
+ echo "1" > a
+ git add a
+ git commit -m "1"
args:
chdir: "{{ repo_dir }}/minimal"
- name: SETUP-LOCAL-REPOS | prepare git repo for shallow clone
shell: |
- git init;
- echo "1" > a; git add a; git commit -m "1"; git tag earlytag; git branch earlybranch;
- echo "2" > a; git add a; git commit -m "2";
+ set -eEu
+
+ git init
+
+ echo "1" > a
+ git add a
+ git commit -m "1"
+ git tag earlytag
+ git branch earlybranch
+
+ echo "2" > a
+ git add a
+ git commit -m "2"
args:
chdir: "{{ repo_dir }}/shallow"
@@ -29,7 +46,10 @@
- name: SETUP-LOCAL-REPOS | prepare tmp git repo with two branches
shell: |
+ set -eEu
+
git init
+
echo "1" > a; git add a; git commit -m "1"
git checkout -b test_branch; echo "2" > a; git commit -m "2 on branch" a
git checkout -b new_branch; echo "3" > a; git commit -m "3 on new branch" a
@@ -40,6 +60,9 @@
# We make the repo here for consistency with the other repos,
# but we finish setting it up in forcefully-fetch-tag.yml.
- name: SETUP-LOCAL-REPOS | prepare tag_force_push git repo
- shell: git init --bare
+ shell: |
+ set -eEu
+
+ git init --bare
args:
chdir: "{{ repo_dir }}/tag_force_push"
diff --git a/test/integration/targets/git/tasks/setup.yml b/test/integration/targets/git/tasks/setup.yml
index 06511053..982c03ff 100644
--- a/test/integration/targets/git/tasks/setup.yml
+++ b/test/integration/targets/git/tasks/setup.yml
@@ -28,10 +28,44 @@
register: gpg_version
- name: SETUP | set git global user.email if not already set
- shell: git config --global user.email || git config --global user.email "noreply@example.com"
+ shell: git config --global user.email 'noreply@example.com'
- name: SETUP | set git global user.name if not already set
- shell: git config --global user.name || git config --global user.name "Ansible Test Runner"
+ shell: git config --global user.name 'Ansible Test Runner'
+
+- name: SETUP | set git global init.defaultBranch
+ shell: >-
+ git config --global init.defaultBranch '{{ git_default_branch }}'
+
+- name: SETUP | set git global init.templateDir
+ # NOTE: This custom Git repository template emulates the `init.defaultBranch`
+ # NOTE: setting on Git versions below 2.28.
+ # NOTE: Ref: https://superuser.com/a/1559582.
+ # NOTE: Other workarounds mentioned there, like invoking
+ # NOTE: `git symbolic-ref HEAD refs/heads/main` after each `git init` turned
+ # NOTE: out to have mysterious side effects that break the tests in surprising
+ # NOTE: ways.
+ shell: |
+ set -eEu
+
+ git config --global \
+ init.templateDir '{{ remote_tmp_dir }}/git-templates/git.git'
+
+ mkdir -pv '{{ remote_tmp_dir }}/git-templates'
+ set +e
+ GIT_TEMPLATES_DIR=$(\
+ 2>/dev/null \
+ ls -1d \
+ '/Library/Developer/CommandLineTools/usr/share/git-core/templates' \
+ '/usr/local/share/git-core/templates' \
+ '/usr/share/git-core/templates' \
+ )
+ set -e
+ >&2 echo "Found Git's default templates directory: ${GIT_TEMPLATES_DIR}"
+ cp -r "${GIT_TEMPLATES_DIR}" '{{ remote_tmp_dir }}/git-templates/git.git'
+
+ echo 'ref: refs/heads/{{ git_default_branch }}' \
+ > '{{ remote_tmp_dir }}/git-templates/git.git/HEAD'
- name: SETUP | create repo_dir
file:
diff --git a/test/integration/targets/git/tasks/single-branch.yml b/test/integration/targets/git/tasks/single-branch.yml
index 5cfb4d5b..ca8457ac 100644
--- a/test/integration/targets/git/tasks/single-branch.yml
+++ b/test/integration/targets/git/tasks/single-branch.yml
@@ -52,7 +52,8 @@
repo: 'file://{{ repo_dir|expanduser }}/shallow_branches'
dest: '{{ checkout_dir }}'
single_branch: yes
- version: master
+ version: >-
+ {{ git_default_branch }}
register: single_branch_3
- name: SINGLE_BRANCH | Clone example git repo using single_branch with version again
@@ -60,7 +61,8 @@
repo: 'file://{{ repo_dir|expanduser }}/shallow_branches'
dest: '{{ checkout_dir }}'
single_branch: yes
- version: master
+ version: >-
+ {{ git_default_branch }}
register: single_branch_4
- name: SINGLE_BRANCH | List revisions
diff --git a/test/integration/targets/git/tasks/specific-revision.yml b/test/integration/targets/git/tasks/specific-revision.yml
index 26fa7cf3..f1fe41d5 100644
--- a/test/integration/targets/git/tasks/specific-revision.yml
+++ b/test/integration/targets/git/tasks/specific-revision.yml
@@ -162,7 +162,14 @@
path: "{{ checkout_dir }}"
- name: SPECIFIC-REVISION | prepare origina repo
- shell: git init; echo "1" > a; git add a; git commit -m "1"
+ shell: |
+ set -eEu
+
+ git init
+
+ echo "1" > a
+ git add a
+ git commit -m "1"
args:
chdir: "{{ checkout_dir }}"
@@ -191,7 +198,14 @@
force: yes
- name: SPECIFIC-REVISION | create new commit in original
- shell: git init; echo "2" > b; git add b; git commit -m "2"
+ shell: |
+ set -eEu
+
+ git init
+
+ echo "2" > b
+ git add b
+ git commit -m "2"
args:
chdir: "{{ checkout_dir }}"
diff --git a/test/integration/targets/git/vars/main.yml b/test/integration/targets/git/vars/main.yml
index b38531f3..55c7c438 100644
--- a/test/integration/targets/git/vars/main.yml
+++ b/test/integration/targets/git/vars/main.yml
@@ -41,6 +41,7 @@ repo_update_url_2: 'https://github.com/ansible-test-robinro/git-test-new'
known_host_files:
- "{{ lookup('env','HOME') }}/.ssh/known_hosts"
- '/etc/ssh/ssh_known_hosts'
+git_default_branch: main
git_version_supporting_depth: 1.9.1
git_version_supporting_ls_remote: 1.7.5
git_version_supporting_single_branch: 1.7.10
diff --git a/test/integration/targets/group/tasks/main.yml b/test/integration/targets/group/tasks/main.yml
index eb8126dd..21235240 100644
--- a/test/integration/targets/group/tasks/main.yml
+++ b/test/integration/targets/group/tasks/main.yml
@@ -16,25 +16,4 @@
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
-- name: ensure test groups are deleted before the test
- group:
- name: '{{ item }}'
- state: absent
- loop:
- - ansibullgroup
- - ansibullgroup2
- - ansibullgroup3
-
-- block:
- - name: run tests
- include_tasks: tests.yml
-
- always:
- - name: remove test groups after test
- group:
- name: '{{ item }}'
- state: absent
- loop:
- - ansibullgroup
- - ansibullgroup2
- - ansibullgroup3 \ No newline at end of file
+- import_tasks: tests.yml
diff --git a/test/integration/targets/group/tasks/tests.yml b/test/integration/targets/group/tasks/tests.yml
index f9a81220..eb92cd1d 100644
--- a/test/integration/targets/group/tasks/tests.yml
+++ b/test/integration/targets/group/tasks/tests.yml
@@ -1,343 +1,412 @@
---
-##
-## group add
-##
-
-- name: create group (check mode)
- group:
- name: ansibullgroup
- state: present
- register: create_group_check
- check_mode: True
-
-- name: get result of create group (check mode)
- script: 'grouplist.sh "{{ ansible_distribution }}"'
- register: create_group_actual_check
-
-- name: assert create group (check mode)
- assert:
- that:
- - create_group_check is changed
- - '"ansibullgroup" not in create_group_actual_check.stdout_lines'
-
-- name: create group
- group:
- name: ansibullgroup
- state: present
- register: create_group
-
-- name: get result of create group
- script: 'grouplist.sh "{{ ansible_distribution }}"'
- register: create_group_actual
-
-- name: assert create group
- assert:
- that:
- - create_group is changed
- - create_group.gid is defined
- - '"ansibullgroup" in create_group_actual.stdout_lines'
-
-- name: create group (idempotent)
+- name: ensure test groups are deleted before the test
group:
- name: ansibullgroup
- state: present
- register: create_group_again
+ name: '{{ item }}'
+ state: absent
+ loop:
+ - ansibullgroup
+ - ansibullgroup2
+ - ansibullgroup3
-- name: assert create group (idempotent)
- assert:
- that:
- - not create_group_again is changed
+- block:
+ ##
+ ## group add
+ ##
-##
-## group check
-##
+ - name: create group (check mode)
+ group:
+ name: ansibullgroup
+ state: present
+ register: create_group_check
+ check_mode: true
-- name: run existing group check tests
- group:
- name: "{{ create_group_actual.stdout_lines|random }}"
- state: present
- with_sequence: start=1 end=5
- register: group_test1
-
-- name: validate results for testcase 1
- assert:
- that:
- - group_test1.results is defined
- - group_test1.results|length == 5
-
-- name: validate change results for testcase 1
- assert:
- that:
- - not group_test1 is changed
-
-##
-## group add with gid
-##
-
-- name: get the next available gid
- script: gidget.py
- args:
- executable: '{{ ansible_python_interpreter }}'
- register: gid
-
-- name: create a group with a gid (check mode)
- group:
- name: ansibullgroup2
- gid: '{{ gid.stdout_lines[0] }}'
- state: present
- register: create_group_gid_check
- check_mode: True
-
-- name: get result of create a group with a gid (check mode)
- script: 'grouplist.sh "{{ ansible_distribution }}"'
- register: create_group_gid_actual_check
-
-- name: assert create group with a gid (check mode)
- assert:
- that:
- - create_group_gid_check is changed
- - '"ansibullgroup2" not in create_group_gid_actual_check.stdout_lines'
-
-- name: create a group with a gid
- group:
- name: ansibullgroup2
- gid: '{{ gid.stdout_lines[0] }}'
- state: present
- register: create_group_gid
-
-- name: get gid of created group
- command: "{{ ansible_python_interpreter | quote }} -c \"import grp; print(grp.getgrnam('ansibullgroup2').gr_gid)\""
- register: create_group_gid_actual
-
-- name: assert create group with a gid
- assert:
- that:
- - create_group_gid is changed
- - create_group_gid.gid | int == gid.stdout_lines[0] | int
- - create_group_gid_actual.stdout | trim | int == gid.stdout_lines[0] | int
-
-- name: create a group with a gid (idempotent)
- group:
- name: ansibullgroup2
- gid: '{{ gid.stdout_lines[0] }}'
- state: present
- register: create_group_gid_again
+ - name: get result of create group (check mode)
+ script: 'grouplist.sh "{{ ansible_distribution }}"'
+ register: create_group_actual_check
-- name: assert create group with a gid (idempotent)
- assert:
- that:
- - not create_group_gid_again is changed
- - create_group_gid_again.gid | int == gid.stdout_lines[0] | int
+ - name: assert create group (check mode)
+ assert:
+ that:
+ - create_group_check is changed
+ - '"ansibullgroup" not in create_group_actual_check.stdout_lines'
-- block:
- - name: create a group with a non-unique gid
+ - name: create group
group:
- name: ansibullgroup3
- gid: '{{ gid.stdout_lines[0] }}'
- non_unique: true
+ name: ansibullgroup
state: present
- register: create_group_gid_non_unique
+ register: create_group
- - name: validate gid required with non_unique
+ - name: get result of create group
+ script: 'grouplist.sh "{{ ansible_distribution }}"'
+ register: create_group_actual
+
+ - name: assert create group
+ assert:
+ that:
+ - create_group is changed
+ - create_group.gid is defined
+ - '"ansibullgroup" in create_group_actual.stdout_lines'
+
+ - name: create group (idempotent)
group:
- name: foo
- non_unique: true
- register: missing_gid
- ignore_errors: true
+ name: ansibullgroup
+ state: present
+ register: create_group_again
- - name: assert create group with a non unique gid
+ - name: assert create group (idempotent)
assert:
that:
- - create_group_gid_non_unique is changed
- - create_group_gid_non_unique.gid | int == gid.stdout_lines[0] | int
- - missing_gid is failed
- when: ansible_facts.distribution not in ['MacOSX', 'Alpine']
+ - not create_group_again is changed
-##
-## group remove
-##
+ ##
+ ## group check
+ ##
-- name: delete group (check mode)
- group:
- name: ansibullgroup
- state: absent
- register: delete_group_check
- check_mode: True
+ - name: run existing group check tests
+ group:
+ name: "{{ create_group_actual.stdout_lines|random }}"
+ state: present
+ with_sequence: start=1 end=5
+ register: group_test1
-- name: get result of delete group (check mode)
- script: grouplist.sh "{{ ansible_distribution }}"
- register: delete_group_actual_check
+ - name: validate results for testcase 1
+ assert:
+ that:
+ - group_test1.results is defined
+ - group_test1.results|length == 5
-- name: assert delete group (check mode)
- assert:
- that:
- - delete_group_check is changed
- - '"ansibullgroup" in delete_group_actual_check.stdout_lines'
+ - name: validate change results for testcase 1
+ assert:
+ that:
+ - not group_test1 is changed
-- name: delete group
- group:
- name: ansibullgroup
- state: absent
- register: delete_group
+ ##
+ ## group add with gid
+ ##
-- name: get result of delete group
- script: grouplist.sh "{{ ansible_distribution }}"
- register: delete_group_actual
+ - name: get the next available gid
+ script: get_free_gid.py
+ args:
+ executable: '{{ ansible_python_interpreter }}'
+ register: gid
-- name: assert delete group
- assert:
- that:
- - delete_group is changed
- - '"ansibullgroup" not in delete_group_actual.stdout_lines'
+ - name: create a group with a gid (check mode)
+ group:
+ name: ansibullgroup2
+ gid: '{{ gid.stdout_lines[0] }}'
+ state: present
+ register: create_group_gid_check
+ check_mode: true
-- name: delete group (idempotent)
- group:
- name: ansibullgroup
- state: absent
- register: delete_group_again
-
-- name: assert delete group (idempotent)
- assert:
- that:
- - not delete_group_again is changed
-
-- name: Ensure lgroupadd is present
- action: "{{ ansible_facts.pkg_mgr }}"
- args:
- name: libuser
- state: present
- when: ansible_facts.system in ['Linux'] and ansible_distribution != 'Alpine' and ansible_os_family != 'Suse'
- tags:
- - user_test_local_mode
-
-- name: Ensure lgroupadd is present - Alpine
- command: apk add -U libuser
- when: ansible_distribution == 'Alpine'
- tags:
- - user_test_local_mode
-
-# https://github.com/ansible/ansible/issues/56481
-- block:
- - name: Test duplicate GID with local=yes
- group:
- name: "{{ item }}"
- gid: 1337
- local: yes
- loop:
- - group1_local_test
- - group2_local_test
- ignore_errors: yes
- register: local_duplicate_gid_result
-
- - assert:
- that:
- - local_duplicate_gid_result['results'][0] is success
- - local_duplicate_gid_result['results'][1]['msg'] == "GID '1337' already exists with group 'group1_local_test'"
- always:
- - name: Cleanup
+ - name: get result of create a group with a gid (check mode)
+ script: 'grouplist.sh "{{ ansible_distribution }}"'
+ register: create_group_gid_actual_check
+
+ - name: assert create group with a gid (check mode)
+ assert:
+ that:
+ - create_group_gid_check is changed
+ - '"ansibullgroup2" not in create_group_gid_actual_check.stdout_lines'
+
+ - name: create a group with a gid
group:
- name: group1_local_test
- state: absent
- # only applicable to Linux, limit further to CentOS where 'luseradd' is installed
- when: ansible_distribution == 'CentOS'
+ name: ansibullgroup2
+ gid: '{{ gid.stdout_lines[0] }}'
+ state: present
+ register: create_group_gid
-# https://github.com/ansible/ansible/pull/59769
-- block:
- - name: create a local group with a gid
- group:
- name: group1_local_test
- gid: 1337
- local: yes
- state: present
- register: create_local_group_gid
-
- - name: get gid of created local group
- command: "{{ ansible_python_interpreter | quote }} -c \"import grp; print(grp.getgrnam('group1_local_test').gr_gid)\""
- register: create_local_group_gid_actual
-
- - name: assert create local group with a gid
- assert:
+ - name: get gid of created group
+ script: "get_gid_for_group.py ansibullgroup2"
+ args:
+ executable: '{{ ansible_python_interpreter }}'
+ register: create_group_gid_actual
+
+ - name: assert create group with a gid
+ assert:
that:
- - create_local_group_gid is changed
- - create_local_group_gid.gid | int == 1337 | int
- - create_local_group_gid_actual.stdout | trim | int == 1337 | int
-
- - name: create a local group with a gid (idempotent)
- group:
- name: group1_local_test
- gid: 1337
- state: present
- register: create_local_group_gid_again
-
- - name: assert create local group with a gid (idempotent)
- assert:
+ - create_group_gid is changed
+ - create_group_gid.gid | int == gid.stdout_lines[0] | int
+ - create_group_gid_actual.stdout | trim | int == gid.stdout_lines[0] | int
+
+ - name: create a group with a gid (idempotent)
+ group:
+ name: ansibullgroup2
+ gid: '{{ gid.stdout_lines[0] }}'
+ state: present
+ register: create_group_gid_again
+
+ - name: assert create group with a gid (idempotent)
+ assert:
that:
- - not create_local_group_gid_again is changed
- - create_local_group_gid_again.gid | int == 1337 | int
- always:
- - name: Cleanup create local group with a gid
+ - not create_group_gid_again is changed
+ - create_group_gid_again.gid | int == gid.stdout_lines[0] | int
+
+ - block:
+ - name: create a group with a non-unique gid
+ group:
+ name: ansibullgroup3
+ gid: '{{ gid.stdout_lines[0] }}'
+ non_unique: true
+ state: present
+ register: create_group_gid_non_unique
+
+ - name: validate gid required with non_unique
+ group:
+ name: foo
+ non_unique: true
+ register: missing_gid
+ ignore_errors: true
+
+ - name: assert create group with a non unique gid
+ assert:
+ that:
+ - create_group_gid_non_unique is changed
+ - create_group_gid_non_unique.gid | int == gid.stdout_lines[0] | int
+ - missing_gid is failed
+ when: ansible_facts.distribution not in ['MacOSX', 'Alpine']
+
+ ##
+ ## group remove
+ ##
+
+ - name: delete group (check mode)
group:
- name: group1_local_test
+ name: ansibullgroup
state: absent
- # only applicable to Linux, limit further to CentOS where 'luseradd' is installed
- when: ansible_distribution == 'CentOS'
+ register: delete_group_check
+ check_mode: true
-# https://github.com/ansible/ansible/pull/59772
-- block:
- - name: create group with a gid
- group:
- name: group1_test
- gid: 1337
- local: no
- state: present
- register: create_group_gid
-
- - name: get gid of created group
- command: "{{ ansible_python_interpreter | quote }} -c \"import grp; print(grp.getgrnam('group1_test').gr_gid)\""
- register: create_group_gid_actual
-
- - name: assert create group with a gid
- assert:
- that:
- - create_group_gid is changed
- - create_group_gid.gid | int == 1337 | int
- - create_group_gid_actual.stdout | trim | int == 1337 | int
-
- - name: create local group with the same gid
- group:
- name: group1_test
- gid: 1337
- local: yes
- state: present
- register: create_local_group_gid
-
- - name: assert create local group with a gid
- assert:
+ - name: get result of delete group (check mode)
+ script: 'grouplist.sh "{{ ansible_distribution }}"'
+ register: delete_group_actual_check
+
+ - name: assert delete group (check mode)
+ assert:
that:
- - create_local_group_gid.gid | int == 1337 | int
- always:
- - name: Cleanup create group with a gid
+ - delete_group_check is changed
+ - '"ansibullgroup" in delete_group_actual_check.stdout_lines'
+
+ - name: delete group
group:
- name: group1_test
- local: no
+ name: ansibullgroup
state: absent
- - name: Cleanup create local group with the same gid
+ register: delete_group
+
+ - name: get result of delete group
+ script: 'grouplist.sh "{{ ansible_distribution }}"'
+ register: delete_group_actual
+
+ - name: assert delete group
+ assert:
+ that:
+ - delete_group is changed
+ - '"ansibullgroup" not in delete_group_actual.stdout_lines'
+
+ - name: delete group (idempotent)
group:
- name: group1_test
- local: yes
+ name: ansibullgroup
state: absent
- # only applicable to Linux, limit further to CentOS where 'lgroupadd' is installed
- when: ansible_distribution == 'CentOS'
+ register: delete_group_again
-# create system group
+ - name: assert delete group (idempotent)
+ assert:
+ that:
+ - not delete_group_again is changed
-- name: remove group
- group:
- name: ansibullgroup
- state: absent
+ - name: Ensure lgroupadd is present
+ action: "{{ ansible_facts.pkg_mgr }}"
+ args:
+ name: libuser
+ state: present
+ when: ansible_facts.system in ['Linux'] and ansible_distribution != 'Alpine' and ansible_os_family != 'Suse'
+ tags:
+ - user_test_local_mode
+
+ - name: Ensure lgroupadd is present - Alpine
+ command: apk add -U libuser
+ when: ansible_distribution == 'Alpine'
+ tags:
+ - user_test_local_mode
+
+ # https://github.com/ansible/ansible/issues/56481
+ - block:
+ - name: Test duplicate GID with local=yes
+ group:
+ name: "{{ item }}"
+ gid: 1337
+ local: true
+ loop:
+ - group1_local_test
+ - group2_local_test
+ ignore_errors: true
+ register: local_duplicate_gid_result
+
+ - assert:
+ that:
+ - local_duplicate_gid_result['results'][0] is success
+ - local_duplicate_gid_result['results'][1]['msg'] == "GID '1337' already exists with group 'group1_local_test'"
+ always:
+ - name: Cleanup
+ group:
+ name: group1_local_test
+ state: absent
+ # only applicable to Linux, limit further to CentOS where 'luseradd' is installed
+ when: ansible_distribution == 'CentOS'
+
+ # https://github.com/ansible/ansible/pull/59769
+ - block:
+ - name: create a local group with a gid
+ group:
+ name: group1_local_test
+ gid: 1337
+ local: true
+ state: present
+ register: create_local_group_gid
+
+ - name: get gid of created local group
+ script: "get_gid_for_group.py group1_local_test"
+ args:
+ executable: '{{ ansible_python_interpreter }}'
+ register: create_local_group_gid_actual
+
+ - name: assert create local group with a gid
+ assert:
+ that:
+ - create_local_group_gid is changed
+ - create_local_group_gid.gid | int == 1337 | int
+ - create_local_group_gid_actual.stdout | trim | int == 1337 | int
+
+ - name: create a local group with a gid (idempotent)
+ group:
+ name: group1_local_test
+ gid: 1337
+ state: present
+ register: create_local_group_gid_again
+
+ - name: assert create local group with a gid (idempotent)
+ assert:
+ that:
+ - not create_local_group_gid_again is changed
+ - create_local_group_gid_again.gid | int == 1337 | int
+ always:
+ - name: Cleanup create local group with a gid
+ group:
+ name: group1_local_test
+ state: absent
+ # only applicable to Linux, limit further to CentOS where 'luseradd' is installed
+ when: ansible_distribution == 'CentOS'
+
+ # https://github.com/ansible/ansible/pull/59772
+ - block:
+ - name: create group with a gid
+ group:
+ name: group1_test
+ gid: 1337
+ local: false
+ state: present
+ register: create_group_gid
+
+ - name: get gid of created group
+ script: "get_gid_for_group.py group1_test"
+ args:
+ executable: '{{ ansible_python_interpreter }}'
+ register: create_group_gid_actual
+
+ - name: assert create group with a gid
+ assert:
+ that:
+ - create_group_gid is changed
+ - create_group_gid.gid | int == 1337 | int
+ - create_group_gid_actual.stdout | trim | int == 1337 | int
+
+ - name: create local group with the same gid
+ group:
+ name: group1_test
+ gid: 1337
+ local: true
+ state: present
+ register: create_local_group_gid
+
+ - name: assert create local group with a gid
+ assert:
+ that:
+ - create_local_group_gid.gid | int == 1337 | int
+ always:
+ - name: Cleanup create group with a gid
+ group:
+ name: group1_test
+ local: false
+ state: absent
+ - name: Cleanup create local group with the same gid
+ group:
+ name: group1_test
+ local: true
+ state: absent
+ # only applicable to Linux, limit further to CentOS where 'lgroupadd' is installed
+ when: ansible_distribution == 'CentOS'
+
+ # https://github.com/ansible/ansible/pull/78172
+ - block:
+ - name: Create a group
+ group:
+ name: groupdeltest
+ state: present
+
+ - name: Create user with primary group of groupdeltest
+ user:
+ name: groupdeluser
+ group: groupdeltest
+ state: present
+
+ - name: Show we can't delete the group usually
+ group:
+ name: groupdeltest
+ state: absent
+ ignore_errors: true
+ register: failed_delete
+
+ - name: assert we couldn't delete the group
+ assert:
+ that:
+ - failed_delete is failed
+
+ - name: force delete the group
+ group:
+ name: groupdeltest
+ force: true
+ state: absent
+
+ always:
+ - name: Cleanup user
+ user:
+ name: groupdeluser
+ state: absent
+
+ - name: Cleanup group
+ group:
+ name: groupdeltest
+ state: absent
+ when: ansible_distribution not in ["MacOSX", "Alpine", "FreeBSD"]
+
+ # create system group
+
+ - name: remove group
+ group:
+ name: ansibullgroup
+ state: absent
-- name: create system group
- group:
- name: ansibullgroup
- state: present
- system: yes
+ - name: create system group
+ group:
+ name: ansibullgroup
+ state: present
+ system: true
+
+ always:
+ - name: remove test groups after test
+ group:
+ name: '{{ item }}'
+ state: absent
+ loop:
+ - ansibullgroup
+ - ansibullgroup2
+ - ansibullgroup3
diff --git a/test/integration/targets/handlers/runme.sh b/test/integration/targets/handlers/runme.sh
index 76fc99d8..368ca44d 100755
--- a/test/integration/targets/handlers/runme.sh
+++ b/test/integration/targets/handlers/runme.sh
@@ -50,6 +50,9 @@ for strategy in linear free; do
[ "$(ansible-playbook test_force_handlers.yml -i inventory.handlers -v "$@" --tags force_false_in_play --force-handlers \
| grep -E -o CALLED_HANDLER_. | sort | uniq | xargs)" = "CALLED_HANDLER_B" ]
+ # https://github.com/ansible/ansible/pull/80898
+ [ "$(ansible-playbook 80880.yml -i inventory.handlers -vv "$@" 2>&1)" ]
+
unset ANSIBLE_STRATEGY
done
@@ -66,6 +69,9 @@ done
# Notify handler listen
ansible-playbook test_handlers_listen.yml -i inventory.handlers -v "$@"
+# https://github.com/ansible/ansible/issues/82363
+ansible-playbook test_multiple_handlers_with_recursive_notification.yml -i inventory.handlers -v "$@"
+
# Notify inexistent handlers results in error
set +e
result="$(ansible-playbook test_handlers_inexistent_notify.yml -i inventory.handlers "$@" 2>&1)"
@@ -181,3 +187,24 @@ grep out.txt -e "ERROR! Using a block as a handler is not supported."
ansible-playbook test_block_as_handler-import.yml "$@" 2>&1 | tee out.txt
grep out.txt -e "ERROR! Using a block as a handler is not supported."
+
+ansible-playbook test_include_role_handler_once.yml -i inventory.handlers "$@" 2>&1 | tee out.txt
+[ "$(grep out.txt -ce 'handler ran')" = "1" ]
+
+ansible-playbook test_listen_role_dedup.yml "$@" 2>&1 | tee out.txt
+[ "$(grep out.txt -ce 'a handler from a role')" = "1" ]
+
+ansible localhost -m include_role -a "name=r1-dep_chain-vars" "$@"
+
+ansible-playbook test_include_tasks_in_include_role.yml "$@" 2>&1 | tee out.txt
+[ "$(grep out.txt -ce 'handler ran')" = "1" ]
+
+ansible-playbook test_run_once.yml -i inventory.handlers "$@" 2>&1 | tee out.txt
+[ "$(grep out.txt -ce 'handler ran once')" = "1" ]
+
+ansible-playbook 82241.yml -i inventory.handlers "$@" 2>&1 | tee out.txt
+[ "$(grep out.txt -ce 'included_task_from_tasks_dir')" = "1" ]
+
+ansible-playbook nested_flush_handlers_failure_force.yml -i inventory.handlers "$@" 2>&1 | tee out.txt
+[ "$(grep out.txt -ce 'flush_handlers_rescued')" = "1" ]
+[ "$(grep out.txt -ce 'flush_handlers_always')" = "2" ]
diff --git a/test/integration/targets/include_vars/tasks/main.yml b/test/integration/targets/include_vars/tasks/main.yml
index 6fc4e85a..97636d9d 100644
--- a/test/integration/targets/include_vars/tasks/main.yml
+++ b/test/integration/targets/include_vars/tasks/main.yml
@@ -208,6 +208,21 @@
- "config.key2.b == 22"
- "config.key3 == 3"
+- name: Include a vars dir with hash variables
+ include_vars:
+ dir: "{{ role_path }}/vars2/hashes/"
+ hash_behaviour: merge
+
+- name: Verify that the hash is merged after vars files are accumulated
+ assert:
+ that:
+ - "config | length == 3"
+ - "config.key0 is undefined"
+ - "config.key1 == 1"
+ - "config.key2 | length == 1"
+ - "config.key2.b == 22"
+ - "config.key3 == 3"
+
- include_vars:
file: no_auto_unsafe.yml
register: baz
@@ -215,3 +230,40 @@
- assert:
that:
- baz.ansible_facts.foo|type_debug != "AnsibleUnsafeText"
+
+- name: setup test following symlinks
+ delegate_to: localhost
+ block:
+ - name: create directory to test following symlinks
+ file:
+ path: "{{ role_path }}/test_symlink"
+ state: directory
+
+ - name: create symlink to the vars2 dir
+ file:
+ src: "{{ role_path }}/vars2"
+ dest: "{{ role_path }}/test_symlink/symlink"
+ state: link
+
+- name: include vars by following the symlink
+ include_vars:
+ dir: "{{ role_path }}/test_symlink"
+ register: follow_sym
+
+- assert:
+ that: follow_sym.ansible_included_var_files | sort == [hash1, hash2]
+ vars:
+ hash1: "{{ role_path }}/test_symlink/symlink/hashes/hash1.yml"
+ hash2: "{{ role_path }}/test_symlink/symlink/hashes/hash2.yml"
+
+- name: Test include_vars includes everything to the correct depth
+ ansible.builtin.include_vars:
+ dir: "{{ role_path }}/files/test_depth"
+ depth: 3
+ name: test_depth_var
+ register: test_depth
+
+- assert:
+ that:
+ - "test_depth.ansible_included_var_files|length == 8"
+ - "test_depth_var.keys()|length == 8"
diff --git a/test/integration/targets/include_vars/vars/services/service_vars.yml b/test/integration/targets/include_vars/vars/services/service_vars.yml
index 96b05d6c..bcac7646 100644
--- a/test/integration/targets/include_vars/vars/services/service_vars.yml
+++ b/test/integration/targets/include_vars/vars/services/service_vars.yml
@@ -1,2 +1,2 @@
---
-service_name: 'my_custom_service' \ No newline at end of file
+service_name: 'my_custom_service'
diff --git a/test/integration/targets/include_vars/vars/services/service_vars_fqcn.yml b/test/integration/targets/include_vars/vars/services/service_vars_fqcn.yml
index 2c04fee5..cd82eca5 100644
--- a/test/integration/targets/include_vars/vars/services/service_vars_fqcn.yml
+++ b/test/integration/targets/include_vars/vars/services/service_vars_fqcn.yml
@@ -1,3 +1,3 @@
---
service_name_fqcn: 'my_custom_service'
-service_name_tmpl_fqcn: '{{ service_name_fqcn }}' \ No newline at end of file
+service_name_tmpl_fqcn: '{{ service_name_fqcn }}'
diff --git a/test/integration/targets/include_when_parent_is_dynamic/tasks.yml b/test/integration/targets/include_when_parent_is_dynamic/tasks.yml
index 6831245c..d500f0df 100644
--- a/test/integration/targets/include_when_parent_is_dynamic/tasks.yml
+++ b/test/integration/targets/include_when_parent_is_dynamic/tasks.yml
@@ -9,4 +9,4 @@
# perform an include task which should be static if all of the task's parents are static, otherwise it should be dynamic
# this file was loaded using include_tasks, which is dynamic, so this include should also be dynamic
-- include: syntax_error.yml
+- include_tasks: syntax_error.yml
diff --git a/test/integration/targets/include_when_parent_is_static/tasks.yml b/test/integration/targets/include_when_parent_is_static/tasks.yml
index a234a3dd..50dd2341 100644
--- a/test/integration/targets/include_when_parent_is_static/tasks.yml
+++ b/test/integration/targets/include_when_parent_is_static/tasks.yml
@@ -9,4 +9,4 @@
# perform an include task which should be static if all of the task's parents are static, otherwise it should be dynamic
# this file was loaded using import_tasks, which is static, so this include should also be static
-- include: syntax_error.yml
+- import_tasks: syntax_error.yml
diff --git a/test/integration/targets/includes/include_on_playbook_should_fail.yml b/test/integration/targets/includes/include_on_playbook_should_fail.yml
index 953459dc..c9b1e81a 100644
--- a/test/integration/targets/includes/include_on_playbook_should_fail.yml
+++ b/test/integration/targets/includes/include_on_playbook_should_fail.yml
@@ -1 +1 @@
-- include: test_includes3.yml
+- include_tasks: test_includes3.yml
diff --git a/test/integration/targets/includes/roles/test_includes/handlers/main.yml b/test/integration/targets/includes/roles/test_includes/handlers/main.yml
index 7d3e625f..453fa96d 100644
--- a/test/integration/targets/includes/roles/test_includes/handlers/main.yml
+++ b/test/integration/targets/includes/roles/test_includes/handlers/main.yml
@@ -1 +1 @@
-- include: more_handlers.yml
+- import_tasks: more_handlers.yml
diff --git a/test/integration/targets/includes/roles/test_includes/tasks/main.yml b/test/integration/targets/includes/roles/test_includes/tasks/main.yml
index 83ca468b..2ba1ae63 100644
--- a/test/integration/targets/includes/roles/test_includes/tasks/main.yml
+++ b/test/integration/targets/includes/roles/test_includes/tasks/main.yml
@@ -17,47 +17,9 @@
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
-- include: included_task1.yml a=1 b=2 c=3
-
-- name: verify non-variable include params
- assert:
- that:
- - "ca == '1'"
- - "cb == '2'"
- - "cc == '3'"
-
-- set_fact:
- a: 101
- b: 102
- c: 103
-
-- include: included_task1.yml a={{a}} b={{b}} c=103
-
-- name: verify variable include params
- assert:
- that:
- - "ca == 101"
- - "cb == 102"
- - "cc == 103"
-
-# Test that strings are not turned into numbers
-- set_fact:
- a: "101"
- b: "102"
- c: "103"
-
-- include: included_task1.yml a={{a}} b={{b}} c=103
-
-- name: verify variable include params
- assert:
- that:
- - "ca == '101'"
- - "cb == '102'"
- - "cc == '103'"
-
# now try long form includes
-- include: included_task1.yml
+- include_tasks: included_task1.yml
vars:
a: 201
b: 202
diff --git a/test/integration/targets/includes/roles/test_includes_free/tasks/main.yml b/test/integration/targets/includes/roles/test_includes_free/tasks/main.yml
index 5ae7882f..d7bcf8eb 100644
--- a/test/integration/targets/includes/roles/test_includes_free/tasks/main.yml
+++ b/test/integration/targets/includes/roles/test_includes_free/tasks/main.yml
@@ -1,9 +1,9 @@
- name: this needs to be here
debug:
msg: "hello"
-- include: inner.yml
+- include_tasks: inner.yml
with_items:
- '1'
-- ansible.builtin.include: inner_fqcn.yml
+- ansible.builtin.include_tasks: inner_fqcn.yml
with_items:
- '1'
diff --git a/test/integration/targets/includes/roles/test_includes_host_pinned/tasks/main.yml b/test/integration/targets/includes/roles/test_includes_host_pinned/tasks/main.yml
index 7bc19faa..c06d3feb 100644
--- a/test/integration/targets/includes/roles/test_includes_host_pinned/tasks/main.yml
+++ b/test/integration/targets/includes/roles/test_includes_host_pinned/tasks/main.yml
@@ -1,6 +1,6 @@
- name: this needs to be here
debug:
msg: "hello"
-- include: inner.yml
+- include_tasks: inner.yml
with_items:
- '1'
diff --git a/test/integration/targets/includes/runme.sh b/test/integration/targets/includes/runme.sh
index e619feaf..8622cf66 100755
--- a/test/integration/targets/includes/runme.sh
+++ b/test/integration/targets/includes/runme.sh
@@ -10,7 +10,7 @@ echo "EXPECTED ERROR: Ensure we fail if using 'include' to include a playbook."
set +e
result="$(ansible-playbook -i ../../inventory include_on_playbook_should_fail.yml -v "$@" 2>&1)"
set -e
-grep -q "ERROR! 'include' is not a valid attribute for a Play" <<< "$result"
+grep -q "ERROR! 'include_tasks' is not a valid attribute for a Play" <<< "$result"
ansible-playbook includes_loop_rescue.yml --extra-vars strategy=linear "$@"
ansible-playbook includes_loop_rescue.yml --extra-vars strategy=free "$@"
diff --git a/test/integration/targets/includes/test_includes2.yml b/test/integration/targets/includes/test_includes2.yml
index a32e8513..da6b914f 100644
--- a/test/integration/targets/includes/test_includes2.yml
+++ b/test/integration/targets/includes/test_includes2.yml
@@ -13,8 +13,8 @@
- role: test_includes
tags: test_includes
tasks:
- - include: roles/test_includes/tasks/not_a_role_task.yml
- - include: roles/test_includes/tasks/empty.yml
+ - include_tasks: roles/test_includes/tasks/not_a_role_task.yml
+ - include_tasks: roles/test_includes/tasks/empty.yml
- assert:
that:
- "ca == 33000"
diff --git a/test/integration/targets/includes/test_includes3.yml b/test/integration/targets/includes/test_includes3.yml
index 0b4c6312..f3c4964e 100644
--- a/test/integration/targets/includes/test_includes3.yml
+++ b/test/integration/targets/includes/test_includes3.yml
@@ -1,6 +1,6 @@
- hosts: testhost
tasks:
- - include: test_includes4.yml
+ - include_tasks: test_includes4.yml
with_items: ["a"]
loop_control:
loop_var: r
diff --git a/test/integration/targets/inventory/inventory_plugins/contructed_with_hostvars.py b/test/integration/targets/inventory/inventory_plugins/contructed_with_hostvars.py
index 7ca445a3..43cad4fc 100644
--- a/test/integration/targets/inventory/inventory_plugins/contructed_with_hostvars.py
+++ b/test/integration/targets/inventory/inventory_plugins/contructed_with_hostvars.py
@@ -14,7 +14,7 @@ DOCUMENTATION = '''
'''
from ansible.errors import AnsibleParserError
-from ansible.module_utils._text import to_native
+from ansible.module_utils.common.text.converters import to_native
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
diff --git a/test/integration/targets/inventory_ini/inventory.ini b/test/integration/targets/inventory_ini/inventory.ini
index a0c99ade..a5de4211 100644
--- a/test/integration/targets/inventory_ini/inventory.ini
+++ b/test/integration/targets/inventory_ini/inventory.ini
@@ -1,3 +1,5 @@
+gitlab-runner-01 ansible_host=gitlab-runner-01.internal.example.net ansible_user=root
+
[local]
testhost ansible_connection=local ansible_become=no ansible_become_user=ansibletest1
diff --git a/test/integration/targets/inventory_ini/runme.sh b/test/integration/targets/inventory_ini/runme.sh
index 81bf1475..919e1884 100755
--- a/test/integration/targets/inventory_ini/runme.sh
+++ b/test/integration/targets/inventory_ini/runme.sh
@@ -3,3 +3,6 @@
set -eux
ansible-playbook -v -i inventory.ini test_ansible_become.yml
+
+ansible-inventory -v -i inventory.ini --list 2> out
+test "$(grep -c 'SyntaxWarning' out)" -eq 0
diff --git a/test/integration/targets/iptables/aliases b/test/integration/targets/iptables/aliases
index 7d66ecf8..73df8aad 100644
--- a/test/integration/targets/iptables/aliases
+++ b/test/integration/targets/iptables/aliases
@@ -1,5 +1,4 @@
shippable/posix/group2
skip/freebsd
-skip/osx
skip/macos
skip/docker
diff --git a/test/integration/targets/iptables/tasks/chain_management.yml b/test/integration/targets/iptables/tasks/chain_management.yml
index 03551228..dae4103a 100644
--- a/test/integration/targets/iptables/tasks/chain_management.yml
+++ b/test/integration/targets/iptables/tasks/chain_management.yml
@@ -45,6 +45,26 @@
- result is not failed
- '"FOOBAR-CHAIN" in result.stdout'
+- name: add rule to foobar chain
+ become: true
+ iptables:
+ chain: FOOBAR-CHAIN
+ source: 0.0.0.0
+ destination: 0.0.0.0
+ jump: DROP
+ comment: "FOOBAR-CHAIN RULE"
+
+- name: get the state of the iptable rules after rule is added to foobar chain
+ become: true
+ shell: "{{ iptables_bin }} -L"
+ register: result
+
+- name: assert rule is present in foobar chain
+ assert:
+ that:
+ - result is not failed
+ - '"FOOBAR-CHAIN RULE" in result.stdout'
+
- name: flush the foobar chain
become: true
iptables:
@@ -68,4 +88,3 @@
that:
- result is not failed
- '"FOOBAR-CHAIN" not in result.stdout'
- - '"FOOBAR-RULE" not in result.stdout'
diff --git a/test/integration/targets/known_hosts/defaults/main.yml b/test/integration/targets/known_hosts/defaults/main.yml
index b1b56ac7..cd438430 100644
--- a/test/integration/targets/known_hosts/defaults/main.yml
+++ b/test/integration/targets/known_hosts/defaults/main.yml
@@ -3,4 +3,4 @@ example_org_rsa_key: >
example.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAglyZmHHWskQ9wkh8LYbIqzvg99/oloneH7BaZ02ripJUy/2Zynv4tgUfm9fdXvAb1XXCEuTRnts9FBer87+voU0FPRgx3CfY9Sgr0FspUjnm4lqs53FIab1psddAaS7/F7lrnjl6VqBtPwMRQZG7qlml5uogGJwYJHxX0PGtsdoTJsM=
example_org_ed25519_key: >
- example.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIzlnSq5ESxLgW0avvPk3j7zLV59hcAPkxrMNdnZMKP2 \ No newline at end of file
+ example.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIzlnSq5ESxLgW0avvPk3j7zLV59hcAPkxrMNdnZMKP2
diff --git a/test/integration/targets/known_hosts/tasks/main.yml b/test/integration/targets/known_hosts/tasks/main.yml
index dc00dedd..d5ffec4d 100644
--- a/test/integration/targets/known_hosts/tasks/main.yml
+++ b/test/integration/targets/known_hosts/tasks/main.yml
@@ -99,7 +99,7 @@
# https://github.com/ansible/ansible/issues/78598
# test removing nonexistent host key when the other keys exist for the host
- name: remove different key
- known_hosts:
+ known_hosts:
name: example.org
key: "{{ example_org_ed25519_key }}"
state: absent
diff --git a/test/integration/targets/lookup_config/tasks/main.yml b/test/integration/targets/lookup_config/tasks/main.yml
index 356d2f80..e5699d34 100644
--- a/test/integration/targets/lookup_config/tasks/main.yml
+++ b/test/integration/targets/lookup_config/tasks/main.yml
@@ -42,6 +42,7 @@
- name: remote user and port for ssh connection
set_fact:
ssh_user_and_port: '{{q("config", "remote_user", "port", plugin_type="connection", plugin_name="ssh")}}'
+ ssh_user_and_port_and_origin: '{{q("config", "remote_user", "port", plugin_type="connection", plugin_name="ssh", show_origin=True)}}'
vars:
ansible_ssh_user: lola
ansible_ssh_port: 2022
@@ -71,4 +72,5 @@
- lookup_config_7 is failed
- '"Invalid setting" in lookup_config_7.msg'
- ssh_user_and_port == ['lola', 2022]
+ - "ssh_user_and_port_and_origin == [['lola', 'var: ansible_ssh_user'], [2022, 'var: ansible_ssh_port']]"
- yolo_remote == ["yolo"]
diff --git a/test/integration/targets/lookup_fileglob/issue72873/test.yml b/test/integration/targets/lookup_fileglob/issue72873/test.yml
index 218ee58d..92d93d45 100644
--- a/test/integration/targets/lookup_fileglob/issue72873/test.yml
+++ b/test/integration/targets/lookup_fileglob/issue72873/test.yml
@@ -5,7 +5,7 @@
dir: files
tasks:
- file: path='{{ dir }}' state=directory
-
+
- file: path='setvars.bat' state=touch # in current directory!
- file: path='{{ dir }}/{{ item }}' state=touch
@@ -20,11 +20,11 @@
- name: Get working order results and sort them
set_fact:
- working: '{{ query("fileglob", "setvars.bat", "{{ dir }}/*.[ch]") | sort }}'
+ working: '{{ query("fileglob", "setvars.bat", dir ~ "/*.[ch]") | sort }}'
- name: Get broken order results and sort them
set_fact:
- broken: '{{ query("fileglob", "{{ dir }}/*.[ch]", "setvars.bat") | sort }}'
+ broken: '{{ query("fileglob", dir ~ "/*.[ch]", "setvars.bat") | sort }}'
- assert:
that:
diff --git a/test/integration/targets/lookup_first_found/tasks/main.yml b/test/integration/targets/lookup_first_found/tasks/main.yml
index 9aeaf1d1..ba248bd5 100644
--- a/test/integration/targets/lookup_first_found/tasks/main.yml
+++ b/test/integration/targets/lookup_first_found/tasks/main.yml
@@ -94,3 +94,56 @@
- assert:
that:
- foo is defined
+
+# TODO: no 'terms' test
+- name: test first_found lookup with no terms
+ set_fact:
+ no_terms: "{{ query('first_found', files=['missing1', 'hosts', 'missing2'], paths=['/etc'], errors='ignore') }}"
+
+- assert:
+ that: "no_terms|first == '/etc/hosts'"
+
+- name: handle templatable dictionary entries
+ block:
+
+ - name: Load variables specific for OS family
+ assert:
+ that:
+ - "item is file"
+ - "item|basename == 'itworks.yml'"
+ with_first_found:
+ - files:
+ - "{{ansible_id}}-{{ansible_lsb.major_release}}.yml" # invalid var, should be skipped
+ - "{{ansible_lsb.id}}-{{ansible_lsb.major_release}}.yml" # does not exist, but should try
+ - "{{ansible_distribution}}-{{ansible_distribution_major_version}}.yml" # does not exist, but should try
+ - itworks.yml
+ - ishouldnotbefound.yml # this exist, but should not be found
+ paths:
+ - "{{role_path}}/vars"
+
+ - name: Load variables specific for OS family, but now as list of dicts, same options as above
+ assert:
+ that:
+ - "item is file"
+ - "item|basename == 'itworks.yml'"
+ with_first_found:
+ - files:
+ - "{{ansible_id}}-{{ansible_lsb.major_release}}.yml"
+ paths:
+ - "{{role_path}}/vars"
+ - files:
+ - "{{ansible_lsb.id}}-{{ansible_lsb.major_release}}.yml"
+ paths:
+ - "{{role_path}}/vars"
+ - files:
+ - "{{ansible_distribution}}-{{ansible_distribution_major_version}}.yml"
+ paths:
+ - "{{role_path}}/vars"
+ - files:
+ - itworks.yml
+ paths:
+ - "{{role_path}}/vars"
+ - files:
+ - ishouldnotbefound.yml
+ paths:
+ - "{{role_path}}/vars"
diff --git a/test/integration/targets/lookup_sequence/tasks/main.yml b/test/integration/targets/lookup_sequence/tasks/main.yml
index bd0a4d80..e64801d3 100644
--- a/test/integration/targets/lookup_sequence/tasks/main.yml
+++ b/test/integration/targets/lookup_sequence/tasks/main.yml
@@ -195,4 +195,4 @@
- ansible_failed_task.name == "EXPECTED FAILURE - test bad format string message"
- ansible_failed_result.msg == expected
vars:
- expected: "bad formatting string: d" \ No newline at end of file
+ expected: "bad formatting string: d"
diff --git a/test/integration/targets/lookup_together/tasks/main.yml b/test/integration/targets/lookup_together/tasks/main.yml
index 71365a15..115c9e52 100644
--- a/test/integration/targets/lookup_together/tasks/main.yml
+++ b/test/integration/targets/lookup_together/tasks/main.yml
@@ -26,4 +26,4 @@
- assert:
that:
- ansible_failed_task.name == "EXPECTED FAILURE - test empty list"
- - ansible_failed_result.msg == "with_together requires at least one element in each list" \ No newline at end of file
+ - ansible_failed_result.msg == "with_together requires at least one element in each list"
diff --git a/test/integration/targets/lookup_url/aliases b/test/integration/targets/lookup_url/aliases
index ef37fce1..19b7d98f 100644
--- a/test/integration/targets/lookup_url/aliases
+++ b/test/integration/targets/lookup_url/aliases
@@ -1,4 +1,11 @@
destructive
shippable/posix/group3
needs/httptester
-skip/macos/12.0 # This test crashes Python due to https://wefearchange.org/2018/11/forkmacos.rst.html
+skip/macos # This test crashes Python due to https://wefearchange.org/2018/11/forkmacos.rst.html
+# Example failure:
+#
+# TASK [lookup_url : Test that retrieving a url works] ***************************
+# objc[15394]: +[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called.
+# objc[15394]: +[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in t
+# he fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
+# ERROR! A worker was found in a dead state
diff --git a/test/integration/targets/lookup_url/meta/main.yml b/test/integration/targets/lookup_url/meta/main.yml
index 374b5fdf..6853708f 100644
--- a/test/integration/targets/lookup_url/meta/main.yml
+++ b/test/integration/targets/lookup_url/meta/main.yml
@@ -1,2 +1,2 @@
-dependencies:
+dependencies:
- prepare_http_tests
diff --git a/test/integration/targets/lookup_url/tasks/main.yml b/test/integration/targets/lookup_url/tasks/main.yml
index 2fb227ad..83fd5db6 100644
--- a/test/integration/targets/lookup_url/tasks/main.yml
+++ b/test/integration/targets/lookup_url/tasks/main.yml
@@ -1,6 +1,6 @@
- name: Test that retrieving a url works
set_fact:
- web_data: "{{ lookup('url', 'https://{{ httpbin_host }}/get?one') }}"
+ web_data: "{{ lookup('url', 'https://' ~ httpbin_host ~ '/get?one') }}"
- name: Assert that the url was retrieved
assert:
@@ -9,7 +9,7 @@
- name: Test that retrieving a url with invalid cert fails
set_fact:
- web_data: "{{ lookup('url', 'https://{{ badssl_host }}/') }}"
+ web_data: "{{ lookup('url', 'https://' ~ badssl_host ~ '/') }}"
ignore_errors: True
register: url_invalid_cert
@@ -20,12 +20,12 @@
- name: Test that retrieving a url with invalid cert with validate_certs=False works
set_fact:
- web_data: "{{ lookup('url', 'https://{{ badssl_host }}/', validate_certs=False) }}"
+ web_data: "{{ lookup('url', 'https://' ~ badssl_host ~ '/', validate_certs=False) }}"
register: url_no_validate_cert
- assert:
that:
- - "'{{ badssl_host_substring }}' in web_data"
+ - badssl_host_substring in web_data
- vars:
url: https://{{ httpbin_host }}/get
@@ -52,3 +52,27 @@
- name: Test use_netrc=False
import_tasks: use_netrc.yml
+
+- vars:
+ ansible_lookup_url_agent: ansible-test-lookup-url-agent
+ block:
+ - name: Test user agent
+ set_fact:
+ web_data: "{{ lookup('url', 'https://' ~ httpbin_host ~ '/user-agent') }}"
+
+ - name: Assert that user agent is set
+ assert:
+ that:
+ - ansible_lookup_url_agent in web_data['user-agent']
+
+- vars:
+ ansible_lookup_url_force_basic_auth: yes
+ block:
+ - name: Test force basic auth
+ set_fact:
+ web_data: "{{ lookup('url', 'https://' ~ httpbin_host ~ '/headers', username='abc') }}"
+
+ - name: Assert that Authorization header is set
+ assert:
+ that:
+ - "'Authorization' in web_data.headers"
diff --git a/test/integration/targets/lookup_url/tasks/use_netrc.yml b/test/integration/targets/lookup_url/tasks/use_netrc.yml
index 68dc8934..b90d05dc 100644
--- a/test/integration/targets/lookup_url/tasks/use_netrc.yml
+++ b/test/integration/targets/lookup_url/tasks/use_netrc.yml
@@ -10,7 +10,7 @@
- name: test Url lookup with ~/.netrc forced Basic auth
set_fact:
- web_data: "{{ lookup('ansible.builtin.url', 'https://{{ httpbin_host }}/bearer', headers={'Authorization':'Bearer foobar'}) }}"
+ web_data: "{{ lookup('ansible.builtin.url', 'https://' ~ httpbin_host ~ '/bearer', headers={'Authorization':'Bearer foobar'}) }}"
ignore_errors: yes
- name: assert test Url lookup with ~/.netrc forced Basic auth
@@ -18,11 +18,11 @@
that:
- "web_data.token.find('v=' ~ 'Zm9vOmJhcg==') == -1"
fail_msg: "Was expecting 'foo:bar' in base64, but received: {{ web_data }}"
- success_msg: "Expected Basic authentication even Bearer headers were sent"
+ success_msg: "Expected Basic authentication even Bearer headers were sent"
- name: test Url lookup with use_netrc=False
set_fact:
- web_data: "{{ lookup('ansible.builtin.url', 'https://{{ httpbin_host }}/bearer', headers={'Authorization':'Bearer foobar'}, use_netrc='False') }}"
+ web_data: "{{ lookup('ansible.builtin.url', 'https://' ~ httpbin_host ~ '/bearer', headers={'Authorization':'Bearer foobar'}, use_netrc='False') }}"
- name: assert test Url lookup with netrc=False used Bearer authentication
assert:
@@ -34,4 +34,4 @@
- name: Clean up. Removing ~/.netrc
file:
path: ~/.netrc
- state: absent \ No newline at end of file
+ state: absent
diff --git a/test/integration/targets/loop-connection/collections/ansible_collections/ns/name/meta/runtime.yml b/test/integration/targets/loop-connection/collections/ansible_collections/ns/name/meta/runtime.yml
index 09322a9d..bd892de9 100644
--- a/test/integration/targets/loop-connection/collections/ansible_collections/ns/name/meta/runtime.yml
+++ b/test/integration/targets/loop-connection/collections/ansible_collections/ns/name/meta/runtime.yml
@@ -1,4 +1,4 @@
plugin_routing:
connection:
redirected_dummy:
- redirect: ns.name.dummy \ No newline at end of file
+ redirect: ns.name.dummy
diff --git a/test/integration/targets/loop-connection/main.yml b/test/integration/targets/loop-connection/main.yml
index fbffe309..ba60e649 100644
--- a/test/integration/targets/loop-connection/main.yml
+++ b/test/integration/targets/loop-connection/main.yml
@@ -30,4 +30,4 @@
- assert:
that:
- connected_test.results[0].stderr == "ran - 1"
- - connected_test.results[1].stderr == "ran - 2" \ No newline at end of file
+ - connected_test.results[1].stderr == "ran - 2"
diff --git a/test/integration/targets/missing_required_lib/library/missing_required_lib.py b/test/integration/targets/missing_required_lib/library/missing_required_lib.py
index 480ea001..8c7ba884 100644
--- a/test/integration/targets/missing_required_lib/library/missing_required_lib.py
+++ b/test/integration/targets/missing_required_lib/library/missing_required_lib.py
@@ -8,7 +8,7 @@ __metaclass__ = type
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
try:
- import ansible_missing_lib
+ import ansible_missing_lib # pylint: disable=unused-import
HAS_LIB = True
except ImportError as e:
HAS_LIB = False
diff --git a/test/integration/targets/module_defaults/action_plugins/debug.py b/test/integration/targets/module_defaults/action_plugins/debug.py
index 2584fd3d..0c43201c 100644
--- a/test/integration/targets/module_defaults/action_plugins/debug.py
+++ b/test/integration/targets/module_defaults/action_plugins/debug.py
@@ -20,7 +20,7 @@ __metaclass__ = type
from ansible.errors import AnsibleUndefinedVariable
from ansible.module_utils.six import string_types
-from ansible.module_utils._text import to_text
+from ansible.module_utils.common.text.converters import to_text
from ansible.plugins.action import ActionBase
diff --git a/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/eos.py b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/eos.py
index 0d39f26d..174f3725 100644
--- a/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/eos.py
+++ b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/eos.py
@@ -5,7 +5,6 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.plugins.action.normal import ActionModule as ActionBase
-from ansible.utils.vars import merge_hash
class ActionModule(ActionBase):
diff --git a/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/ios.py b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/ios.py
index 20284fd1..7ba24348 100644
--- a/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/ios.py
+++ b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/ios.py
@@ -5,7 +5,6 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.plugins.action.normal import ActionModule as ActionBase
-from ansible.utils.vars import merge_hash
class ActionModule(ActionBase):
diff --git a/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/vyos.py b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/vyos.py
index b0e1904b..67050fbd 100644
--- a/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/vyos.py
+++ b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/vyos.py
@@ -5,7 +5,6 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.plugins.action.normal import ActionModule as ActionBase
-from ansible.utils.vars import merge_hash
class ActionModule(ActionBase):
diff --git a/test/integration/targets/module_no_log/aliases b/test/integration/targets/module_no_log/aliases
index 9e84f636..afa1c9c3 100644
--- a/test/integration/targets/module_no_log/aliases
+++ b/test/integration/targets/module_no_log/aliases
@@ -1,5 +1,4 @@
shippable/posix/group3
context/controller
skip/freebsd # not configured to log user.info to /var/log/syslog
-skip/osx # not configured to log user.info to /var/log/syslog
skip/macos # not configured to log user.info to /var/log/syslog
diff --git a/test/integration/targets/module_no_log/tasks/main.yml b/test/integration/targets/module_no_log/tasks/main.yml
index cf9e5802..bf024105 100644
--- a/test/integration/targets/module_no_log/tasks/main.yml
+++ b/test/integration/targets/module_no_log/tasks/main.yml
@@ -59,3 +59,41 @@
# 2) the AnsibleModule.log method is not working
- good_message in grep.stdout
- bad_message not in grep.stdout
+
+- name: Ensure we do not obscure what we should not
+ block:
+ - module_that_has_secret:
+ secret: u
+ notsecret: u
+ register: ouch
+ ignore_errors: true
+
+ - name: no log wont obscure booleans when True, but still hide in msg
+ assert:
+ that:
+ - ouch['changed'] is boolean
+ - "'*' in ouch['msg']"
+
+ - module_that_has_secret:
+ secret: a
+ notsecret: b
+ register: ouch
+ ignore_errors: true
+
+ - name: no log wont obscure booleans when False, but still hide in msg
+ assert:
+ that:
+ - ouch['changed'] is boolean
+ - "'*' in ouch['msg']"
+
+ - module_that_has_secret:
+ secret: True
+ notsecret: False
+ register: ouch
+ ignore_errors: true
+
+ - name: no log does not hide bool values
+ assert:
+ that:
+ - ouch['changed'] is boolean
+ - "'*' not in ouch['msg']"
diff --git a/test/integration/targets/module_utils/library/test.py b/test/integration/targets/module_utils/library/test.py
index fb6c8a81..857d3d8e 100644
--- a/test/integration/targets/module_utils/library/test.py
+++ b/test/integration/targets/module_utils/library/test.py
@@ -11,8 +11,8 @@ import ansible.module_utils.foo0
results['foo0'] = ansible.module_utils.foo0.data
# Test depthful import with no from
-import ansible.module_utils.bar0.foo
-results['bar0'] = ansible.module_utils.bar0.foo.data
+import ansible.module_utils.bar0.foo3
+results['bar0'] = ansible.module_utils.bar0.foo3.data
# Test import of module_utils/foo1.py
from ansible.module_utils import foo1
@@ -72,12 +72,12 @@ from ansible.module_utils.spam8.ham import eggs
results['spam8'] = (bacon.data, eggs)
# Test that import of module_utils/qux1/quux.py using as works
-from ansible.module_utils.qux1 import quux as one
-results['qux1'] = one.data
+from ansible.module_utils.qux1 import quux as two
+results['qux1'] = two.data
# Test that importing qux2/quux.py and qux2/quuz.py using as works
-from ansible.module_utils.qux2 import quux as one, quuz as two
-results['qux2'] = (one.data, two.data)
+from ansible.module_utils.qux2 import quux as three, quuz as four
+results['qux2'] = (three.data, four.data)
# Test depth
from ansible.module_utils.a.b.c.d.e.f.g.h import data
diff --git a/test/integration/targets/module_utils/library/test_failure.py b/test/integration/targets/module_utils/library/test_failure.py
index efb3ddae..ab80ceae 100644
--- a/test/integration/targets/module_utils/library/test_failure.py
+++ b/test/integration/targets/module_utils/library/test_failure.py
@@ -6,9 +6,9 @@ results = {}
# Test that we are rooted correctly
# Following files:
# module_utils/yak/zebra/foo.py
-from ansible.module_utils.zebra import foo
+from ansible.module_utils.zebra import foo4
-results['zebra'] = foo.data
+results['zebra'] = foo4.data
from ansible.module_utils.basic import AnsibleModule
AnsibleModule(argument_spec=dict()).exit_json(**results)
diff --git a/test/integration/targets/module_utils/module_utils_test.yml b/test/integration/targets/module_utils/module_utils_test.yml
index 4e948bd6..352bc582 100644
--- a/test/integration/targets/module_utils/module_utils_test.yml
+++ b/test/integration/targets/module_utils/module_utils_test.yml
@@ -47,7 +47,7 @@
assert:
that:
- result is failed
- - result['msg'] == "Could not find imported module support code for ansible.modules.test_failure. Looked for (['ansible.module_utils.zebra.foo', 'ansible.module_utils.zebra'])"
+ - result['msg'] == "Could not find imported module support code for ansible.modules.test_failure. Looked for (['ansible.module_utils.zebra.foo4', 'ansible.module_utils.zebra'])"
- name: Test that alias deprecation works
test_alias_deprecation:
diff --git a/test/integration/targets/module_utils_Ansible.Basic/library/ansible_basic_tests.ps1 b/test/integration/targets/module_utils_Ansible.Basic/library/ansible_basic_tests.ps1
index 6170f046..9644df93 100644
--- a/test/integration/targets/module_utils_Ansible.Basic/library/ansible_basic_tests.ps1
+++ b/test/integration/targets/module_utils_Ansible.Basic/library/ansible_basic_tests.ps1
@@ -87,7 +87,7 @@ Function Assert-DictionaryEqual {
}
Function Exit-Module {
- # Make sure Exit actually calls exit and not our overriden test behaviour
+ # Make sure Exit actually calls exit and not our overridden test behaviour
[Ansible.Basic.AnsibleModule]::Exit = { param([Int32]$rc) exit $rc }
Write-Output -InputObject (ConvertTo-Json -InputObject $module.Result -Compress -Depth 99)
$module.ExitJson()
diff --git a/test/integration/targets/module_utils_Ansible.ModuleUtils.AddType/library/add_type_test.ps1 b/test/integration/targets/module_utils_Ansible.ModuleUtils.AddType/library/add_type_test.ps1
index d18c42d7..5cb1a72d 100644
--- a/test/integration/targets/module_utils_Ansible.ModuleUtils.AddType/library/add_type_test.ps1
+++ b/test/integration/targets/module_utils_Ansible.ModuleUtils.AddType/library/add_type_test.ps1
@@ -328,5 +328,73 @@ finally {
}
Assert-Equal -actual ([Namespace12.Class12]::GetString()) -expected "b"
+$unsafe_code_fail = @'
+using System;
+
+namespace Namespace13
+{
+ public class Class13
+ {
+
+ public static int GetNumber()
+ {
+ int num = 2;
+ int* numPtr = &num;
+
+ DoubleNumber(numPtr);
+
+ return num;
+ }
+
+ private unsafe static void DoubleNumber(int* num)
+ {
+ *num = *num * 3;
+ }
+ }
+}
+'@
+$failed = $false
+try {
+ Add-CSharpType -Reference $unsafe_code_fail
+}
+catch {
+ $failed = $true
+ $actual = $_.Exception.Message.Contains("error CS0227: Unsafe code may only appear if compiling with /unsafe")
+ Assert-Equal -actual $actual -expected $true
+}
+Assert-Equal -actual $failed -expected $true
+
+$unsafe_code = @'
+using System;
+
+//AllowUnsafe
+
+namespace Namespace13
+{
+ public class Class13
+ {
+ public static int GetNumber()
+ {
+ int num = 2;
+ unsafe
+ {
+ int* numPtr = &num;
+
+ DoubleNumber(numPtr);
+ }
+
+ return num;
+ }
+
+ private unsafe static void DoubleNumber(int* num)
+ {
+ *num = *num * 2;
+ }
+ }
+}
+'@
+Add-CSharpType -Reference $unsafe_code
+Assert-Equal -actual ([Namespace13.Class13]::GetNumber()) -expected 4
+
$result.res = "success"
Exit-Json -obj $result
diff --git a/test/integration/targets/no_log/runme.sh b/test/integration/targets/no_log/runme.sh
index bb5c048f..bf764bf9 100755
--- a/test/integration/targets/no_log/runme.sh
+++ b/test/integration/targets/no_log/runme.sh
@@ -5,7 +5,7 @@ set -eux
# This test expects 7 loggable vars and 0 non-loggable ones.
# If either mismatches it fails, run the ansible-playbook command to debug.
[ "$(ansible-playbook no_log_local.yml -i ../../inventory -vvvvv "$@" | awk \
-'BEGIN { logme = 0; nolog = 0; } /LOG_ME/ { logme += 1;} /DO_NOT_LOG/ { nolog += 1;} END { printf "%d/%d", logme, nolog; }')" = "26/0" ]
+'BEGIN { logme = 0; nolog = 0; } /LOG_ME/ { logme += 1;} /DO_NOT_LOG/ { nolog += 1;} END { printf "%d/%d", logme, nolog; }')" = "27/0" ]
# deal with corner cases with no log and loops
# no log enabled, should produce 6 censored messages
@@ -19,3 +19,8 @@ set -eux
# test invalid data passed to a suboption
[ "$(ansible-playbook no_log_suboptions_invalid.yml -i ../../inventory -vvvvv "$@" | grep -Ec '(SUPREME|IDIOM|MOCKUP|EDUCATED|FOOTREST|CRAFTY|FELINE|CRYSTAL|EXPECTANT|AGROUND|GOLIATH|FREEFALL)')" = "0" ]
+
+# test variations on ANSIBLE_NO_LOG
+[ "$(ansible-playbook no_log_config.yml -i ../../inventory -vvvvv "$@" | grep -Ec 'the output has been hidden')" = "1" ]
+[ "$(ANSIBLE_NO_LOG=0 ansible-playbook no_log_config.yml -i ../../inventory -vvvvv "$@" | grep -Ec 'the output has been hidden')" = "1" ]
+[ "$(ANSIBLE_NO_LOG=1 ansible-playbook no_log_config.yml -i ../../inventory -vvvvv "$@" | grep -Ec 'the output has been hidden')" = "6" ]
diff --git a/test/integration/targets/old_style_cache_plugins/aliases b/test/integration/targets/old_style_cache_plugins/aliases
index 37773831..163129e2 100644
--- a/test/integration/targets/old_style_cache_plugins/aliases
+++ b/test/integration/targets/old_style_cache_plugins/aliases
@@ -2,5 +2,4 @@ destructive
needs/root
shippable/posix/group5
context/controller
-skip/osx
skip/macos
diff --git a/test/integration/targets/old_style_cache_plugins/plugins/cache/configurable_redis.py b/test/integration/targets/old_style_cache_plugins/plugins/cache/configurable_redis.py
index 44b6cf93..23c7789b 100644
--- a/test/integration/targets/old_style_cache_plugins/plugins/cache/configurable_redis.py
+++ b/test/integration/targets/old_style_cache_plugins/plugins/cache/configurable_redis.py
@@ -44,7 +44,6 @@ DOCUMENTATION = '''
import time
import json
-from ansible import constants as C
from ansible.errors import AnsibleError
from ansible.parsing.ajson import AnsibleJSONEncoder, AnsibleJSONDecoder
from ansible.plugins.cache import BaseCacheModule
diff --git a/test/integration/targets/old_style_cache_plugins/setup_redis_cache.yml b/test/integration/targets/old_style_cache_plugins/setup_redis_cache.yml
index 8aad37a3..b7cd4831 100644
--- a/test/integration/targets/old_style_cache_plugins/setup_redis_cache.yml
+++ b/test/integration/targets/old_style_cache_plugins/setup_redis_cache.yml
@@ -20,8 +20,9 @@
- name: get the latest stable redis server release
get_url:
- url: http://download.redis.io/redis-stable.tar.gz
+ url: https://download.redis.io/redis-stable.tar.gz
dest: ./
+ timeout: 60
- name: unzip download
unarchive:
diff --git a/test/integration/targets/old_style_vars_plugins/deprecation_warning/vars.py b/test/integration/targets/old_style_vars_plugins/deprecation_warning/vars.py
index d5c9a422..f554be04 100644
--- a/test/integration/targets/old_style_vars_plugins/deprecation_warning/vars.py
+++ b/test/integration/targets/old_style_vars_plugins/deprecation_warning/vars.py
@@ -2,7 +2,7 @@ from ansible.plugins.vars import BaseVarsPlugin
class VarsModule(BaseVarsPlugin):
- REQUIRES_WHITELIST = False
+ REQUIRES_WHITELIST = True
def get_vars(self, loader, path, entities):
return {}
diff --git a/test/integration/targets/old_style_vars_plugins/runme.sh b/test/integration/targets/old_style_vars_plugins/runme.sh
index 4cd19168..9f416235 100755
--- a/test/integration/targets/old_style_vars_plugins/runme.sh
+++ b/test/integration/targets/old_style_vars_plugins/runme.sh
@@ -12,9 +12,39 @@ export ANSIBLE_VARS_PLUGINS=./vars_plugins
export ANSIBLE_VARS_ENABLED=require_enabled
[ "$(ansible-inventory -i localhost, --list --yaml all "$@" | grep -c 'require_enabled')" = "1" ]
-# Test the deprecated class attribute
+# Test deprecated features
export ANSIBLE_VARS_PLUGINS=./deprecation_warning
-WARNING="The VarsModule class variable 'REQUIRES_WHITELIST' is deprecated. Use 'REQUIRES_ENABLED' instead."
+WARNING_1="The VarsModule class variable 'REQUIRES_WHITELIST' is deprecated. Use 'REQUIRES_ENABLED' instead."
+WARNING_2="The vars plugin v2_vars_plugin .* is relying on the deprecated entrypoints 'get_host_vars' and 'get_group_vars'"
ANSIBLE_DEPRECATION_WARNINGS=True ANSIBLE_NOCOLOR=True ANSIBLE_FORCE_COLOR=False \
- ansible-inventory -i localhost, --list all 2> err.txt
-ansible localhost -m debug -a "msg={{ lookup('file', 'err.txt') | regex_replace('\n', '') }}" | grep "$WARNING"
+ ansible-inventory -i localhost, --list all "$@" 2> err.txt
+for WARNING in "$WARNING_1" "$WARNING_2"; do
+ ansible localhost -m debug -a "msg={{ lookup('file', 'err.txt') | regex_replace('\n', '') }}" | grep "$WARNING"
+done
+
+# Test how many times vars plugins are loaded for a simple play containing a task
+# host_group_vars is stateless, so we can load it once and reuse it, every other vars plugin should be instantiated before it runs
+cat << EOF > "test_task_vars.yml"
+---
+- hosts: localhost
+ connection: local
+ gather_facts: no
+ tasks:
+ - debug:
+EOF
+
+# hide the debug noise by dumping to a file
+trap 'rm -rf -- "out.txt"' EXIT
+
+ANSIBLE_DEBUG=True ansible-playbook test_task_vars.yml > out.txt
+[ "$(grep -c "Loading VarsModule 'host_group_vars'" out.txt)" -eq 1 ]
+[ "$(grep -c "Loading VarsModule 'require_enabled'" out.txt)" -gt 50 ]
+[ "$(grep -c "Loading VarsModule 'auto_enabled'" out.txt)" -gt 50 ]
+
+export ANSIBLE_VARS_ENABLED=ansible.builtin.host_group_vars
+ANSIBLE_DEBUG=True ansible-playbook test_task_vars.yml > out.txt
+[ "$(grep -c "Loading VarsModule 'host_group_vars'" out.txt)" -eq 1 ]
+[ "$(grep -c "Loading VarsModule 'require_enabled'" out.txt)" -lt 3 ]
+[ "$(grep -c "Loading VarsModule 'auto_enabled'" out.txt)" -gt 50 ]
+
+ansible localhost -m include_role -a 'name=a' "$@"
diff --git a/test/integration/targets/omit/75692.yml b/test/integration/targets/omit/75692.yml
index b4000c97..5ba8a2df 100644
--- a/test/integration/targets/omit/75692.yml
+++ b/test/integration/targets/omit/75692.yml
@@ -2,10 +2,10 @@
hosts: testhost
gather_facts: false
become: yes
+ # become_user needed at play level for testing this behavior
become_user: nobody
roles:
- name: setup_test_user
- become: yes
become_user: root
tasks:
- shell: whoami
diff --git a/test/integration/targets/package/tasks/main.yml b/test/integration/targets/package/tasks/main.yml
index c17525d8..37267aa6 100644
--- a/test/integration/targets/package/tasks/main.yml
+++ b/test/integration/targets/package/tasks/main.yml
@@ -239,4 +239,4 @@
that:
- "result is changed"
- when: ansible_distribution == "Fedora" \ No newline at end of file
+ when: ansible_distribution == "Fedora"
diff --git a/test/integration/targets/package_facts/aliases b/test/integration/targets/package_facts/aliases
index 5a5e4646..f5edf4b1 100644
--- a/test/integration/targets/package_facts/aliases
+++ b/test/integration/targets/package_facts/aliases
@@ -1,3 +1,2 @@
shippable/posix/group2
-skip/osx
skip/macos
diff --git a/test/integration/targets/parsing/roles/test_good_parsing/tasks/main.yml b/test/integration/targets/parsing/roles/test_good_parsing/tasks/main.yml
index d225c0f9..25e91f28 100644
--- a/test/integration/targets/parsing/roles/test_good_parsing/tasks/main.yml
+++ b/test/integration/targets/parsing/roles/test_good_parsing/tasks/main.yml
@@ -121,7 +121,10 @@
- result.cmd == "echo foo --arg=a --arg=b"
- name: test includes with params
- include: test_include.yml fact_name=include_params param="{{ test_input }}"
+ include_tasks: test_include.yml
+ vars:
+ fact_name: include_params
+ param: "{{ test_input }}"
- name: assert the include set the correct fact for the param
assert:
@@ -129,7 +132,10 @@
- include_params == test_input
- name: test includes with quoted params
- include: test_include.yml fact_name=double_quoted_param param="this is a param with double quotes"
+ include_tasks: test_include.yml
+ vars:
+ fact_name: double_quoted_param
+ param: "this is a param with double quotes"
- name: assert the include set the correct fact for the double quoted param
assert:
@@ -137,7 +143,10 @@
- double_quoted_param == "this is a param with double quotes"
- name: test includes with single quoted params
- include: test_include.yml fact_name=single_quoted_param param='this is a param with single quotes'
+ include_tasks: test_include.yml
+ vars:
+ fact_name: single_quoted_param
+ param: 'this is a param with single quotes'
- name: assert the include set the correct fact for the single quoted param
assert:
@@ -145,7 +154,7 @@
- single_quoted_param == "this is a param with single quotes"
- name: test includes with quoted params in complex args
- include: test_include.yml
+ include_tasks: test_include.yml
vars:
fact_name: complex_param
param: "this is a param in a complex arg with double quotes"
@@ -165,7 +174,7 @@
- result.msg == "this should be debugged"
- name: test conditional includes
- include: test_include_conditional.yml
+ include_tasks: test_include_conditional.yml
when: false
- name: assert the nested include from test_include_conditional was not set
diff --git a/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_conditional.yml b/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_conditional.yml
index 070888da..a1d8b7ce 100644
--- a/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_conditional.yml
+++ b/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_conditional.yml
@@ -1 +1 @@
-- include: test_include_nested.yml
+- include_tasks: test_include_nested.yml
diff --git a/test/integration/targets/parsing/runme.sh b/test/integration/targets/parsing/runme.sh
index 022ce4cf..2d550082 100755
--- a/test/integration/targets/parsing/runme.sh
+++ b/test/integration/targets/parsing/runme.sh
@@ -2,5 +2,5 @@
set -eux
-ansible-playbook bad_parsing.yml -i ../../inventory -vvv "$@" --tags prepare,common,scenario5
-ansible-playbook good_parsing.yml -i ../../inventory -v "$@"
+ansible-playbook parsing.yml -i ../../inventory "$@" -e "output_dir=${OUTPUT_DIR}"
+ansible-playbook good_parsing.yml -i ../../inventory "$@"
diff --git a/test/integration/targets/path_lookups/testplay.yml b/test/integration/targets/path_lookups/testplay.yml
index 8bf45532..bc05c7e5 100644
--- a/test/integration/targets/path_lookups/testplay.yml
+++ b/test/integration/targets/path_lookups/testplay.yml
@@ -4,9 +4,11 @@
pre_tasks:
- name: remove {{ remove }}
file: path={{ playbook_dir }}/{{ remove }} state=absent
- roles:
- - showfile
- post_tasks:
+ tasks:
+ - import_role:
+ name: showfile
+ tasks_from: notmain.yml
+
- name: from play
set_fact: play_result="{{lookup('file', 'testfile')}}"
diff --git a/test/integration/targets/pause/test-pause.py b/test/integration/targets/pause/test-pause.py
index 3703470d..ab771fa0 100755
--- a/test/integration/targets/pause/test-pause.py
+++ b/test/integration/targets/pause/test-pause.py
@@ -168,7 +168,9 @@ pause_test = pexpect.spawn(
pause_test.logfile = log_buffer
pause_test.expect(r'Pausing for \d+ seconds')
pause_test.expect(r"\(ctrl\+C then 'C' = continue early, ctrl\+C then 'A' = abort\)")
+pause_test.send('\n') # test newline does not stop the prompt - waiting for a timeout or ctrl+C
pause_test.send('\x03')
+pause_test.expect("Press 'C' to continue the play or 'A' to abort")
pause_test.send('C')
pause_test.expect('Task after pause')
pause_test.expect(pexpect.EOF)
@@ -187,6 +189,7 @@ pause_test.logfile = log_buffer
pause_test.expect(r'Pausing for \d+ seconds')
pause_test.expect(r"\(ctrl\+C then 'C' = continue early, ctrl\+C then 'A' = abort\)")
pause_test.send('\x03')
+pause_test.expect("Press 'C' to continue the play or 'A' to abort")
pause_test.send('A')
pause_test.expect('user requested abort!')
pause_test.expect(pexpect.EOF)
@@ -225,6 +228,7 @@ pause_test.expect(r'Pausing for \d+ seconds')
pause_test.expect(r"\(ctrl\+C then 'C' = continue early, ctrl\+C then 'A' = abort\)")
pause_test.expect(r"Waiting for two seconds:")
pause_test.send('\x03')
+pause_test.expect("Press 'C' to continue the play or 'A' to abort")
pause_test.send('C')
pause_test.expect('Task after pause')
pause_test.expect(pexpect.EOF)
@@ -244,6 +248,7 @@ pause_test.expect(r'Pausing for \d+ seconds')
pause_test.expect(r"\(ctrl\+C then 'C' = continue early, ctrl\+C then 'A' = abort\)")
pause_test.expect(r"Waiting for two seconds:")
pause_test.send('\x03')
+pause_test.expect("Press 'C' to continue the play or 'A' to abort")
pause_test.send('A')
pause_test.expect('user requested abort!')
pause_test.expect(pexpect.EOF)
@@ -275,6 +280,24 @@ pause_test.send('\r')
pause_test.expect(pexpect.EOF)
pause_test.close()
+# Test input is not returned if a timeout is given
+
+playbook = 'pause-6.yml'
+
+pause_test = pexpect.spawn(
+ 'ansible-playbook',
+ args=[playbook] + args,
+ timeout=10,
+ env=os.environ
+)
+
+pause_test.logfile = log_buffer
+pause_test.expect(r'Wait for three seconds:')
+pause_test.send('ignored user input')
+pause_test.expect('Task after pause')
+pause_test.expect(pexpect.EOF)
+pause_test.close()
+
# Test that enter presses may not continue the play when a timeout is set.
diff --git a/test/integration/targets/pip/tasks/main.yml b/test/integration/targets/pip/tasks/main.yml
index 66992fd0..a3770702 100644
--- a/test/integration/targets/pip/tasks/main.yml
+++ b/test/integration/targets/pip/tasks/main.yml
@@ -40,6 +40,9 @@
extra_args: "-c {{ remote_constraints }}"
- include_tasks: pip.yml
+
+ - include_tasks: no_setuptools.yml
+ when: ansible_python.version_info[:2] >= [3, 8]
always:
- name: platform specific cleanup
include_tasks: "{{ cleanup_filename }}"
diff --git a/test/integration/targets/pip/tasks/pip.yml b/test/integration/targets/pip/tasks/pip.yml
index 39480614..9f1034d2 100644
--- a/test/integration/targets/pip/tasks/pip.yml
+++ b/test/integration/targets/pip/tasks/pip.yml
@@ -568,6 +568,28 @@
that:
- "version13 is success"
+- name: Test virtualenv command with venv formatting
+ when: ansible_python.version.major > 2
+ block:
+ - name: Clean up the virtualenv
+ file:
+ state: absent
+ name: "{{ remote_tmp_dir }}/pipenv"
+
+ # ref: https://github.com/ansible/ansible/issues/76372
+ - name: install using different venv formatting
+ pip:
+ name: "{{ pip_test_package }}"
+ virtualenv: "{{ remote_tmp_dir }}/pipenv"
+ virtualenv_command: "{{ ansible_python_interpreter ~ ' -mvenv' }}"
+ state: present
+ register: version14
+
+ - name: ensure install using virtualenv_command with venv formatting
+ assert:
+ that:
+ - "version14 is changed"
+
### test virtualenv_command end ###
# https://github.com/ansible/ansible/issues/68592
diff --git a/test/integration/targets/pkg_resources/lookup_plugins/check_pkg_resources.py b/test/integration/targets/pkg_resources/lookup_plugins/check_pkg_resources.py
index 9f1c5c0b..44412f22 100644
--- a/test/integration/targets/pkg_resources/lookup_plugins/check_pkg_resources.py
+++ b/test/integration/targets/pkg_resources/lookup_plugins/check_pkg_resources.py
@@ -11,7 +11,7 @@ __metaclass__ = type
# noinspection PyUnresolvedReferences
try:
- from pkg_resources import Requirement
+ from pkg_resources import Requirement # pylint: disable=unused-import
except ImportError:
Requirement = None
diff --git a/test/integration/targets/plugin_filtering/filter_lookup.yml b/test/integration/targets/plugin_filtering/filter_lookup.yml
index 694ebfcb..5f183e9f 100644
--- a/test/integration/targets/plugin_filtering/filter_lookup.yml
+++ b/test/integration/targets/plugin_filtering/filter_lookup.yml
@@ -1,6 +1,6 @@
---
filter_version: 1.0
-module_blacklist:
+module_rejectlist:
# Specify the name of a lookup plugin here. This should have no effect as
# this is only for filtering modules
- list
diff --git a/test/integration/targets/plugin_filtering/filter_modules.yml b/test/integration/targets/plugin_filtering/filter_modules.yml
index 6cffa676..bef7d6d8 100644
--- a/test/integration/targets/plugin_filtering/filter_modules.yml
+++ b/test/integration/targets/plugin_filtering/filter_modules.yml
@@ -1,6 +1,6 @@
---
filter_version: 1.0
-module_blacklist:
+module_rejectlist:
# A pure action plugin
- pause
# A hybrid action plugin with module
diff --git a/test/integration/targets/plugin_filtering/filter_ping.yml b/test/integration/targets/plugin_filtering/filter_ping.yml
index 08e56f24..8604716e 100644
--- a/test/integration/targets/plugin_filtering/filter_ping.yml
+++ b/test/integration/targets/plugin_filtering/filter_ping.yml
@@ -1,5 +1,5 @@
---
filter_version: 1.0
-module_blacklist:
+module_rejectlist:
# Ping is special
- ping
diff --git a/test/integration/targets/plugin_filtering/filter_stat.yml b/test/integration/targets/plugin_filtering/filter_stat.yml
index c1ce42ef..132bf03f 100644
--- a/test/integration/targets/plugin_filtering/filter_stat.yml
+++ b/test/integration/targets/plugin_filtering/filter_stat.yml
@@ -1,5 +1,5 @@
---
filter_version: 1.0
-module_blacklist:
+module_rejectlist:
# Stat is special
- stat
diff --git a/test/integration/targets/plugin_filtering/runme.sh b/test/integration/targets/plugin_filtering/runme.sh
index aa0e2b0c..03d78abc 100755
--- a/test/integration/targets/plugin_filtering/runme.sh
+++ b/test/integration/targets/plugin_filtering/runme.sh
@@ -22,11 +22,11 @@ if test $? != 0 ; then
fi
#
-# Check that if no modules are blacklisted then Ansible should not through traceback
+# Check that if no modules are rejected then Ansible should not through traceback
#
-ANSIBLE_CONFIG=no_blacklist_module.ini ansible-playbook tempfile.yml -i ../../inventory -vvv "$@"
+ANSIBLE_CONFIG=no_rejectlist_module.ini ansible-playbook tempfile.yml -i ../../inventory -vvv "$@"
if test $? != 0 ; then
- echo "### Failed to run tempfile with no modules blacklisted"
+ echo "### Failed to run tempfile with no modules rejected"
exit 1
fi
@@ -87,7 +87,7 @@ fi
ANSIBLE_CONFIG=filter_lookup.ini ansible-playbook lookup.yml -i ../../inventory -vvv "$@"
if test $? != 0 ; then
- echo "### Failed to use a lookup plugin when it is incorrectly specified in the *module* blacklist"
+ echo "### Failed to use a lookup plugin when it is incorrectly specified in the *module* reject list"
exit 1
fi
@@ -107,10 +107,10 @@ ANSIBLE_CONFIG=filter_stat.ini
export ANSIBLE_CONFIG
CAPTURE=$(ansible-playbook copy.yml -i ../../inventory -vvv "$@" 2>&1)
if test $? = 0 ; then
- echo "### Copy ran even though stat is in the module blacklist"
+ echo "### Copy ran even though stat is in the module reject list"
exit 1
else
- echo "$CAPTURE" | grep 'The stat module was specified in the module blacklist file,.*, but Ansible will not function without the stat module. Please remove stat from the blacklist.'
+ echo "$CAPTURE" | grep 'The stat module was specified in the module reject list file,.*, but Ansible will not function without the stat module. Please remove stat from the reject list.'
if test $? != 0 ; then
echo "### Stat did not give us our custom error message"
exit 1
@@ -124,10 +124,10 @@ ANSIBLE_CONFIG=filter_stat.ini
export ANSIBLE_CONFIG
CAPTURE=$(ansible-playbook stat.yml -i ../../inventory -vvv "$@" 2>&1)
if test $? = 0 ; then
- echo "### Stat ran even though it is in the module blacklist"
+ echo "### Stat ran even though it is in the module reject list"
exit 1
else
- echo "$CAPTURE" | grep 'The stat module was specified in the module blacklist file,.*, but Ansible will not function without the stat module. Please remove stat from the blacklist.'
+ echo "$CAPTURE" | grep 'The stat module was specified in the module reject list file,.*, but Ansible will not function without the stat module. Please remove stat from the reject list.'
if test $? != 0 ; then
echo "### Stat did not give us our custom error message"
exit 1
diff --git a/test/integration/targets/plugin_loader/override/filters.yml b/test/integration/targets/plugin_loader/override/filters.yml
index e51ab4e9..569a4479 100644
--- a/test/integration/targets/plugin_loader/override/filters.yml
+++ b/test/integration/targets/plugin_loader/override/filters.yml
@@ -1,7 +1,7 @@
- hosts: testhost
gather_facts: false
tasks:
- - name: ensure local 'flag' filter works, 'flatten' is overriden and 'ternary' is still from core
+ - name: ensure local 'flag' filter works, 'flatten' is overridden and 'ternary' is still from core
assert:
that:
- a|flag == 'flagged'
diff --git a/test/integration/targets/plugin_loader/runme.sh b/test/integration/targets/plugin_loader/runme.sh
index e30f6241..e68f06ad 100755
--- a/test/integration/targets/plugin_loader/runme.sh
+++ b/test/integration/targets/plugin_loader/runme.sh
@@ -34,3 +34,8 @@ done
# test config loading
ansible-playbook use_coll_name.yml -i ../../inventory -e 'ansible_connection=ansible.builtin.ssh' "$@"
+
+# test filter loading ignoring duplicate file basename
+ansible-playbook file_collision/play.yml "$@"
+
+ANSIBLE_COLLECTIONS_PATH=$PWD/collections ansible-playbook unsafe_plugin_name.yml "$@"
diff --git a/test/integration/targets/rel_plugin_loading/subdir/inventory_plugins/notyaml.py b/test/integration/targets/rel_plugin_loading/subdir/inventory_plugins/notyaml.py
index e542913d..41a76d9b 100644
--- a/test/integration/targets/rel_plugin_loading/subdir/inventory_plugins/notyaml.py
+++ b/test/integration/targets/rel_plugin_loading/subdir/inventory_plugins/notyaml.py
@@ -64,7 +64,7 @@ from collections.abc import MutableMapping
from ansible.errors import AnsibleError, AnsibleParserError
from ansible.module_utils.six import string_types
-from ansible.module_utils._text import to_native, to_text
+from ansible.module_utils.common.text.converters import to_native, to_text
from ansible.plugins.inventory import BaseFileInventoryPlugin
NoneType = type(None)
diff --git a/test/integration/targets/remote_tmp/playbook.yml b/test/integration/targets/remote_tmp/playbook.yml
index 5adef626..2d0db4e8 100644
--- a/test/integration/targets/remote_tmp/playbook.yml
+++ b/test/integration/targets/remote_tmp/playbook.yml
@@ -30,30 +30,43 @@
- name: Test tempdir is removed
hosts: testhost
gather_facts: false
+ vars:
+ # These tests cannot be run with pipelining as it defeats the purpose of
+ # ensuring remote_tmp is cleaned up. Pipelining is enabled in the test
+ # inventory
+ ansible_pipelining: false
+ # Ensure that the remote_tmp_dir we create allows the unpriv connection user
+ # to create the remote_tmp
+ ansible_become: false
tasks:
- import_role:
name: ../setup_remote_tmp_dir
- - file:
- state: touch
- path: "{{ remote_tmp_dir }}/65393"
+ - vars:
+ # Isolate the remote_tmp used by these tests
+ ansible_remote_tmp: "{{ remote_tmp_dir }}/remote_tmp"
+ block:
+ - file:
+ state: touch
+ path: "{{ remote_tmp_dir }}/65393"
- - copy:
- src: "{{ remote_tmp_dir }}/65393"
- dest: "{{ remote_tmp_dir }}/65393.2"
- remote_src: true
+ - copy:
+ src: "{{ remote_tmp_dir }}/65393"
+ dest: "{{ remote_tmp_dir }}/65393.2"
+ remote_src: true
- - find:
- path: "~/.ansible/tmp"
- use_regex: yes
- patterns: 'AnsiballZ_.+\.py'
- recurse: true
- register: result
+ - find:
+ path: "{{ ansible_remote_tmp }}"
+ use_regex: yes
+ patterns: 'AnsiballZ_.+\.py'
+ recurse: true
+ register: result
- debug:
var: result
- assert:
that:
- # Should find nothing since pipelining is used
- - result.files|length == 0
+ # Should only be AnsiballZ_find.py because find is actively running
+ - result.files|length == 1
+ - result.files[0].path.endswith('/AnsiballZ_find.py')
diff --git a/test/integration/targets/replace/tasks/main.yml b/test/integration/targets/replace/tasks/main.yml
index d267b783..ca8b4ec1 100644
--- a/test/integration/targets/replace/tasks/main.yml
+++ b/test/integration/targets/replace/tasks/main.yml
@@ -263,3 +263,22 @@
- replace_cat8.stdout_lines[1] == "9.9.9.9"
- replace_cat8.stdout_lines[7] == "0.0.0.0"
- replace_cat8.stdout_lines[13] == "0.0.0.0"
+
+# For Python 3.6 or greater - https://github.com/ansible/ansible/issues/79364
+- name: Handle bad escape character in regular expression
+ replace:
+ path: /dev/null
+ after: ^
+ before: $
+ regexp: \.
+ replace: '\D'
+ ignore_errors: true
+ register: replace_test9
+ when: ansible_python.version.major == 3 and ansible_python.version.minor > 6
+
+- name: Validate the failure
+ assert:
+ that:
+ - replace_test9 is failure
+ - replace_test9.msg.startswith("Unable to process replace")
+ when: ansible_python.version.major == 3 and ansible_python.version.minor > 6
diff --git a/test/integration/targets/roles/runme.sh b/test/integration/targets/roles/runme.sh
index bb98a932..bf3aaf58 100755
--- a/test/integration/targets/roles/runme.sh
+++ b/test/integration/targets/roles/runme.sh
@@ -3,26 +3,47 @@
set -eux
# test no dupes when dependencies in b and c point to a in roles:
-[ "$(ansible-playbook no_dupes.yml -i ../../inventory --tags inroles "$@" | grep -c '"msg": "A"')" = "1" ]
-[ "$(ansible-playbook no_dupes.yml -i ../../inventory --tags acrossroles "$@" | grep -c '"msg": "A"')" = "1" ]
-[ "$(ansible-playbook no_dupes.yml -i ../../inventory --tags intasks "$@" | grep -c '"msg": "A"')" = "1" ]
+[ "$(ansible-playbook no_dupes.yml -i ../../inventory --tags inroles | grep -c '"msg": "A"')" = "1" ]
+[ "$(ansible-playbook no_dupes.yml -i ../../inventory --tags acrossroles | grep -c '"msg": "A"')" = "1" ]
+[ "$(ansible-playbook no_dupes.yml -i ../../inventory --tags intasks | grep -c '"msg": "A"')" = "1" ]
# but still dupe across plays
-[ "$(ansible-playbook no_dupes.yml -i ../../inventory "$@" | grep -c '"msg": "A"')" = "3" ]
+[ "$(ansible-playbook no_dupes.yml -i ../../inventory | grep -c '"msg": "A"')" = "3" ]
+
+# and don't dedupe before the role successfully completes
+[ "$(ansible-playbook role_complete.yml -i ../../inventory -i fake, --tags conditional_skipped | grep -c '"msg": "A"')" = "1" ]
+[ "$(ansible-playbook role_complete.yml -i ../../inventory -i fake, --tags conditional_failed | grep -c '"msg": "failed_when task succeeded"')" = "1" ]
+[ "$(ansible-playbook role_complete.yml -i ../../inventory -i fake, --tags unreachable -vvv | grep -c '"data": "reachable"')" = "1" ]
+ansible-playbook role_complete.yml -i ../../inventory -i fake, --tags unreachable | grep -e 'ignored=2'
# include/import can execute another instance of role
-[ "$(ansible-playbook allowed_dupes.yml -i ../../inventory --tags importrole "$@" | grep -c '"msg": "A"')" = "2" ]
-[ "$(ansible-playbook allowed_dupes.yml -i ../../inventory --tags includerole "$@" | grep -c '"msg": "A"')" = "2" ]
+[ "$(ansible-playbook allowed_dupes.yml -i ../../inventory --tags importrole | grep -c '"msg": "A"')" = "2" ]
+[ "$(ansible-playbook allowed_dupes.yml -i ../../inventory --tags includerole | grep -c '"msg": "A"')" = "2" ]
+[ "$(ansible-playbook dupe_inheritance.yml -i ../../inventory | grep -c '"msg": "abc"')" = "3" ]
# ensure role data is merged correctly
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
+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
+
+# ensure vars scope is correct
+ansible-playbook vars_scope.yml -i ../../inventory "$@"
+
+# test nested includes get parent roles greater than a depth of 3
+[ "$(ansible-playbook 47023.yml -i ../../inventory | grep '\<\(Default\|Var\)\>' | grep -c 'is defined')" = "2" ]
+
+# ensure import_role called from include_role has the include_role in the dep chain
+ansible-playbook role_dep_chain.yml -i ../../inventory "$@"
+
+# global role privacy setting test, set to private, set to not private, default
+ANSIBLE_PRIVATE_ROLE_VARS=1 ansible-playbook privacy.yml -e @vars/privacy_vars.yml "$@"
+ANSIBLE_PRIVATE_ROLE_VARS=0 ansible-playbook privacy.yml -e @vars/privacy_vars.yml "$@"
+ansible-playbook privacy.yml -e @vars/privacy_vars.yml "$@"
diff --git a/test/integration/targets/roles_arg_spec/roles/c/meta/main.yml b/test/integration/targets/roles_arg_spec/roles/c/meta/main.yml
index 1a1ccbe4..10dce6d2 100644
--- a/test/integration/targets/roles_arg_spec/roles/c/meta/main.yml
+++ b/test/integration/targets/roles_arg_spec/roles/c/meta/main.yml
@@ -2,6 +2,15 @@ argument_specs:
main:
short_description: Main entry point for role C.
options:
+ c_dict:
+ type: "dict"
+ required: true
c_int:
type: "int"
required: true
+ c_list:
+ type: "list"
+ required: true
+ c_raw:
+ type: "raw"
+ required: true
diff --git a/test/integration/targets/roles_arg_spec/test.yml b/test/integration/targets/roles_arg_spec/test.yml
index 5eca7c73..b88d2e18 100644
--- a/test/integration/targets/roles_arg_spec/test.yml
+++ b/test/integration/targets/roles_arg_spec/test.yml
@@ -48,6 +48,7 @@
name: a
vars:
a_int: "{{ INT_VALUE }}"
+ a_str: "import_role"
- name: "Call role entry point that is defined, but has no spec data"
import_role:
@@ -144,7 +145,10 @@
hosts: localhost
gather_facts: false
vars:
+ c_dict: {}
c_int: 1
+ c_list: []
+ c_raw: ~
a_str: "some string"
a_int: 42
tasks:
@@ -156,6 +160,125 @@
include_role:
name: c
+- name: "New play to reset vars: Test nested role including/importing role fails with null required options"
+ hosts: localhost
+ gather_facts: false
+ vars:
+ a_main_spec:
+ a_str:
+ required: true
+ type: "str"
+ c_main_spec:
+ c_int:
+ required: true
+ type: "int"
+ c_list:
+ required: true
+ type: "list"
+ c_dict:
+ required: true
+ type: "dict"
+ c_raw:
+ required: true
+ type: "raw"
+ # role c calls a's main and alternate entrypoints
+ a_str: ''
+ c_dict: {}
+ c_int: 0
+ c_list: []
+ c_raw: ~
+ tasks:
+ - name: test type coercion fails on None for required str
+ block:
+ - name: "Test import_role of role C (missing a_str)"
+ import_role:
+ name: c
+ vars:
+ a_str: ~
+ - fail:
+ msg: "Should not get here"
+ rescue:
+ - debug:
+ var: ansible_failed_result
+ - name: "Validate import_role failure"
+ assert:
+ that:
+ # NOTE: a bug here that prevents us from getting ansible_failed_task
+ - ansible_failed_result.argument_errors == [error]
+ - ansible_failed_result.argument_spec_data == a_main_spec
+ vars:
+ error: >-
+ argument 'a_str' is of type <class 'NoneType'> and we were unable to convert to str:
+ 'None' is not a string and conversion is not allowed
+
+ - name: test type coercion fails on None for required int
+ block:
+ - name: "Test import_role of role C (missing c_int)"
+ import_role:
+ name: c
+ vars:
+ c_int: ~
+ - fail:
+ msg: "Should not get here"
+ rescue:
+ - debug:
+ var: ansible_failed_result
+ - name: "Validate import_role failure"
+ assert:
+ that:
+ # NOTE: a bug here that prevents us from getting ansible_failed_task
+ - ansible_failed_result.argument_errors == [error]
+ - ansible_failed_result.argument_spec_data == c_main_spec
+ vars:
+ error: >-
+ argument 'c_int' is of type <class 'NoneType'> and we were unable to convert to int:
+ <class 'NoneType'> cannot be converted to an int
+
+ - name: test type coercion fails on None for required list
+ block:
+ - name: "Test import_role of role C (missing c_list)"
+ import_role:
+ name: c
+ vars:
+ c_list: ~
+ - fail:
+ msg: "Should not get here"
+ rescue:
+ - debug:
+ var: ansible_failed_result
+ - name: "Validate import_role failure"
+ assert:
+ that:
+ # NOTE: a bug here that prevents us from getting ansible_failed_task
+ - ansible_failed_result.argument_errors == [error]
+ - ansible_failed_result.argument_spec_data == c_main_spec
+ vars:
+ error: >-
+ argument 'c_list' is of type <class 'NoneType'> and we were unable to convert to list:
+ <class 'NoneType'> cannot be converted to a list
+
+ - name: test type coercion fails on None for required dict
+ block:
+ - name: "Test import_role of role C (missing c_dict)"
+ import_role:
+ name: c
+ vars:
+ c_dict: ~
+ - fail:
+ msg: "Should not get here"
+ rescue:
+ - debug:
+ var: ansible_failed_result
+ - name: "Validate import_role failure"
+ assert:
+ that:
+ # NOTE: a bug here that prevents us from getting ansible_failed_task
+ - ansible_failed_result.argument_errors == [error]
+ - ansible_failed_result.argument_spec_data == c_main_spec
+ vars:
+ error: >-
+ argument 'c_dict' is of type <class 'NoneType'> and we were unable to convert to dict:
+ <class 'NoneType'> cannot be converted to a dict
- name: "New play to reset vars: Test nested role including/importing role fails"
hosts: localhost
@@ -170,13 +293,15 @@
required: true
type: "int"
+ c_int: 100
+ c_list: []
+ c_dict: {}
+ c_raw: ~
tasks:
- block:
- name: "Test import_role of role C (missing a_str)"
import_role:
name: c
- vars:
- c_int: 100
- fail:
msg: "Should not get here"
@@ -201,7 +326,6 @@
include_role:
name: c
vars:
- c_int: 200
a_str: "some string"
- fail:
diff --git a/test/integration/targets/rpm_key/tasks/rpm_key.yaml b/test/integration/targets/rpm_key/tasks/rpm_key.yaml
index 89ed2361..204b42ac 100644
--- a/test/integration/targets/rpm_key/tasks/rpm_key.yaml
+++ b/test/integration/targets/rpm_key/tasks/rpm_key.yaml
@@ -123,6 +123,32 @@
assert:
that: "'rsa sha1 (md5) pgp md5 OK' in sl_check.stdout or 'digests signatures OK' in sl_check.stdout"
+- name: get keyid
+ shell: "rpm -q gpg-pubkey | head -n 1 | xargs rpm -q --qf %{version}"
+ register: key_id
+
+- name: remove GPG key using keyid
+ rpm_key:
+ state: absent
+ key: "{{ key_id.stdout }}"
+ register: remove_keyid
+ failed_when: remove_keyid.changed == false
+
+- name: remove GPG key using keyid (idempotent)
+ rpm_key:
+ state: absent
+ key: "{{ key_id.stdout }}"
+ register: key_id_idempotence
+
+- name: verify idempotent (key_id)
+ assert:
+ that: "not key_id_idempotence.changed"
+
+- name: add very first key on system again
+ rpm_key:
+ state: present
+ key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY-EPEL-7
+
- name: Issue 20325 - Verify fingerprint of key, invalid fingerprint - EXPECTED FAILURE
rpm_key:
key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag
diff --git a/test/integration/targets/script/tasks/main.yml b/test/integration/targets/script/tasks/main.yml
index 74189f81..668ec48e 100644
--- a/test/integration/targets/script/tasks/main.yml
+++ b/test/integration/targets/script/tasks/main.yml
@@ -37,6 +37,17 @@
## script
##
+- name: Required one of free-form and cmd
+ script:
+ ignore_errors: yes
+ register: script_required
+
+- name: assert that the script fails if neither free-form nor cmd is given
+ assert:
+ that:
+ - script_required.failed
+ - "'one of the following' in script_required.msg"
+
- name: execute the test.sh script via command
script: test.sh
register: script_result0
diff --git a/test/integration/targets/service/aliases b/test/integration/targets/service/aliases
index f2f9ac9d..f3703f85 100644
--- a/test/integration/targets/service/aliases
+++ b/test/integration/targets/service/aliases
@@ -1,4 +1,3 @@
destructive
shippable/posix/group1
-skip/osx
skip/macos
diff --git a/test/integration/targets/service/files/ansible_test_service.py b/test/integration/targets/service/files/ansible_test_service.py
index 522493fc..6292272e 100644
--- a/test/integration/targets/service/files/ansible_test_service.py
+++ b/test/integration/targets/service/files/ansible_test_service.py
@@ -9,7 +9,6 @@ __metaclass__ = type
import os
import resource
import signal
-import sys
import time
UMASK = 0
diff --git a/test/integration/targets/service_facts/aliases b/test/integration/targets/service_facts/aliases
index 17d3eb75..32e10b03 100644
--- a/test/integration/targets/service_facts/aliases
+++ b/test/integration/targets/service_facts/aliases
@@ -1,4 +1,3 @@
shippable/posix/group2
skip/freebsd
-skip/osx
skip/macos
diff --git a/test/integration/targets/setup_deb_repo/tasks/main.yml b/test/integration/targets/setup_deb_repo/tasks/main.yml
index 471fb2a2..3e640f69 100644
--- a/test/integration/targets/setup_deb_repo/tasks/main.yml
+++ b/test/integration/targets/setup_deb_repo/tasks/main.yml
@@ -59,6 +59,7 @@
loop:
- stable
- testing
+ when: install_repo|default(True)|bool is true
# Need to uncomment the deb-src for the universe component for build-dep state
- name: Ensure deb-src for the universe component
diff --git a/test/integration/targets/setup_paramiko/install-Alpine-3-python-3.yml b/test/integration/targets/setup_paramiko/install-Alpine-3-python-3.yml
index f16d9b53..8c0b28bf 100644
--- a/test/integration/targets/setup_paramiko/install-Alpine-3-python-3.yml
+++ b/test/integration/targets/setup_paramiko/install-Alpine-3-python-3.yml
@@ -1,9 +1,2 @@
-- name: Setup remote constraints
- include_tasks: setup-remote-constraints.yml
- name: Install Paramiko for Python 3 on Alpine
- pip: # no apk package manager in core, just use pip
- name: paramiko
- extra_args: "-c {{ remote_constraints }}"
- environment:
- # Not sure why this fixes the test, but it does.
- SETUPTOOLS_USE_DISTUTILS: stdlib
+ command: apk add py3-paramiko
diff --git a/test/integration/targets/setup_paramiko/uninstall-Alpine-3-python-3.yml b/test/integration/targets/setup_paramiko/uninstall-Alpine-3-python-3.yml
index e9dcc62c..edb504ff 100644
--- a/test/integration/targets/setup_paramiko/uninstall-Alpine-3-python-3.yml
+++ b/test/integration/targets/setup_paramiko/uninstall-Alpine-3-python-3.yml
@@ -1,4 +1,2 @@
- name: Uninstall Paramiko for Python 3 on Alpine
- pip:
- name: paramiko
- state: absent
+ command: apk del py3-paramiko
diff --git a/test/integration/targets/setup_rpm_repo/tasks/main.yml b/test/integration/targets/setup_rpm_repo/tasks/main.yml
index be20078f..bf5af101 100644
--- a/test/integration/targets/setup_rpm_repo/tasks/main.yml
+++ b/test/integration/targets/setup_rpm_repo/tasks/main.yml
@@ -24,9 +24,18 @@
args:
name: "{{ rpm_repo_packages }}"
- - name: Install rpmfluff via pip
- pip:
- name: rpmfluff
+ - name: Install rpmfluff via pip, ensure it is installed with default python as python3-rpm may not exist for other versions
+ block:
+ - action: "{{ ansible_facts.pkg_mgr }}"
+ args:
+ name:
+ - python3-pip
+ - python3
+ state: latest
+
+ - pip:
+ name: rpmfluff
+ executable: pip3
when: ansible_facts.os_family == 'RedHat' and ansible_distribution_major_version is version('9', '==')
- set_fact:
diff --git a/test/integration/targets/strategy_linear/runme.sh b/test/integration/targets/strategy_linear/runme.sh
index cbb6aea3..a2734f97 100755
--- a/test/integration/targets/strategy_linear/runme.sh
+++ b/test/integration/targets/strategy_linear/runme.sh
@@ -5,3 +5,5 @@ set -eux
ansible-playbook test_include_file_noop.yml -i inventory "$@"
ansible-playbook task_action_templating.yml -i inventory "$@"
+
+ansible-playbook task_templated_run_once.yml -i inventory "$@"
diff --git a/test/integration/targets/subversion/aliases b/test/integration/targets/subversion/aliases
index 3cc41e4c..03b96434 100644
--- a/test/integration/targets/subversion/aliases
+++ b/test/integration/targets/subversion/aliases
@@ -1,6 +1,4 @@
shippable/posix/group2
-skip/osx
skip/macos
-skip/rhel/9.0b # svn checkout hangs
destructive
needs/root
diff --git a/test/integration/targets/systemd/tasks/test_indirect_service.yml b/test/integration/targets/systemd/tasks/test_indirect_service.yml
index fc11343e..0df60486 100644
--- a/test/integration/targets/systemd/tasks/test_indirect_service.yml
+++ b/test/integration/targets/systemd/tasks/test_indirect_service.yml
@@ -34,4 +34,4 @@
- assert:
that:
- systemd_enable_dummy_indirect_1 is changed
- - systemd_enable_dummy_indirect_2 is not changed \ No newline at end of file
+ - systemd_enable_dummy_indirect_2 is not changed
diff --git a/test/integration/targets/systemd/vars/Debian.yml b/test/integration/targets/systemd/vars/Debian.yml
index 613410f0..2dd0affb 100644
--- a/test/integration/targets/systemd/vars/Debian.yml
+++ b/test/integration/targets/systemd/vars/Debian.yml
@@ -1,3 +1,3 @@
ssh_service: ssh
sleep_bin_path: /bin/sleep
-indirect_service: dummy \ No newline at end of file
+indirect_service: dummy
diff --git a/test/integration/targets/tags/runme.sh b/test/integration/targets/tags/runme.sh
index 9da0b301..7dcb9985 100755
--- a/test/integration/targets/tags/runme.sh
+++ b/test/integration/targets/tags/runme.sh
@@ -73,3 +73,12 @@ ansible-playbook -i ../../inventory ansible_run_tags.yml -e expect=list --tags t
ansible-playbook -i ../../inventory ansible_run_tags.yml -e expect=untagged --tags untagged "$@"
ansible-playbook -i ../../inventory ansible_run_tags.yml -e expect=untagged_list --tags untagged,tag3 "$@"
ansible-playbook -i ../../inventory ansible_run_tags.yml -e expect=tagged --tags tagged "$@"
+
+ansible-playbook test_template_parent_tags.yml "$@" 2>&1 | tee out.txt
+[ "$(grep out.txt -ce 'Tagged_task')" = "1" ]; rm out.txt
+
+ansible-playbook test_template_parent_tags.yml --tags tag1 "$@" 2>&1 | tee out.txt
+[ "$(grep out.txt -ce 'Tagged_task')" = "1" ]; rm out.txt
+
+ansible-playbook test_template_parent_tags.yml --skip-tags tag1 "$@" 2>&1 | tee out.txt
+[ "$(grep out.txt -ce 'Tagged_task')" = "0" ]; rm out.txt
diff --git a/test/integration/targets/tasks/playbook.yml b/test/integration/targets/tasks/playbook.yml
index 80d9f8b1..10bd8591 100644
--- a/test/integration/targets/tasks/playbook.yml
+++ b/test/integration/targets/tasks/playbook.yml
@@ -6,6 +6,11 @@
debug:
msg: Hello
+ # ensure we properly test for an action name, not a task name when cheking for a meta task
+ - name: "meta"
+ debug:
+ msg: Hello
+
- name: ensure malformed raw_params on arbitrary actions are not ignored
debug:
garbage {{"with a template"}}
diff --git a/test/integration/targets/tasks/runme.sh b/test/integration/targets/tasks/runme.sh
index 594447bd..57cbf28a 100755
--- a/test/integration/targets/tasks/runme.sh
+++ b/test/integration/targets/tasks/runme.sh
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
-ansible-playbook playbook.yml "$@"
+ansible-playbook playbook.yml \ No newline at end of file
diff --git a/test/integration/targets/template/runme.sh b/test/integration/targets/template/runme.sh
index 30163af7..d3913d97 100755
--- a/test/integration/targets/template/runme.sh
+++ b/test/integration/targets/template/runme.sh
@@ -8,7 +8,10 @@ ANSIBLE_ROLES_PATH=../ ansible-playbook template.yml -i ../../inventory -v "$@"
ansible testhost -i testhost, -m debug -a 'msg={{ hostvars["localhost"] }}' -e "vars1={{ undef() }}" -e "vars2={{ vars1 }}"
# Test for https://github.com/ansible/ansible/issues/27262
-ansible-playbook ansible_managed.yml -c ansible_managed.cfg -i ../../inventory -v "$@"
+ANSIBLE_CONFIG=ansible_managed.cfg ansible-playbook ansible_managed.yml -i ../../inventory -v "$@"
+
+# Test for https://github.com/ansible/ansible/pull/79129
+ANSIBLE_CONFIG=ansible_managed.cfg ansible-playbook ansible_managed_79129.yml -i ../../inventory -v "$@"
# Test for #42585
ANSIBLE_ROLES_PATH=../ ansible-playbook custom_template.yml -i ../../inventory -v "$@"
@@ -39,7 +42,7 @@ ansible-playbook 72262.yml -v "$@"
ansible-playbook unsafe.yml -v "$@"
# ensure Jinja2 overrides from a template are used
-ansible-playbook in_template_overrides.yml -v "$@"
+ansible-playbook template_overrides.yml -v "$@"
ansible-playbook lazy_eval.yml -i ../../inventory -v "$@"
diff --git a/test/integration/targets/template/tasks/main.yml b/test/integration/targets/template/tasks/main.yml
index 3c91734b..34e88287 100644
--- a/test/integration/targets/template/tasks/main.yml
+++ b/test/integration/targets/template/tasks/main.yml
@@ -25,7 +25,7 @@
- name: show jinja2 version
debug:
- msg: "{{ lookup('pipe', '{{ ansible_python[\"executable\"] }} -c \"import jinja2; print(jinja2.__version__)\"') }}"
+ msg: "{{ lookup('pipe', ansible_python.executable ~ ' -c \"import jinja2; print(jinja2.__version__)\"') }}"
- name: get default group
shell: id -gn
@@ -760,7 +760,7 @@
that:
- test
vars:
- test: "{{ lookup('file', '{{ output_dir }}/empty_template.templated')|length == 0 }}"
+ test: "{{ lookup('file', output_dir ~ '/empty_template.templated')|length == 0 }}"
- name: test jinja2 override without colon throws proper error
block:
diff --git a/test/integration/targets/template/unsafe.yml b/test/integration/targets/template/unsafe.yml
index bef9a4b4..6f163881 100644
--- a/test/integration/targets/template/unsafe.yml
+++ b/test/integration/targets/template/unsafe.yml
@@ -3,6 +3,7 @@
vars:
nottemplated: this should not be seen
imunsafe: !unsafe '{{ nottemplated }}'
+ unsafe_set: !unsafe '{{ "test" }}'
tasks:
- set_fact:
@@ -12,11 +13,15 @@
- set_fact:
this_always_safe: '{{ imunsafe }}'
+ - set_fact:
+ this_unsafe_set: "{{ unsafe_set }}"
+
- name: ensure nothing was templated
assert:
that:
- this_always_safe == imunsafe
- imunsafe == this_was_unsafe.strip()
+ - unsafe_set == this_unsafe_set.strip()
- hosts: localhost
diff --git a/test/integration/targets/template_jinja2_non_native/macro_override.yml b/test/integration/targets/template_jinja2_non_native/macro_override.yml
index 8a1cabd2..c3f9ab69 100644
--- a/test/integration/targets/template_jinja2_non_native/macro_override.yml
+++ b/test/integration/targets/template_jinja2_non_native/macro_override.yml
@@ -12,4 +12,4 @@
- "'foobar' not in data"
- "'\"foo\" \"bar\"' in data"
vars:
- data: "{{ lookup('file', '{{ output_dir }}/macro_override.out') }}"
+ data: "{{ lookup('file', output_dir ~ '/macro_override.out') }}"
diff --git a/test/integration/targets/templating/tasks/main.yml b/test/integration/targets/templating/tasks/main.yml
index 312e171d..edbf012e 100644
--- a/test/integration/targets/templating/tasks/main.yml
+++ b/test/integration/targets/templating/tasks/main.yml
@@ -33,3 +33,14 @@
- result is failed
- >-
"TemplateSyntaxError: Could not load \"asdf \": 'invalid plugin name: ansible.builtin.asdf '" in result.msg
+
+- name: Make sure syntax errors originating from a template being compiled into Python code object result in a failure
+ debug:
+ msg: "{{ lookup('vars', 'v1', default='', default='') }}"
+ ignore_errors: true
+ register: r
+
+- assert:
+ that:
+ - r is failed
+ - "'keyword argument repeated' in r.msg"
diff --git a/test/integration/targets/test_core/tasks/main.yml b/test/integration/targets/test_core/tasks/main.yml
index 8c2decbd..ac06d67e 100644
--- a/test/integration/targets/test_core/tasks/main.yml
+++ b/test/integration/targets/test_core/tasks/main.yml
@@ -126,6 +126,16 @@
hello: world
register: executed_task
+- name: Skip me with multiple conditions
+ set_fact:
+ hello: world
+ when:
+ - True == True
+ - foo == 'bar'
+ vars:
+ foo: foo
+ register: skipped_task_multi_condition
+
- name: Try skipped test on non-dictionary
set_fact:
hello: "{{ 'nope' is skipped }}"
@@ -136,8 +146,11 @@
assert:
that:
- skipped_task is skipped
+ - skipped_task.false_condition == False
- executed_task is not skipped
- misuse_of_skipped is failure
+ - skipped_task_multi_condition is skipped
+ - skipped_task_multi_condition.false_condition == "foo == 'bar'"
- name: Not an async task
set_fact:
diff --git a/test/integration/targets/unarchive/tasks/main.yml b/test/integration/targets/unarchive/tasks/main.yml
index 148e583f..b07c2fe7 100644
--- a/test/integration/targets/unarchive/tasks/main.yml
+++ b/test/integration/targets/unarchive/tasks/main.yml
@@ -20,3 +20,4 @@
- import_tasks: test_different_language_var.yml
- import_tasks: test_invalid_options.yml
- import_tasks: test_ownership_top_folder.yml
+- import_tasks: test_relative_dest.yml
diff --git a/test/integration/targets/unarchive/tasks/test_different_language_var.yml b/test/integration/targets/unarchive/tasks/test_different_language_var.yml
index 9eec658e..32c84f4b 100644
--- a/test/integration/targets/unarchive/tasks/test_different_language_var.yml
+++ b/test/integration/targets/unarchive/tasks/test_different_language_var.yml
@@ -2,10 +2,10 @@
when: ansible_os_family == 'Debian'
block:
- name: install fr language pack
- apt:
+ apt:
name: language-pack-fr
state: present
-
+
- name: create our unarchive destination
file:
path: "{{ remote_tmp_dir }}/test-unarchive-nonascii-くらとみ-tar-gz"
diff --git a/test/integration/targets/unarchive/tasks/test_mode.yml b/test/integration/targets/unarchive/tasks/test_mode.yml
index 06fbc7b8..efd428eb 100644
--- a/test/integration/targets/unarchive/tasks/test_mode.yml
+++ b/test/integration/targets/unarchive/tasks/test_mode.yml
@@ -3,6 +3,29 @@
path: '{{remote_tmp_dir}}/test-unarchive-tar-gz'
state: directory
+- name: test invalid modes
+ unarchive:
+ src: "{{ remote_tmp_dir }}/test-unarchive.tar.gz"
+ dest: "{{ remote_tmp_dir }}/test-unarchive-tar-gz"
+ remote_src: yes
+ mode: "{{ item }}"
+ list_files: True
+ register: unarchive_mode_errors
+ ignore_errors: yes
+ loop:
+ - u=foo
+ - foo=r
+ - ufoo=r
+ - abc=r
+ - ao=r
+ - oa=r
+
+- assert:
+ that:
+ - item.failed
+ - "'bad symbolic permission for mode: ' + item.item == item.details"
+ loop: "{{ unarchive_mode_errors.results }}"
+
- name: unarchive and set mode to 0600, directories 0700
unarchive:
src: "{{ remote_tmp_dir }}/test-unarchive.tar.gz"
diff --git a/test/integration/targets/unsafe_writes/aliases b/test/integration/targets/unsafe_writes/aliases
index da1b554e..3560af2f 100644
--- a/test/integration/targets/unsafe_writes/aliases
+++ b/test/integration/targets/unsafe_writes/aliases
@@ -1,7 +1,6 @@
context/target
needs/root
skip/freebsd
-skip/osx
skip/macos
shippable/posix/group2
needs/target/setup_remote_tmp_dir
diff --git a/test/integration/targets/until/tasks/main.yml b/test/integration/targets/until/tasks/main.yml
index 2b2ac94e..42ce9c8f 100644
--- a/test/integration/targets/until/tasks/main.yml
+++ b/test/integration/targets/until/tasks/main.yml
@@ -82,3 +82,37 @@
register: counter
delay: 0.5
until: counter.rc == 0
+
+- name: test retries without explicit until, defaults to "until task succeeds"
+ block:
+ - name: EXPECTED FAILURE
+ fail:
+ retries: 3
+ delay: 0.1
+ register: r
+ ignore_errors: true
+
+ - assert:
+ that:
+ - r.attempts == 3
+
+ - vars:
+ test_file: "{{ lookup('env', 'OUTPUT_DIR') }}/until_success_test_file"
+ block:
+ - file:
+ name: "{{ test_file }}"
+ state: absent
+
+ - name: fail on the first invocation, succeed on the second
+ shell: "[ -f {{ test_file }} ] || (touch {{ test_file }} && false)"
+ retries: 5
+ delay: 0.1
+ register: r
+ always:
+ - file:
+ name: "{{ test_file }}"
+ state: absent
+
+ - assert:
+ that:
+ - r.attempts == 2
diff --git a/test/integration/targets/unvault/main.yml b/test/integration/targets/unvault/main.yml
index a0f97b4b..8f0adc75 100644
--- a/test/integration/targets/unvault/main.yml
+++ b/test/integration/targets/unvault/main.yml
@@ -1,4 +1,5 @@
- hosts: localhost
+ gather_facts: false
tasks:
- set_fact:
unvaulted: "{{ lookup('unvault', 'vault') }}"
diff --git a/test/integration/targets/unvault/runme.sh b/test/integration/targets/unvault/runme.sh
index df4585e3..054a14df 100755
--- a/test/integration/targets/unvault/runme.sh
+++ b/test/integration/targets/unvault/runme.sh
@@ -2,5 +2,5 @@
set -eux
-
+# simple run
ansible-playbook --vault-password-file password main.yml
diff --git a/test/integration/targets/uri/tasks/main.yml b/test/integration/targets/uri/tasks/main.yml
index 9ba09ece..ddae83a0 100644
--- a/test/integration/targets/uri/tasks/main.yml
+++ b/test/integration/targets/uri/tasks/main.yml
@@ -132,7 +132,7 @@
- "result.changed == true"
- name: "get ca certificate {{ self_signed_host }}"
- get_url:
+ uri:
url: "http://{{ httpbin_host }}/ca2cert.pem"
dest: "{{ remote_tmp_dir }}/ca2cert.pem"
@@ -638,9 +638,18 @@
- assert:
that:
- result['set_cookie'] == 'Foo=bar, Baz=qux'
- # Python sorts cookies in order of most specific (ie. longest) path first
+ # Python 3.10 and earlier sorts cookies in order of most specific (ie. longest) path first
# items with the same path are reversed from response order
- result['cookies_string'] == 'Baz=qux; Foo=bar'
+ when: ansible_python_version is version('3.11', '<')
+
+- assert:
+ that:
+ - result['set_cookie'] == 'Foo=bar, Baz=qux'
+ # Python 3.11 no longer sorts cookies.
+ # See: https://github.com/python/cpython/issues/86232
+ - result['cookies_string'] == 'Foo=bar; Baz=qux'
+ when: ansible_python_version is version('3.11', '>=')
- name: Write out netrc template
template:
@@ -757,6 +766,30 @@
dest: "{{ remote_tmp_dir }}/output"
state: absent
+- name: Test download root to dir without content-disposition
+ uri:
+ url: "https://{{ httpbin_host }}/"
+ dest: "{{ remote_tmp_dir }}"
+ register: get_root_no_filename
+
+- name: Test downloading to dir without content-disposition
+ uri:
+ url: "https://{{ httpbin_host }}/response-headers"
+ dest: "{{ remote_tmp_dir }}"
+ register: get_dir_no_filename
+
+- name: Test downloading to dir with content-disposition
+ uri:
+ url: 'https://{{ httpbin_host }}/response-headers?Content-Disposition=attachment%3B%20filename%3D%22filename.json%22'
+ dest: "{{ remote_tmp_dir }}"
+ register: get_dir_filename
+
+- assert:
+ that:
+ - get_root_no_filename.path == remote_tmp_dir ~ "/index.html"
+ - get_dir_no_filename.path == remote_tmp_dir ~ "/response-headers"
+ - get_dir_filename.path == remote_tmp_dir ~ "/filename.json"
+
- name: Test follow_redirects=none
import_tasks: redirect-none.yml
diff --git a/test/integration/targets/uri/tasks/redirect-none.yml b/test/integration/targets/uri/tasks/redirect-none.yml
index 0d1b2b34..060950d2 100644
--- a/test/integration/targets/uri/tasks/redirect-none.yml
+++ b/test/integration/targets/uri/tasks/redirect-none.yml
@@ -240,7 +240,7 @@
url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
follow_redirects: none
return_content: yes
- method: GET
+ method: HEAD
ignore_errors: yes
register: http_308_head
diff --git a/test/integration/targets/uri/tasks/redirect-urllib2.yml b/test/integration/targets/uri/tasks/redirect-urllib2.yml
index 6cdafdb2..73e87960 100644
--- a/test/integration/targets/uri/tasks/redirect-urllib2.yml
+++ b/test/integration/targets/uri/tasks/redirect-urllib2.yml
@@ -237,7 +237,7 @@
url: https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything
follow_redirects: urllib2
return_content: yes
- method: GET
+ method: HEAD
ignore_errors: yes
register: http_308_head
@@ -250,6 +250,23 @@
- http_308_head.redirected == false
- http_308_head.status == 308
- http_308_head.url == 'https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything'
+ # Python 3.10 and earlier do not support HTTP 308 responses.
+ # See: https://github.com/python/cpython/issues/84501
+ when: ansible_python_version is version('3.11', '<')
+
+# NOTE: The HTTP HEAD turns into an HTTP GET
+- assert:
+ that:
+ - http_308_head is successful
+ - http_308_head.json.data == ''
+ - http_308_head.json.method == 'GET'
+ - http_308_head.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_308_head.redirected == true
+ - http_308_head.status == 200
+ - http_308_head.url == 'https://{{ httpbin_host }}/anything'
+ # Python 3.11 introduced support for HTTP 308 responses.
+ # See: https://github.com/python/cpython/issues/84501
+ when: ansible_python_version is version('3.11', '>=')
# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809
- name: Test HTTP 308 using GET
@@ -270,6 +287,22 @@
- http_308_get.redirected == false
- http_308_get.status == 308
- http_308_get.url == 'https://{{ httpbin_host }}/redirect-to?status_code=308&url=https://{{ httpbin_host }}/anything'
+ # Python 3.10 and earlier do not support HTTP 308 responses.
+ # See: https://github.com/python/cpython/issues/84501
+ when: ansible_python_version is version('3.11', '<')
+
+- assert:
+ that:
+ - http_308_get is successful
+ - http_308_get.json.data == ''
+ - http_308_get.json.method == 'GET'
+ - http_308_get.json.url == 'https://{{ httpbin_host }}/anything'
+ - http_308_get.redirected == true
+ - http_308_get.status == 200
+ - http_308_get.url == 'https://{{ httpbin_host }}/anything'
+ # Python 3.11 introduced support for HTTP 308 responses.
+ # See: https://github.com/python/cpython/issues/84501
+ when: ansible_python_version is version('3.11', '>=')
# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809
- name: Test HTTP 308 using POST
diff --git a/test/integration/targets/uri/tasks/return-content.yml b/test/integration/targets/uri/tasks/return-content.yml
index 5a9b97e6..cb8aeea2 100644
--- a/test/integration/targets/uri/tasks/return-content.yml
+++ b/test/integration/targets/uri/tasks/return-content.yml
@@ -46,4 +46,4 @@
assert:
that:
- result is failed
- - "'content' not in result" \ No newline at end of file
+ - "'content' not in result"
diff --git a/test/integration/targets/uri/tasks/use_netrc.yml b/test/integration/targets/uri/tasks/use_netrc.yml
index da745b89..521f8ebf 100644
--- a/test/integration/targets/uri/tasks/use_netrc.yml
+++ b/test/integration/targets/uri/tasks/use_netrc.yml
@@ -48,4 +48,4 @@
- name: Clean up
file:
dest: "{{ remote_tmp_dir }}/netrc"
- state: absent \ No newline at end of file
+ state: absent
diff --git a/test/integration/targets/user/tasks/main.yml b/test/integration/targets/user/tasks/main.yml
index 9d36bfca..be4c4d6f 100644
--- a/test/integration/targets/user/tasks/main.yml
+++ b/test/integration/targets/user/tasks/main.yml
@@ -31,7 +31,9 @@
- import_tasks: test_expires.yml
- import_tasks: test_expires_new_account.yml
- import_tasks: test_expires_new_account_epoch_negative.yml
+- import_tasks: test_expires_no_shadow.yml
- import_tasks: test_expires_min_max.yml
+- import_tasks: test_expires_warn.yml
- import_tasks: test_shadow_backup.yml
- import_tasks: test_ssh_key_passphrase.yml
- import_tasks: test_password_lock.yml
diff --git a/test/integration/targets/user/tasks/test_create_user.yml b/test/integration/targets/user/tasks/test_create_user.yml
index bced7905..644dbebb 100644
--- a/test/integration/targets/user/tasks/test_create_user.yml
+++ b/test/integration/targets/user/tasks/test_create_user.yml
@@ -65,3 +65,15 @@
- "user_test1.results[2]['state'] == 'present'"
- "user_test1.results[3]['state'] == 'present'"
- "user_test1.results[4]['state'] == 'present'"
+
+- name: register user informations
+ when: ansible_facts.system == 'Darwin'
+ command: dscl . -read /Users/ansibulluser
+ register: user_test2
+
+- name: validate user defaults for MacOS
+ when: ansible_facts.system == 'Darwin'
+ assert:
+ that:
+ - "'RealName: ansibulluser' in user_test2.stdout_lines "
+ - "'PrimaryGroupID: 20' in user_test2.stdout_lines "
diff --git a/test/integration/targets/user/tasks/test_create_user_home.yml b/test/integration/targets/user/tasks/test_create_user_home.yml
index 1b529f76..5561a2f5 100644
--- a/test/integration/targets/user/tasks/test_create_user_home.yml
+++ b/test/integration/targets/user/tasks/test_create_user_home.yml
@@ -134,3 +134,21 @@
name: randomuser
state: absent
remove: yes
+
+- name: Create user home directory with /dev/null as skeleton, https://github.com/ansible/ansible/issues/75063
+ # create_homedir is mostly used by linux, rest of OSs take care of it themselves via -k option (which fails this task)
+ when: ansible_system == 'Linux'
+ block:
+ - name: "Create user home directory with /dev/null as skeleton"
+ user:
+ name: withskeleton
+ state: present
+ skeleton: "/dev/null"
+ createhome: yes
+ register: create_user_with_skeleton_dev_null
+ always:
+ - name: "Remove test user"
+ user:
+ name: withskeleton
+ state: absent
+ remove: yes
diff --git a/test/integration/targets/user/tasks/test_local.yml b/test/integration/targets/user/tasks/test_local.yml
index 67c24a21..217d4769 100644
--- a/test/integration/targets/user/tasks/test_local.yml
+++ b/test/integration/targets/user/tasks/test_local.yml
@@ -86,9 +86,11 @@
- testgroup3
- testgroup4
- testgroup5
+ - testgroup6
- local_ansibulluser
tags:
- user_test_local_mode
+ register: test_groups
- name: Create local_ansibulluser with groups
user:
@@ -113,6 +115,18 @@
tags:
- user_test_local_mode
+- name: Append groups for local_ansibulluser (again)
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ groups: ['testgroup3', 'testgroup4']
+ append: yes
+ register: local_user_test_4_again
+ ignore_errors: yes
+ tags:
+ - user_test_local_mode
+
- name: Test append without groups for local_ansibulluser
user:
name: local_ansibulluser
@@ -133,6 +147,28 @@
tags:
- user_test_local_mode
+- name: Append groups for local_ansibulluser using group id
+ user:
+ name: local_ansibulluser
+ state: present
+ append: yes
+ groups: "{{ test_groups.results[5]['gid'] }}"
+ register: local_user_test_7
+ ignore_errors: yes
+ tags:
+ - user_test_local_mode
+
+- name: Append groups for local_ansibulluser using gid (again)
+ user:
+ name: local_ansibulluser
+ state: present
+ append: yes
+ groups: "{{ test_groups.results[5]['gid'] }}"
+ register: local_user_test_7_again
+ ignore_errors: yes
+ tags:
+ - user_test_local_mode
+
# If we don't re-assign, then "Set user expiration" will
# fail.
- name: Re-assign named group for local_ansibulluser
@@ -164,6 +200,7 @@
- testgroup3
- testgroup4
- testgroup5
+ - testgroup6
- local_ansibulluser
tags:
- user_test_local_mode
@@ -175,7 +212,10 @@
- local_user_test_2 is not changed
- local_user_test_3 is changed
- local_user_test_4 is changed
+ - local_user_test_4_again is not changed
- local_user_test_6 is changed
+ - local_user_test_7 is changed
+ - local_user_test_7_again is not changed
- local_user_test_remove_1 is changed
- local_user_test_remove_2 is not changed
tags:
diff --git a/test/integration/targets/user/vars/main.yml b/test/integration/targets/user/vars/main.yml
index 4b328f71..2acd1e12 100644
--- a/test/integration/targets/user/vars/main.yml
+++ b/test/integration/targets/user/vars/main.yml
@@ -10,4 +10,4 @@ status_command:
default_user_group:
openSUSE Leap: users
- MacOSX: admin
+ MacOSX: staff
diff --git a/test/integration/targets/var_blending/roles/test_var_blending/tasks/main.yml b/test/integration/targets/var_blending/roles/test_var_blending/tasks/main.yml
index f2b2e54a..ef2a06e1 100644
--- a/test/integration/targets/var_blending/roles/test_var_blending/tasks/main.yml
+++ b/test/integration/targets/var_blending/roles/test_var_blending/tasks/main.yml
@@ -1,4 +1,4 @@
-# test code
+# test code
# (c) 2014, Michael DeHaan <michael.dehaan@gmail.com>
# This file is part of Ansible
@@ -22,7 +22,7 @@
output_dir: "{{ lookup('env', 'OUTPUT_DIR') }}"
- name: deploy a template that will use variables at various levels
- template: src=foo.j2 dest={{output_dir}}/foo.templated
+ template: src=foo.j2 dest={{output_dir}}/foo.templated
register: template_result
- name: copy known good into place
@@ -33,9 +33,9 @@
register: diff_result
- name: verify templated file matches known good
- assert:
- that:
- - 'diff_result.stdout == ""'
+ assert:
+ that:
+ - 'diff_result.stdout == ""'
- name: check debug variable with same name as var content
debug: var=same_value_as_var_name_var
diff --git a/test/integration/targets/var_precedence/ansible-var-precedence-check.py b/test/integration/targets/var_precedence/ansible-var-precedence-check.py
index fc31688b..b03c87b8 100755
--- a/test/integration/targets/var_precedence/ansible-var-precedence-check.py
+++ b/test/integration/targets/var_precedence/ansible-var-precedence-check.py
@@ -14,7 +14,6 @@ import stat
import subprocess
import tempfile
import yaml
-from pprint import pprint
from optparse import OptionParser
from jinja2 import Environment
@@ -364,9 +363,9 @@ class VarTestMaker(object):
block_wrapper = [debug_task, test_task]
if 'include_params' in self.features:
- self.tasks.append(dict(name='including tasks', include='included_tasks.yml', vars=dict(findme='include_params')))
+ self.tasks.append(dict(name='including tasks', include_tasks='included_tasks.yml', vars=dict(findme='include_params')))
else:
- self.tasks.append(dict(include='included_tasks.yml'))
+ self.tasks.append(dict(include_tasks='included_tasks.yml'))
fname = os.path.join(TESTDIR, 'included_tasks.yml')
with open(fname, 'w') as f:
diff --git a/test/integration/targets/var_precedence/test_var_precedence.yml b/test/integration/targets/var_precedence/test_var_precedence.yml
index 58584bfb..bba661db 100644
--- a/test/integration/targets/var_precedence/test_var_precedence.yml
+++ b/test/integration/targets/var_precedence/test_var_precedence.yml
@@ -1,14 +1,18 @@
---
- hosts: testhost
vars:
- - ansible_hostname: "BAD!"
- - vars_var: "vars_var"
- - param_var: "BAD!"
- - vars_files_var: "BAD!"
- - extra_var_override_once_removed: "{{ extra_var_override }}"
- - from_inventory_once_removed: "{{ inven_var | default('BAD!') }}"
+ ansible_hostname: "BAD!"
+ vars_var: "vars_var"
+ param_var: "BAD!"
+ vars_files_var: "BAD!"
+ extra_var_override_once_removed: "{{ extra_var_override }}"
+ from_inventory_once_removed: "{{ inven_var | default('BAD!') }}"
vars_files:
- vars/test_var_precedence.yml
+ pre_tasks:
+ - name: param vars should also override set_fact
+ set_fact:
+ param_var: "BAD!"
roles:
- { role: test_var_precedence, param_var: "param_var" }
tasks:
diff --git a/test/integration/targets/wait_for/tasks/main.yml b/test/integration/targets/wait_for/tasks/main.yml
index f81fd0f2..74b8e9aa 100644
--- a/test/integration/targets/wait_for/tasks/main.yml
+++ b/test/integration/targets/wait_for/tasks/main.yml
@@ -91,7 +91,7 @@
wait_for:
path: "{{remote_tmp_dir}}/wait_for_keyword"
search_regex: completed (?P<foo>\w+) ([0-9]+)
- timeout: 5
+ timeout: 25
register: waitfor
- name: verify test wait for keyword in file with match groups
@@ -114,6 +114,15 @@
path: "{{remote_tmp_dir}}/utf16.txt"
search_regex: completed
+- name: test non mmapable file
+ wait_for:
+ path: "/sys/class/net/lo/carrier"
+ search_regex: "1"
+ timeout: 30
+ when:
+ - ansible_facts['os_family'] not in ['FreeBSD', 'Darwin']
+ - not (ansible_facts['os_family'] in ['RedHat', 'CentOS'] and ansible_facts['distribution_major_version'] is version('7', '<='))
+
- name: test wait for port timeout
wait_for:
port: 12121
diff --git a/test/integration/targets/win_exec_wrapper/tasks/main.yml b/test/integration/targets/win_exec_wrapper/tasks/main.yml
index 8fc54f7c..f1342c48 100644
--- a/test/integration/targets/win_exec_wrapper/tasks/main.yml
+++ b/test/integration/targets/win_exec_wrapper/tasks/main.yml
@@ -272,3 +272,12 @@
assert:
that:
- ps_log_count.stdout | int == 0
+
+- name: test module that sets HadErrors with no error records
+ test_rc_1:
+ register: module_had_errors
+
+- name: assert test module that sets HadErrors with no error records
+ assert:
+ that:
+ - module_had_errors.rc == 0
diff --git a/test/integration/targets/win_fetch/tasks/main.yml b/test/integration/targets/win_fetch/tasks/main.yml
index b5818352..16a28761 100644
--- a/test/integration/targets/win_fetch/tasks/main.yml
+++ b/test/integration/targets/win_fetch/tasks/main.yml
@@ -215,3 +215,17 @@
- fetch_special_file.checksum == '34d4150adc3347f1dd8ce19fdf65b74d971ab602'
- fetch_special_file.dest == host_output_dir + "/abc$not var'quote‘"
- fetch_special_file_actual.stdout == 'abc'
+
+- name: create file with wildcard characters
+ raw: Set-Content -LiteralPath '{{ remote_tmp_dir }}\abc[].txt' -Value 'abc'
+
+- name: fetch file with wildcard characters
+ fetch:
+ src: '{{ remote_tmp_dir }}\abc[].txt'
+ dest: '{{ host_output_dir }}/'
+ register: fetch_wildcard_file_nofail
+
+- name: assert fetch file with wildcard characters
+ assert:
+ that:
+ - "fetch_wildcard_file_nofail is not failed"
diff --git a/test/integration/targets/win_script/files/test_script_with_args.ps1 b/test/integration/targets/win_script/files/test_script_with_args.ps1
index 01bb37f5..669c6410 100644
--- a/test/integration/targets/win_script/files/test_script_with_args.ps1
+++ b/test/integration/targets/win_script/files/test_script_with_args.ps1
@@ -2,5 +2,5 @@
# passed to the script.
foreach ($i in $args) {
- Write-Host $i;
+ Write-Host $i
}
diff --git a/test/integration/targets/win_script/files/test_script_with_errors.ps1 b/test/integration/targets/win_script/files/test_script_with_errors.ps1
index 56f97735..bdf7ee48 100644
--- a/test/integration/targets/win_script/files/test_script_with_errors.ps1
+++ b/test/integration/targets/win_script/files/test_script_with_errors.ps1
@@ -2,7 +2,7 @@
trap {
Write-Error -ErrorRecord $_
- exit 1;
+ exit 1
}
throw "Oh noes I has an error"
diff --git a/test/integration/targets/windows-minimal/library/win_ping_set_attr.ps1 b/test/integration/targets/windows-minimal/library/win_ping_set_attr.ps1
index f1704964..d23bbc74 100644
--- a/test/integration/targets/windows-minimal/library/win_ping_set_attr.ps1
+++ b/test/integration/targets/windows-minimal/library/win_ping_set_attr.ps1
@@ -16,16 +16,16 @@
# POWERSHELL_COMMON
-$params = Parse-Args $args $true;
+$params = Parse-Args $args $true
-$data = Get-Attr $params "data" "pong";
+$data = Get-Attr $params "data" "pong"
$result = @{
changed = $false
ping = "pong"
-};
+}
# Test that Set-Attr will replace an existing attribute.
Set-Attr $result "ping" $data
-Exit-Json $result;
+Exit-Json $result
diff --git a/test/integration/targets/windows-minimal/library/win_ping_strict_mode_error.ps1 b/test/integration/targets/windows-minimal/library/win_ping_strict_mode_error.ps1
index 508174af..09400d08 100644
--- a/test/integration/targets/windows-minimal/library/win_ping_strict_mode_error.ps1
+++ b/test/integration/targets/windows-minimal/library/win_ping_strict_mode_error.ps1
@@ -16,15 +16,15 @@
# POWERSHELL_COMMON
-$params = Parse-Args $args $true;
+$params = Parse-Args $args $true
$params.thisPropertyDoesNotExist
-$data = Get-Attr $params "data" "pong";
+$data = Get-Attr $params "data" "pong"
$result = @{
changed = $false
ping = $data
-};
+}
-Exit-Json $result;
+Exit-Json $result
diff --git a/test/integration/targets/windows-minimal/library/win_ping_syntax_error.ps1 b/test/integration/targets/windows-minimal/library/win_ping_syntax_error.ps1
index d4c9f07a..6932d538 100644
--- a/test/integration/targets/windows-minimal/library/win_ping_syntax_error.ps1
+++ b/test/integration/targets/windows-minimal/library/win_ping_syntax_error.ps1
@@ -18,13 +18,13 @@
$blah = 'I can't quote my strings correctly.'
-$params = Parse-Args $args $true;
+$params = Parse-Args $args $true
-$data = Get-Attr $params "data" "pong";
+$data = Get-Attr $params "data" "pong"
$result = @{
changed = $false
ping = $data
-};
+}
-Exit-Json $result;
+Exit-Json $result
diff --git a/test/integration/targets/windows-minimal/library/win_ping_throw.ps1 b/test/integration/targets/windows-minimal/library/win_ping_throw.ps1
index 7306f4d2..2fba2092 100644
--- a/test/integration/targets/windows-minimal/library/win_ping_throw.ps1
+++ b/test/integration/targets/windows-minimal/library/win_ping_throw.ps1
@@ -18,13 +18,13 @@
throw
-$params = Parse-Args $args $true;
+$params = Parse-Args $args $true
-$data = Get-Attr $params "data" "pong";
+$data = Get-Attr $params "data" "pong"
$result = @{
changed = $false
ping = $data
-};
+}
-Exit-Json $result;
+Exit-Json $result
diff --git a/test/integration/targets/windows-minimal/library/win_ping_throw_string.ps1 b/test/integration/targets/windows-minimal/library/win_ping_throw_string.ps1
index 09e3b7cb..62de8263 100644
--- a/test/integration/targets/windows-minimal/library/win_ping_throw_string.ps1
+++ b/test/integration/targets/windows-minimal/library/win_ping_throw_string.ps1
@@ -18,13 +18,13 @@
throw "no ping for you"
-$params = Parse-Args $args $true;
+$params = Parse-Args $args $true
-$data = Get-Attr $params "data" "pong";
+$data = Get-Attr $params "data" "pong"
$result = @{
changed = $false
ping = $data
-};
+}
-Exit-Json $result;
+Exit-Json $result
diff --git a/test/integration/targets/yum/aliases b/test/integration/targets/yum/aliases
index 1d491339..b12f3547 100644
--- a/test/integration/targets/yum/aliases
+++ b/test/integration/targets/yum/aliases
@@ -1,5 +1,4 @@
destructive
shippable/posix/group1
skip/freebsd
-skip/osx
skip/macos
diff --git a/test/integration/targets/yum/filter_plugins/filter_list_of_tuples_by_first_param.py b/test/integration/targets/yum/filter_plugins/filter_list_of_tuples_by_first_param.py
index 27f38ce5..306ccd9a 100644
--- a/test/integration/targets/yum/filter_plugins/filter_list_of_tuples_by_first_param.py
+++ b/test/integration/targets/yum/filter_plugins/filter_list_of_tuples_by_first_param.py
@@ -1,8 +1,6 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-from ansible.errors import AnsibleError, AnsibleFilterError
-
def filter_list_of_tuples_by_first_param(lst, search, startswith=False):
out = []