ansible-core 2.17.4rc1__py3-none-any.whl → 2.18.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ansible-core might be problematic. Click here for more details.
- ansible/__main__.py +2 -17
- ansible/cli/__init__.py +3 -15
- ansible/cli/config.py +187 -24
- ansible/cli/console.py +1 -1
- ansible/cli/doc.py +38 -16
- ansible/cli/galaxy.py +30 -53
- ansible/cli/inventory.py +2 -2
- ansible/cli/pull.py +2 -2
- ansible/cli/scripts/ansible_connection_cli_stub.py +1 -10
- ansible/config/base.yml +127 -57
- ansible/config/manager.py +89 -11
- ansible/constants.py +32 -9
- ansible/errors/__init__.py +5 -0
- ansible/executor/interpreter_discovery.py +1 -1
- ansible/executor/play_iterator.py +16 -0
- ansible/executor/playbook_executor.py +1 -4
- ansible/executor/powershell/become_wrapper.ps1 +4 -5
- ansible/executor/powershell/bootstrap_wrapper.ps1 +2 -3
- ansible/executor/powershell/exec_wrapper.ps1 +1 -1
- ansible/executor/powershell/module_manifest.py +2 -2
- ansible/executor/task_executor.py +50 -39
- ansible/executor/task_queue_manager.py +1 -1
- ansible/executor/task_result.py +1 -1
- ansible/galaxy/api.py +3 -4
- ansible/galaxy/collection/__init__.py +21 -10
- ansible/galaxy/collection/concrete_artifact_manager.py +2 -2
- ansible/galaxy/collection/galaxy_api_proxy.py +10 -16
- ansible/galaxy/collection/gpg.py +17 -23
- ansible/galaxy/data/COPYING +7 -0
- ansible/galaxy/data/apb/Dockerfile.j2 +1 -0
- ansible/galaxy/data/apb/Makefile.j2 +1 -0
- ansible/galaxy/data/apb/README.md +7 -3
- ansible/galaxy/data/apb/apb.yml.j2 +1 -0
- ansible/galaxy/data/apb/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/handlers/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/playbooks/deprovision.yml.j2 +1 -0
- ansible/galaxy/data/apb/playbooks/provision.yml.j2 +1 -0
- ansible/galaxy/data/apb/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/tests/ansible.cfg +1 -0
- ansible/galaxy/data/apb/tests/inventory +1 -0
- ansible/galaxy/data/apb/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/apb/vars/main.yml.j2 +1 -0
- ansible/galaxy/data/collections_galaxy_meta.yml +1 -0
- ansible/galaxy/data/container/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/container/handlers/main.yml.j2 +1 -0
- ansible/galaxy/data/container/meta/container.yml.j2 +1 -0
- ansible/galaxy/data/container/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/container/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/container/tests/ansible.cfg +1 -0
- ansible/galaxy/data/container/tests/inventory +1 -0
- ansible/galaxy/data/container/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/container/vars/main.yml.j2 +1 -0
- ansible/galaxy/data/default/collection/README.md.j2 +1 -0
- ansible/galaxy/data/default/collection/galaxy.yml.j2 +1 -0
- ansible/galaxy/data/default/collection/meta/runtime.yml +1 -0
- ansible/galaxy/data/default/collection/plugins/README.md.j2 +1 -0
- ansible/galaxy/data/default/role/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/handlers/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/tests/inventory +1 -0
- ansible/galaxy/data/default/role/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/default/role/vars/main.yml.j2 +1 -0
- ansible/galaxy/data/network/cliconf_plugins/example.py.j2 +1 -0
- ansible/galaxy/data/network/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/network/library/example_command.py.j2 +1 -0
- ansible/galaxy/data/network/library/example_config.py.j2 +1 -0
- ansible/galaxy/data/network/library/example_facts.py.j2 +1 -0
- ansible/galaxy/data/network/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/network/module_utils/example.py.j2 +1 -0
- ansible/galaxy/data/network/netconf_plugins/example.py.j2 +1 -0
- ansible/galaxy/data/network/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/network/terminal_plugins/example.py.j2 +1 -0
- ansible/galaxy/data/network/tests/inventory +1 -0
- ansible/galaxy/data/network/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/network/vars/main.yml.j2 +1 -0
- ansible/galaxy/dependency_resolution/providers.py +3 -3
- ansible/galaxy/role.py +1 -1
- ansible/galaxy/token.py +20 -8
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +0 -0
- ansible/module_utils/_internal/_concurrent/__init__.py +0 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +28 -0
- ansible/module_utils/_internal/_concurrent/_futures.py +21 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +2 -2
- ansible/module_utils/basic.py +14 -11
- ansible/module_utils/common/collections.py +1 -1
- ansible/module_utils/common/file.py +0 -6
- ansible/module_utils/common/process.py +22 -9
- ansible/module_utils/common/text/converters.py +5 -8
- ansible/module_utils/common/text/formatters.py +20 -4
- ansible/module_utils/common/validation.py +33 -25
- ansible/module_utils/compat/paramiko.py +6 -1
- ansible/module_utils/compat/selinux.py +2 -2
- ansible/module_utils/connection.py +8 -24
- ansible/module_utils/csharp/Ansible.Become.cs +14 -25
- ansible/module_utils/csharp/Ansible.Process.cs +1 -1
- ansible/module_utils/distro/__init__.py +1 -1
- ansible/module_utils/distro/_distro.py +8 -4
- ansible/module_utils/facts/collector.py +2 -0
- ansible/module_utils/facts/default_collectors.py +3 -1
- ansible/module_utils/facts/hardware/aix.py +54 -52
- ansible/module_utils/facts/hardware/darwin.py +37 -34
- ansible/module_utils/facts/hardware/freebsd.py +55 -15
- ansible/module_utils/facts/hardware/hpux.py +3 -0
- ansible/module_utils/facts/hardware/linux.py +101 -57
- ansible/module_utils/facts/hardware/netbsd.py +3 -0
- ansible/module_utils/facts/hardware/openbsd.py +4 -1
- ansible/module_utils/facts/hardware/sunos.py +7 -1
- ansible/module_utils/facts/network/aix.py +16 -17
- ansible/module_utils/facts/network/fc_wwn.py +4 -1
- ansible/module_utils/facts/network/hpux.py +21 -4
- ansible/module_utils/facts/network/iscsi.py +7 -8
- ansible/module_utils/facts/network/linux.py +0 -2
- ansible/module_utils/facts/other/facter.py +9 -4
- ansible/module_utils/facts/other/ohai.py +5 -5
- ansible/module_utils/facts/packages.py +49 -7
- ansible/module_utils/facts/sysctl.py +33 -31
- ansible/module_utils/facts/system/distribution.py +1 -1
- ansible/module_utils/facts/system/local.py +12 -22
- ansible/module_utils/facts/system/service_mgr.py +3 -1
- ansible/module_utils/facts/system/systemd.py +47 -0
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/splitter.py +1 -1
- ansible/modules/add_host.py +1 -1
- ansible/modules/apt.py +43 -32
- ansible/modules/apt_key.py +6 -6
- ansible/modules/apt_repository.py +23 -14
- ansible/modules/assemble.py +7 -2
- ansible/modules/assert.py +4 -4
- ansible/modules/blockinfile.py +3 -6
- ansible/modules/command.py +1 -1
- ansible/modules/copy.py +4 -4
- ansible/modules/cron.py +13 -10
- ansible/modules/deb822_repository.py +16 -17
- ansible/modules/debconf.py +9 -9
- ansible/modules/debug.py +1 -1
- ansible/modules/dnf.py +79 -164
- ansible/modules/dnf5.py +48 -31
- ansible/modules/dpkg_selections.py +2 -2
- ansible/modules/expect.py +2 -2
- ansible/modules/fetch.py +2 -2
- ansible/modules/file.py +5 -3
- ansible/modules/find.py +40 -12
- ansible/modules/gather_facts.py +4 -2
- ansible/modules/get_url.py +29 -24
- ansible/modules/git.py +35 -35
- ansible/modules/group.py +71 -1
- ansible/modules/hostname.py +2 -4
- ansible/modules/include_vars.py +5 -5
- ansible/modules/iptables.py +13 -16
- ansible/modules/known_hosts.py +16 -13
- ansible/modules/lineinfile.py +1 -4
- ansible/modules/meta.py +6 -1
- ansible/modules/mount_facts.py +651 -0
- ansible/modules/package_facts.py +63 -80
- ansible/modules/pause.py +4 -3
- ansible/modules/pip.py +14 -14
- ansible/modules/replace.py +1 -4
- ansible/modules/rpm_key.py +31 -11
- ansible/modules/service.py +8 -8
- ansible/modules/service_facts.py +20 -5
- ansible/modules/set_stats.py +1 -1
- ansible/modules/setup.py +3 -3
- ansible/modules/stat.py +3 -3
- ansible/modules/subversion.py +1 -1
- ansible/modules/systemd.py +16 -10
- ansible/modules/systemd_service.py +16 -10
- ansible/modules/sysvinit.py +4 -4
- ansible/modules/unarchive.py +35 -22
- ansible/modules/uri.py +24 -18
- ansible/modules/user.py +145 -12
- ansible/modules/validate_argument_spec.py +3 -3
- ansible/modules/wait_for_connection.py +2 -1
- ansible/modules/yum_repository.py +136 -179
- ansible/parsing/dataloader.py +2 -2
- ansible/parsing/mod_args.py +11 -10
- ansible/parsing/vault/__init__.py +8 -3
- ansible/parsing/yaml/constructor.py +10 -8
- ansible/parsing/yaml/objects.py +1 -1
- ansible/playbook/base.py +12 -23
- ansible/playbook/helpers.py +4 -0
- ansible/playbook/loop_control.py +8 -0
- ansible/playbook/play.py +4 -22
- ansible/playbook/play_context.py +0 -16
- ansible/playbook/playbook_include.py +2 -2
- ansible/playbook/role/__init__.py +2 -2
- ansible/playbook/task.py +1 -1
- ansible/plugins/__init__.py +2 -0
- ansible/plugins/action/__init__.py +7 -9
- ansible/plugins/action/reboot.py +2 -2
- ansible/plugins/become/__init__.py +1 -1
- ansible/plugins/callback/__init__.py +44 -3
- ansible/plugins/callback/default.py +1 -1
- ansible/plugins/cliconf/__init__.py +1 -1
- ansible/plugins/connection/paramiko_ssh.py +2 -80
- ansible/plugins/connection/psrp.py +33 -82
- ansible/plugins/connection/ssh.py +0 -8
- ansible/plugins/connection/winrm.py +46 -1
- ansible/plugins/doc_fragments/connection_pipelining.py +2 -2
- ansible/plugins/doc_fragments/constructed.py +10 -10
- ansible/plugins/doc_fragments/default_callback.py +8 -8
- ansible/plugins/doc_fragments/files.py +5 -5
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +6 -6
- ansible/plugins/doc_fragments/return_common.py +1 -1
- ansible/plugins/doc_fragments/shell_common.py +2 -10
- ansible/plugins/doc_fragments/shell_windows.py +0 -9
- ansible/plugins/doc_fragments/url.py +2 -2
- ansible/plugins/doc_fragments/url_windows.py +4 -5
- ansible/plugins/doc_fragments/validate.py +1 -1
- ansible/plugins/filter/core.py +2 -0
- ansible/plugins/filter/human_to_bytes.yml +9 -0
- ansible/plugins/filter/password_hash.yml +1 -1
- ansible/plugins/filter/strftime.yml +1 -1
- ansible/plugins/filter/to_nice_json.yml +7 -3
- ansible/plugins/filter/to_uuid.yml +1 -1
- ansible/plugins/inventory/script.py +1 -1
- ansible/plugins/list.py +1 -1
- ansible/plugins/loader.py +0 -11
- ansible/plugins/lookup/config.py +1 -1
- ansible/plugins/lookup/csvfile.py +21 -9
- ansible/plugins/lookup/env.py +8 -9
- ansible/plugins/lookup/ini.py +10 -1
- ansible/plugins/lookup/random_choice.py +2 -2
- ansible/plugins/lookup/url.py +7 -2
- ansible/plugins/shell/__init__.py +15 -20
- ansible/plugins/shell/powershell.py +9 -6
- ansible/plugins/strategy/__init__.py +16 -7
- ansible/plugins/test/core.py +23 -1
- ansible/plugins/test/issubset.yml +1 -1
- ansible/plugins/test/subset.yml +1 -1
- ansible/plugins/test/timedout.yml +20 -0
- ansible/plugins/test/vault_encrypted.yml +6 -6
- ansible/plugins/test/vaulted_file.yml +19 -0
- ansible/release.py +2 -2
- ansible/template/__init__.py +3 -8
- ansible/utils/collection_loader/_collection_finder.py +23 -55
- ansible/utils/display.py +44 -31
- ansible/utils/jsonrpc.py +1 -1
- ansible/utils/listify.py +1 -5
- ansible/utils/path.py +3 -0
- ansible/utils/vars.py +18 -27
- ansible/vars/manager.py +7 -150
- ansible/vars/plugins.py +1 -1
- ansible_core-2.18.0b1.dist-info/Apache-License.txt +202 -0
- {ansible_core-2.17.4rc1.dist-info → ansible_core-2.18.0b1.dist-info}/METADATA +36 -23
- ansible_core-2.18.0b1.dist-info/MIT-license.txt +14 -0
- ansible_core-2.18.0b1.dist-info/PSF-license.txt +48 -0
- {ansible_core-2.17.4rc1.dist-info → ansible_core-2.18.0b1.dist-info}/RECORD +311 -306
- {ansible_core-2.17.4rc1.dist-info → ansible_core-2.18.0b1.dist-info}/WHEEL +1 -1
- {ansible_core-2.17.4rc1.dist-info → ansible_core-2.18.0b1.dist-info}/entry_points.txt +1 -1
- ansible_core-2.18.0b1.dist-info/simplified_bsd.txt +8 -0
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +5 -4
- ansible_test/_data/completion/windows.txt +4 -4
- ansible_test/_data/requirements/ansible-test.txt +1 -2
- ansible_test/_data/requirements/constraints.txt +1 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.in +1 -1
- ansible_test/_data/requirements/sanity.changelog.txt +4 -4
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.import.txt +1 -1
- ansible_test/_data/requirements/sanity.integration-aliases.txt +1 -1
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +5 -7
- ansible_test/_data/requirements/sanity.runtime-metadata.txt +2 -2
- ansible_test/_data/requirements/sanity.validate-modules.txt +3 -3
- ansible_test/_data/requirements/sanity.yamllint.in +1 -0
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_internal/ansible_util.py +8 -35
- ansible_test/_internal/ci/azp.py +1 -1
- ansible_test/_internal/classification/__init__.py +0 -2
- ansible_test/_internal/cli/parsers/key_value_parsers.py +3 -0
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -1
- ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
- ansible_test/_internal/commands/integration/cloud/nios.py +1 -1
- ansible_test/_internal/commands/sanity/__init__.py +96 -19
- ansible_test/_internal/commands/sanity/pylint.py +20 -24
- ansible_test/_internal/completion.py +2 -0
- ansible_test/_internal/constants.py +0 -1
- ansible_test/_internal/coverage_util.py +1 -2
- ansible_test/_internal/docker_util.py +1 -1
- ansible_test/_internal/host_configs.py +10 -0
- ansible_test/_internal/host_profiles.py +9 -13
- ansible_test/_internal/pypi_proxy.py +1 -1
- ansible_test/_internal/python_requirements.py +5 -14
- ansible_test/_internal/timeout.py +1 -1
- ansible_test/_internal/util.py +40 -0
- ansible_test/_internal/util_common.py +5 -1
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.json +3 -1
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +6 -3
- ansible_test/_util/controller/sanity/code-smell/empty-init.json +0 -2
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +1 -0
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -19
- ansible_test/_util/controller/sanity/shellcheck/exclude.txt +1 -0
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +67 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +27 -5
- ansible_test/_util/target/cli/ansible_test_cli_stub.py +0 -0
- ansible_test/_util/target/common/constants.py +2 -2
- ansible_test/_util/target/injector/python.py +5 -0
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +6 -0
- ansible_test/_util/target/sanity/import/importer.py +1 -1
- ansible_test/_util/target/setup/bootstrap.sh +6 -17
- ansible_test/_util/target/setup/requirements.py +14 -20
- ansible_test/config/config.yml +1 -1
- ansible_core-2.17.4rc1.data/scripts/ansible-test +0 -44
- ansible_test/_data/requirements/sanity.mypy.in +0 -10
- ansible_test/_data/requirements/sanity.mypy.txt +0 -18
- ansible_test/_internal/commands/sanity/mypy.py +0 -274
- ansible_test/_util/controller/sanity/mypy/ansible-core.ini +0 -116
- ansible_test/_util/controller/sanity/mypy/ansible-test.ini +0 -27
- ansible_test/_util/controller/sanity/mypy/modules.ini +0 -92
- ansible_test/_util/controller/sanity/mypy/packaging.ini +0 -20
- {ansible_core-2.17.4rc1.dist-info → ansible_core-2.18.0b1.dist-info}/COPYING +0 -0
- {ansible_core-2.17.4rc1.dist-info → ansible_core-2.18.0b1.dist-info}/top_level.txt +0 -0
|
@@ -130,7 +130,7 @@ EXAMPLES = r'''# fmt: code
|
|
|
130
130
|
mandatory_options = arg_parser.add_mutually_exclusive_group()
|
|
131
131
|
mandatory_options.add_argument('--list', action='store', nargs="*", help="Get inventory JSON from our API")
|
|
132
132
|
mandatory_options.add_argument('--host', action='store',
|
|
133
|
-
help="Get variables for specific host, not used but kept for
|
|
133
|
+
help="Get variables for specific host, not used but kept for compatibility")
|
|
134
134
|
|
|
135
135
|
try:
|
|
136
136
|
config = load_config()
|
ansible/plugins/list.py
CHANGED
|
@@ -84,7 +84,7 @@ def _list_plugins_from_paths(ptype, dirs, collection, depth=0):
|
|
|
84
84
|
to_native(b_ext) in C.REJECT_EXTS, # general extensions to ignore
|
|
85
85
|
b_ext in (b'.yml', b'.yaml', b'.json'), # ignore docs files TODO: constant!
|
|
86
86
|
plugin in IGNORE.get(bkey, ()), # plugin in reject list
|
|
87
|
-
os.path.islink(full_path), # skip aliases, author should document in '
|
|
87
|
+
os.path.islink(full_path), # skip aliases, author should document in 'aliases' field
|
|
88
88
|
]):
|
|
89
89
|
continue
|
|
90
90
|
|
ansible/plugins/loader.py
CHANGED
|
@@ -1110,10 +1110,6 @@ class PluginLoader:
|
|
|
1110
1110
|
needs_enabled = False
|
|
1111
1111
|
if hasattr(obj, 'REQUIRES_ENABLED'):
|
|
1112
1112
|
needs_enabled = obj.REQUIRES_ENABLED
|
|
1113
|
-
elif hasattr(obj, 'REQUIRES_WHITELIST'):
|
|
1114
|
-
needs_enabled = obj.REQUIRES_WHITELIST
|
|
1115
|
-
display.deprecated("The VarsModule class variable 'REQUIRES_WHITELIST' is deprecated. "
|
|
1116
|
-
"Use 'REQUIRES_ENABLED' instead.", version=2.18)
|
|
1117
1113
|
if not needs_enabled:
|
|
1118
1114
|
# Use get_with_context to cache the plugin the first time we see it.
|
|
1119
1115
|
self.get_with_context(fqcn)[0]
|
|
@@ -1424,13 +1420,6 @@ def _load_plugin_filter():
|
|
|
1424
1420
|
# Modules and action plugins share the same reject list since the difference between the
|
|
1425
1421
|
# two isn't visible to the users
|
|
1426
1422
|
if version == u'1.0':
|
|
1427
|
-
|
|
1428
|
-
if 'module_blacklist' in filter_data:
|
|
1429
|
-
display.deprecated("'module_blacklist' is being removed in favor of 'module_rejectlist'", version='2.18')
|
|
1430
|
-
if 'module_rejectlist' not in filter_data:
|
|
1431
|
-
filter_data['module_rejectlist'] = filter_data['module_blacklist']
|
|
1432
|
-
del filter_data['module_blacklist']
|
|
1433
|
-
|
|
1434
1423
|
try:
|
|
1435
1424
|
filters['ansible.modules'] = frozenset(filter_data['module_rejectlist'])
|
|
1436
1425
|
except TypeError:
|
ansible/plugins/lookup/config.py
CHANGED
|
@@ -8,7 +8,7 @@ DOCUMENTATION = """
|
|
|
8
8
|
version_added: "2.5"
|
|
9
9
|
short_description: Display the 'resolved' Ansible option values.
|
|
10
10
|
description:
|
|
11
|
-
- Retrieves the value of an Ansible configuration setting, resolving all sources, from defaults, ansible.cfg,
|
|
11
|
+
- Retrieves the value of an Ansible configuration setting, resolving all sources, from defaults, ansible.cfg, environment,
|
|
12
12
|
CLI, and variables, but not keywords.
|
|
13
13
|
- The values returned assume the context of the current host or C(inventory_hostname).
|
|
14
14
|
- You can use C(ansible-config list) to see the global available settings, add C(-t all) to also show plugin options.
|
|
@@ -52,18 +52,30 @@ EXAMPLES = """
|
|
|
52
52
|
- name: msg="Match 'Li' on the first column, but return the 3rd column (columns start counting after the match)"
|
|
53
53
|
ansible.builtin.debug: msg="The atomic mass of Lithium is {{ lookup('ansible.builtin.csvfile', 'Li file=elements.csv delimiter=, col=2') }}"
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
# Contents of bgp_neighbors.csv
|
|
56
|
+
# 127.0.0.1,10.0.0.1,24,nones,lola,pepe,127.0.0.2
|
|
57
|
+
# 128.0.0.1,10.1.0.1,20,notes,lolita,pepito,128.0.0.2
|
|
58
|
+
# 129.0.0.1,10.2.0.1,23,nines,aayush,pepete,129.0.0.2
|
|
59
|
+
|
|
60
|
+
- name: Define values from CSV file, this reads file in one go, but you could also use col= to read each in it's own lookup.
|
|
56
61
|
ansible.builtin.set_fact:
|
|
57
|
-
|
|
58
|
-
int_ip: "{{ csvline[1] }}"
|
|
59
|
-
int_mask: "{{ csvline[2] }}"
|
|
60
|
-
int_name: "{{ csvline[3] }}"
|
|
61
|
-
local_as: "{{ csvline[4] }}"
|
|
62
|
-
neighbor_as: "{{ csvline[5] }}"
|
|
63
|
-
neigh_int_ip: "{{ csvline[6] }}"
|
|
62
|
+
'{{ columns[item|int] }}': "{{ csvline }}"
|
|
64
63
|
vars:
|
|
65
|
-
csvline: "{{ lookup('
|
|
64
|
+
csvline: "{{ lookup('csvfile', bgp_neighbor_ip, file='bgp_neighbors.csv', delimiter=',', col=item) }}"
|
|
65
|
+
columns: ['loop_ip', 'int_ip', 'int_mask', 'int_name', 'local_as', 'neighbour_as', 'neight_int_ip']
|
|
66
|
+
bgp_neighbor_ip: '127.0.0.1'
|
|
67
|
+
loop: '{{ range(columns|length|int) }}'
|
|
66
68
|
delegate_to: localhost
|
|
69
|
+
delegate_facts: true
|
|
70
|
+
|
|
71
|
+
# Contents of people.csv
|
|
72
|
+
# # Last,First,Email,Extension
|
|
73
|
+
# Smith,Jane,jsmith@example.com,1234
|
|
74
|
+
|
|
75
|
+
- name: Specify the column (by keycol) in which the string should be searched
|
|
76
|
+
assert:
|
|
77
|
+
that:
|
|
78
|
+
- lookup('ansible.builtin.csvfile', 'Jane', file='people.csv', delimiter=',', col=0, keycol=1) == "Smith"
|
|
67
79
|
|
|
68
80
|
# Contents of debug.csv
|
|
69
81
|
# test1 ret1.1 ret2.1
|
ansible/plugins/lookup/env.py
CHANGED
|
@@ -30,22 +30,21 @@ EXAMPLES = """
|
|
|
30
30
|
ansible.builtin.debug:
|
|
31
31
|
msg: "'{{ lookup('ansible.builtin.env', 'HOME') }}' is the HOME environment variable."
|
|
32
32
|
|
|
33
|
-
- name: Before 2.13, how to set default value if the variable is not defined
|
|
34
|
-
This cannot distinguish between USR undefined and USR=''.
|
|
33
|
+
- name: Before 2.13, how to set default value if the variable is not defined
|
|
35
34
|
ansible.builtin.debug:
|
|
36
|
-
msg: "{{ lookup('ansible.builtin.env', '
|
|
35
|
+
msg: "Hello {{ lookup('ansible.builtin.env', 'UNDEFINED_VARIABLE') | default('World', True) }}"
|
|
37
36
|
|
|
38
|
-
- name: Example how to set default value if the variable is not defined
|
|
37
|
+
- name: Example how to set default value if the variable is not defined
|
|
39
38
|
ansible.builtin.debug:
|
|
40
|
-
msg: "{{ lookup('ansible.builtin.env', '
|
|
39
|
+
msg: "Hello {{ lookup('ansible.builtin.env', 'UNDEFINED_VARIABLE', default='World') }}"
|
|
41
40
|
|
|
42
|
-
- name:
|
|
41
|
+
- name: Fail if the variable is not defined by setting default value to 'Undefined'
|
|
43
42
|
ansible.builtin.debug:
|
|
44
|
-
msg: "{{ lookup('ansible.builtin.env', '
|
|
43
|
+
msg: "Hello {{ lookup('ansible.builtin.env', 'UNDEFINED_VARIABLE', default=Undefined) }}"
|
|
45
44
|
|
|
46
|
-
- name:
|
|
45
|
+
- name: Fail if the variable is not defined by setting default value to 'undef()'
|
|
47
46
|
ansible.builtin.debug:
|
|
48
|
-
msg: "{{ lookup('ansible.builtin.env', '
|
|
47
|
+
msg: "Hello {{ lookup('ansible.builtin.env', 'UNDEFINED_VARIABLE', default=undef()) }}"
|
|
49
48
|
"""
|
|
50
49
|
|
|
51
50
|
RETURN = """
|
ansible/plugins/lookup/ini.py
CHANGED
|
@@ -49,6 +49,12 @@ DOCUMENTATION = """
|
|
|
49
49
|
default: False
|
|
50
50
|
aliases: ['allow_none']
|
|
51
51
|
version_added: '2.12'
|
|
52
|
+
interpolation:
|
|
53
|
+
description:
|
|
54
|
+
Allows for interpolation of values, see https://docs.python.org/3/library/configparser.html#configparser.BasicInterpolation
|
|
55
|
+
type: bool
|
|
56
|
+
default: True
|
|
57
|
+
version_added: '2.18'
|
|
52
58
|
seealso:
|
|
53
59
|
- ref: playbook_task_paths
|
|
54
60
|
description: Search paths used for relative files.
|
|
@@ -140,7 +146,10 @@ class LookupModule(LookupBase):
|
|
|
140
146
|
self.set_options(var_options=variables, direct=kwargs)
|
|
141
147
|
paramvals = self.get_options()
|
|
142
148
|
|
|
143
|
-
self.cp = configparser.ConfigParser(
|
|
149
|
+
self.cp = configparser.ConfigParser(
|
|
150
|
+
allow_no_value=paramvals.get('allow_no_value', paramvals.get('allow_none')),
|
|
151
|
+
interpolation=configparser.BasicInterpolation() if paramvals.get('interpolation') else None,
|
|
152
|
+
)
|
|
144
153
|
if paramvals['case_sensitive']:
|
|
145
154
|
self.cp.optionxform = to_native
|
|
146
155
|
|
|
@@ -31,7 +31,7 @@ RETURN = """
|
|
|
31
31
|
- random item
|
|
32
32
|
type: raw
|
|
33
33
|
"""
|
|
34
|
-
import
|
|
34
|
+
import secrets
|
|
35
35
|
|
|
36
36
|
from ansible.errors import AnsibleError
|
|
37
37
|
from ansible.module_utils.common.text.converters import to_native
|
|
@@ -45,7 +45,7 @@ class LookupModule(LookupBase):
|
|
|
45
45
|
ret = terms
|
|
46
46
|
if terms:
|
|
47
47
|
try:
|
|
48
|
-
ret = [
|
|
48
|
+
ret = [secrets.choice(terms)]
|
|
49
49
|
except Exception as e:
|
|
50
50
|
raise AnsibleError("Unable to choose random term: %s" % to_native(e))
|
|
51
51
|
|
ansible/plugins/lookup/url.py
CHANGED
|
@@ -103,8 +103,8 @@ options:
|
|
|
103
103
|
none: Will not follow any redirects.
|
|
104
104
|
safe: Only redirects doing GET or HEAD requests will be followed.
|
|
105
105
|
urllib2: Defer to urllib2 behavior (As of writing this follows HTTP redirects).
|
|
106
|
-
'no': (DEPRECATED,
|
|
107
|
-
'yes': (DEPRECATED,
|
|
106
|
+
'no': (DEPRECATED, removed in 2.22) alias of V(none).
|
|
107
|
+
'yes': (DEPRECATED, removed in 2.22) alias of V(all).
|
|
108
108
|
use_gssapi:
|
|
109
109
|
description:
|
|
110
110
|
- Use GSSAPI handler of requests
|
|
@@ -234,6 +234,11 @@ class LookupModule(LookupBase):
|
|
|
234
234
|
ret = []
|
|
235
235
|
for term in terms:
|
|
236
236
|
display.vvvv("url lookup connecting to %s" % term)
|
|
237
|
+
if self.get_option('follow_redirects') in ('yes', 'no'):
|
|
238
|
+
display.deprecated(
|
|
239
|
+
"Using 'yes' or 'no' for 'follow_redirects' parameter is deprecated.",
|
|
240
|
+
version='2.22'
|
|
241
|
+
)
|
|
237
242
|
try:
|
|
238
243
|
response = open_url(
|
|
239
244
|
term, validate_certs=self.get_option('validate_certs'),
|
|
@@ -18,8 +18,8 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
import os
|
|
20
20
|
import os.path
|
|
21
|
-
import random
|
|
22
21
|
import re
|
|
22
|
+
import secrets
|
|
23
23
|
import shlex
|
|
24
24
|
import time
|
|
25
25
|
|
|
@@ -38,6 +38,9 @@ class ShellBase(AnsiblePlugin):
|
|
|
38
38
|
|
|
39
39
|
super(ShellBase, self).__init__()
|
|
40
40
|
|
|
41
|
+
# Not used but here for backwards compatibility.
|
|
42
|
+
# ansible.posix.fish uses (but does not actually use) this value.
|
|
43
|
+
# https://github.com/ansible-collections/ansible.posix/blob/f41f08e9e3d3129e709e122540b5ae6bc19932be/plugins/shell/fish.py#L38-L39
|
|
41
44
|
self.env = {}
|
|
42
45
|
self.tmpdir = None
|
|
43
46
|
self.executable = None
|
|
@@ -60,18 +63,6 @@ class ShellBase(AnsiblePlugin):
|
|
|
60
63
|
|
|
61
64
|
super(ShellBase, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
|
|
62
65
|
|
|
63
|
-
# set env if needed, deal with environment's 'dual nature' list of dicts or dict
|
|
64
|
-
# TODO: config system should already resolve this so we should be able to just iterate over dicts
|
|
65
|
-
env = self.get_option('environment')
|
|
66
|
-
if isinstance(env, string_types):
|
|
67
|
-
raise AnsibleError('The "environment" keyword takes a list of dictionaries or a dictionary, not a string')
|
|
68
|
-
if not isinstance(env, Sequence):
|
|
69
|
-
env = [env]
|
|
70
|
-
for env_dict in env:
|
|
71
|
-
if not isinstance(env_dict, Mapping):
|
|
72
|
-
raise AnsibleError('The "environment" keyword takes a list of dictionaries (or single dictionary), but got a "%s" instead' % type(env_dict))
|
|
73
|
-
self.env.update(env_dict)
|
|
74
|
-
|
|
75
66
|
# We can remove the try: except in the future when we make ShellBase a proper subset of
|
|
76
67
|
# *all* shells. Right now powershell and third party shells which do not use the
|
|
77
68
|
# shell_common documentation fragment (and so do not have system_tmpdirs) will fail
|
|
@@ -82,7 +73,7 @@ class ShellBase(AnsiblePlugin):
|
|
|
82
73
|
|
|
83
74
|
@staticmethod
|
|
84
75
|
def _generate_temp_dir_name():
|
|
85
|
-
return 'ansible-tmp-%s-%s-%s' % (time.time(), os.getpid(),
|
|
76
|
+
return 'ansible-tmp-%s-%s-%s' % (time.time(), os.getpid(), secrets.randbelow(2**48))
|
|
86
77
|
|
|
87
78
|
def env_prefix(self, **kwargs):
|
|
88
79
|
return ' '.join(['%s=%s' % (k, self.quote(text_type(v))) for k, v in kwargs.items()])
|
|
@@ -101,23 +92,23 @@ class ShellBase(AnsiblePlugin):
|
|
|
101
92
|
def chmod(self, paths, mode):
|
|
102
93
|
cmd = ['chmod', mode]
|
|
103
94
|
cmd.extend(paths)
|
|
104
|
-
return
|
|
95
|
+
return self.join(cmd)
|
|
105
96
|
|
|
106
97
|
def chown(self, paths, user):
|
|
107
98
|
cmd = ['chown', user]
|
|
108
99
|
cmd.extend(paths)
|
|
109
|
-
return
|
|
100
|
+
return self.join(cmd)
|
|
110
101
|
|
|
111
102
|
def chgrp(self, paths, group):
|
|
112
103
|
cmd = ['chgrp', group]
|
|
113
104
|
cmd.extend(paths)
|
|
114
|
-
return
|
|
105
|
+
return self.join(cmd)
|
|
115
106
|
|
|
116
107
|
def set_user_facl(self, paths, user, mode):
|
|
117
108
|
"""Only sets acls for users as that's really all we need"""
|
|
118
109
|
cmd = ['setfacl', '-m', 'u:%s:%s' % (user, mode)]
|
|
119
110
|
cmd.extend(paths)
|
|
120
|
-
return
|
|
111
|
+
return self.join(cmd)
|
|
121
112
|
|
|
122
113
|
def remove(self, path, recurse=False):
|
|
123
114
|
path = self.quote(path)
|
|
@@ -138,7 +129,7 @@ class ShellBase(AnsiblePlugin):
|
|
|
138
129
|
# other users can read and access the tmp directory.
|
|
139
130
|
# This is because we use system to create tmp dirs for unprivileged users who are
|
|
140
131
|
# sudo'ing to a second unprivileged user.
|
|
141
|
-
# The 'system_tmpdirs' setting defines
|
|
132
|
+
# The 'system_tmpdirs' setting defines directories we can use for this purpose
|
|
142
133
|
# the default are, /tmp and /var/tmp.
|
|
143
134
|
# So we only allow one of those locations if system=True, using the
|
|
144
135
|
# passed in tmpdir if it is valid or the first one from the setting if not.
|
|
@@ -211,7 +202,7 @@ class ShellBase(AnsiblePlugin):
|
|
|
211
202
|
arg_path,
|
|
212
203
|
]
|
|
213
204
|
|
|
214
|
-
cleaned_up_cmd =
|
|
205
|
+
cleaned_up_cmd = self.join(
|
|
215
206
|
stripped_cmd_part for raw_cmd_part in cmd_parts
|
|
216
207
|
if raw_cmd_part and (stripped_cmd_part := raw_cmd_part.strip())
|
|
217
208
|
)
|
|
@@ -232,3 +223,7 @@ class ShellBase(AnsiblePlugin):
|
|
|
232
223
|
def quote(self, cmd):
|
|
233
224
|
"""Returns a shell-escaped string that can be safely used as one token in a shell command line"""
|
|
234
225
|
return shlex.quote(cmd)
|
|
226
|
+
|
|
227
|
+
def join(self, cmd_parts):
|
|
228
|
+
"""Returns a shell-escaped string from a list that can be safely used in a shell command line"""
|
|
229
|
+
return shlex.join(cmd_parts)
|
|
@@ -100,6 +100,8 @@ class ShellModule(ShellBase):
|
|
|
100
100
|
# Family of shells this has. Must match the filename without extension
|
|
101
101
|
SHELL_FAMILY = 'powershell'
|
|
102
102
|
|
|
103
|
+
# We try catch as some connection plugins don't have a console (PSRP).
|
|
104
|
+
_CONSOLE_ENCODING = "try { [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding } catch {}"
|
|
103
105
|
_SHELL_REDIRECT_ALLNULL = '> $null'
|
|
104
106
|
_SHELL_AND = ';'
|
|
105
107
|
|
|
@@ -157,13 +159,14 @@ class ShellModule(ShellBase):
|
|
|
157
159
|
if not basefile:
|
|
158
160
|
basefile = self.__class__._generate_temp_dir_name()
|
|
159
161
|
basefile = self._escape(self._unquote(basefile))
|
|
160
|
-
basetmpdir = tmpdir if tmpdir else self.get_option('remote_tmp')
|
|
162
|
+
basetmpdir = self._escape(tmpdir if tmpdir else self.get_option('remote_tmp'))
|
|
161
163
|
|
|
162
|
-
script = '''
|
|
163
|
-
|
|
164
|
-
$
|
|
164
|
+
script = f'''
|
|
165
|
+
{self._CONSOLE_ENCODING}
|
|
166
|
+
$tmp_path = [System.Environment]::ExpandEnvironmentVariables('{basetmpdir}')
|
|
167
|
+
$tmp = New-Item -Type Directory -Path $tmp_path -Name '{basefile}'
|
|
165
168
|
Write-Output -InputObject $tmp.FullName
|
|
166
|
-
'''
|
|
169
|
+
'''
|
|
167
170
|
return self._encode_script(script.strip())
|
|
168
171
|
|
|
169
172
|
def expand_user(self, user_home_path, username=''):
|
|
@@ -177,7 +180,7 @@ class ShellModule(ShellBase):
|
|
|
177
180
|
script = "Write-Output ((Get-Location).Path + '%s')" % self._escape(user_home_path[1:])
|
|
178
181
|
else:
|
|
179
182
|
script = "Write-Output '%s'" % self._escape(user_home_path)
|
|
180
|
-
return self._encode_script(script)
|
|
183
|
+
return self._encode_script(f"{self._CONSOLE_ENCODING}; {script}")
|
|
181
184
|
|
|
182
185
|
def exists(self, path):
|
|
183
186
|
path = self._escape(self._unquote(path))
|
|
@@ -646,7 +646,7 @@ class StrategyBase:
|
|
|
646
646
|
for result_item in result_items:
|
|
647
647
|
if '_ansible_notify' in result_item and task_result.is_changed():
|
|
648
648
|
# only ensure that notified handlers exist, if so save the notifications for when
|
|
649
|
-
# handlers are actually flushed so the last defined handlers are
|
|
649
|
+
# handlers are actually flushed so the last defined handlers are executed,
|
|
650
650
|
# otherwise depending on the setting either error or warn
|
|
651
651
|
host_state = iterator.get_state_for_host(original_host.name)
|
|
652
652
|
for notification in result_item['_ansible_notify']:
|
|
@@ -993,7 +993,7 @@ class StrategyBase:
|
|
|
993
993
|
if _evaluate_conditional(target_host):
|
|
994
994
|
for host in self._inventory.get_hosts(iterator._play.hosts):
|
|
995
995
|
if host.name not in self._tqm._unreachable_hosts:
|
|
996
|
-
iterator.
|
|
996
|
+
iterator.end_host(host.name)
|
|
997
997
|
msg = "ending batch"
|
|
998
998
|
else:
|
|
999
999
|
skipped = True
|
|
@@ -1002,7 +1002,7 @@ class StrategyBase:
|
|
|
1002
1002
|
if _evaluate_conditional(target_host):
|
|
1003
1003
|
for host in self._inventory.get_hosts(iterator._play.hosts):
|
|
1004
1004
|
if host.name not in self._tqm._unreachable_hosts:
|
|
1005
|
-
iterator.
|
|
1005
|
+
iterator.end_host(host.name)
|
|
1006
1006
|
# end_play is used in PlaybookExecutor/TQM to indicate that
|
|
1007
1007
|
# the whole play is supposed to be ended as opposed to just a batch
|
|
1008
1008
|
iterator.end_play = True
|
|
@@ -1012,8 +1012,7 @@ class StrategyBase:
|
|
|
1012
1012
|
skip_reason += ', continuing play'
|
|
1013
1013
|
elif meta_action == 'end_host':
|
|
1014
1014
|
if _evaluate_conditional(target_host):
|
|
1015
|
-
iterator.
|
|
1016
|
-
iterator._play._removed_hosts.append(target_host.name)
|
|
1015
|
+
iterator.end_host(target_host.name)
|
|
1017
1016
|
msg = "ending play for %s" % target_host.name
|
|
1018
1017
|
else:
|
|
1019
1018
|
skipped = True
|
|
@@ -1021,13 +1020,23 @@ class StrategyBase:
|
|
|
1021
1020
|
# TODO: Nix msg here? Left for historical reasons, but skip_reason exists now.
|
|
1022
1021
|
msg = "end_host conditional evaluated to false, continuing execution for %s" % target_host.name
|
|
1023
1022
|
elif meta_action == 'role_complete':
|
|
1024
|
-
# Allow users to use this in a play as reported in https://github.com/ansible/ansible/issues/22286?
|
|
1025
|
-
# How would this work with allow_duplicates??
|
|
1026
1023
|
if task.implicit:
|
|
1027
1024
|
role_obj = self._get_cached_role(task, iterator._play)
|
|
1028
1025
|
if target_host.name in role_obj._had_task_run:
|
|
1029
1026
|
role_obj._completed[target_host.name] = True
|
|
1030
1027
|
msg = 'role_complete for %s' % target_host.name
|
|
1028
|
+
elif meta_action == 'end_role':
|
|
1029
|
+
if _evaluate_conditional(target_host):
|
|
1030
|
+
while True:
|
|
1031
|
+
state, task = iterator.get_next_task_for_host(target_host, peek=True)
|
|
1032
|
+
if task.action in C._ACTION_META and task.args.get("_raw_params") == "role_complete":
|
|
1033
|
+
break
|
|
1034
|
+
iterator.set_state_for_host(target_host.name, state)
|
|
1035
|
+
display.debug("'%s' skipped because role has been ended via 'end_role'" % task)
|
|
1036
|
+
msg = 'ending role %s for %s' % (task._role.get_name(), target_host.name)
|
|
1037
|
+
else:
|
|
1038
|
+
skipped = True
|
|
1039
|
+
skip_reason += 'continuing role %s for %s' % (task._role.get_name(), target_host.name)
|
|
1031
1040
|
elif meta_action == 'reset_connection':
|
|
1032
1041
|
all_vars = self._variable_manager.get_vars(play=iterator._play, host=target_host, task=task,
|
|
1033
1042
|
_hosts=self._hosts_cache, _hosts_all=self._hosts_cache_all)
|
ansible/plugins/test/core.py
CHANGED
|
@@ -25,8 +25,9 @@ from collections.abc import MutableMapping, MutableSequence
|
|
|
25
25
|
from ansible.module_utils.compat.version import LooseVersion, StrictVersion
|
|
26
26
|
|
|
27
27
|
from ansible import errors
|
|
28
|
-
from ansible.module_utils.common.text.converters import to_native, to_text
|
|
28
|
+
from ansible.module_utils.common.text.converters import to_native, to_text, to_bytes
|
|
29
29
|
from ansible.module_utils.parsing.convert_bool import boolean
|
|
30
|
+
from ansible.parsing.vault import is_encrypted_file
|
|
30
31
|
from ansible.utils.display import Display
|
|
31
32
|
from ansible.utils.version import SemanticVersion
|
|
32
33
|
|
|
@@ -39,6 +40,13 @@ except ImportError:
|
|
|
39
40
|
display = Display()
|
|
40
41
|
|
|
41
42
|
|
|
43
|
+
def timedout(result):
|
|
44
|
+
''' Test if task result yields a time out'''
|
|
45
|
+
if not isinstance(result, MutableMapping):
|
|
46
|
+
raise errors.AnsibleFilterError("The 'timedout' test expects a dictionary")
|
|
47
|
+
return result.get('timedout', False) and result['timedout'].get('period', False)
|
|
48
|
+
|
|
49
|
+
|
|
42
50
|
def failed(result):
|
|
43
51
|
''' Test if task result yields failed '''
|
|
44
52
|
if not isinstance(result, MutableMapping):
|
|
@@ -143,6 +151,18 @@ def vault_encrypted(value):
|
|
|
143
151
|
return getattr(value, '__ENCRYPTED__', False) and value.is_encrypted()
|
|
144
152
|
|
|
145
153
|
|
|
154
|
+
def vaulted_file(value):
|
|
155
|
+
"""Evaluate whether a file is a vault
|
|
156
|
+
|
|
157
|
+
.. versionadded:: 2.18
|
|
158
|
+
"""
|
|
159
|
+
try:
|
|
160
|
+
with open(to_bytes(value), 'rb') as f:
|
|
161
|
+
return is_encrypted_file(f)
|
|
162
|
+
except (OSError, IOError) as e:
|
|
163
|
+
raise errors.AnsibleFilterError(f"Cannot test if the file {value} is a vault", orig_exc=e)
|
|
164
|
+
|
|
165
|
+
|
|
146
166
|
def match(value, pattern='', ignorecase=False, multiline=False):
|
|
147
167
|
''' Perform a `re.match` returning a boolean '''
|
|
148
168
|
return regex(value, pattern, ignorecase, multiline, 'match')
|
|
@@ -250,6 +270,7 @@ class TestModule(object):
|
|
|
250
270
|
'successful': success,
|
|
251
271
|
'reachable': reachable,
|
|
252
272
|
'unreachable': unreachable,
|
|
273
|
+
'timedout': timedout,
|
|
253
274
|
|
|
254
275
|
# changed testing
|
|
255
276
|
'changed': changed,
|
|
@@ -282,4 +303,5 @@ class TestModule(object):
|
|
|
282
303
|
|
|
283
304
|
# vault
|
|
284
305
|
'vault_encrypted': vault_encrypted,
|
|
306
|
+
'vaulted_file': vaulted_file,
|
|
285
307
|
}
|
ansible/plugins/test/subset.yml
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
DOCUMENTATION:
|
|
2
|
+
name: timedout
|
|
3
|
+
author: Ansible Core
|
|
4
|
+
version_added: "2.18"
|
|
5
|
+
short_description: did the task time out
|
|
6
|
+
description:
|
|
7
|
+
- Tests if task finished ended due to a time out
|
|
8
|
+
options:
|
|
9
|
+
_input:
|
|
10
|
+
description: registered result from an Ansible task
|
|
11
|
+
type: dictionary
|
|
12
|
+
required: True
|
|
13
|
+
EXAMPLES: |
|
|
14
|
+
# test 'status' to know how to respond
|
|
15
|
+
{{ taskresults is timedout }}
|
|
16
|
+
|
|
17
|
+
RETURN:
|
|
18
|
+
_value:
|
|
19
|
+
description: A dictionary with 2 keys 'frame' showing the 'frame of code' in which the timeout occurred and 'period' with the time limit that was enforced.
|
|
20
|
+
type: dict
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
DOCUMENTATION:
|
|
2
|
-
name:
|
|
2
|
+
name: vault_encrypted
|
|
3
3
|
author: Ansible Core
|
|
4
4
|
version_added: "2.10"
|
|
5
|
-
short_description: Is this an encrypted vault
|
|
5
|
+
short_description: Is this an encrypted vault string
|
|
6
6
|
description:
|
|
7
|
-
- Verifies if the input is an Ansible vault
|
|
7
|
+
- Verifies if the input string is an Ansible vault or not
|
|
8
8
|
options:
|
|
9
9
|
_input:
|
|
10
|
-
description: The possible vault
|
|
10
|
+
description: The possible vault string
|
|
11
11
|
type: string
|
|
12
12
|
required: True
|
|
13
13
|
EXAMPLES: |
|
|
14
|
-
thisisfalse: '{{ "any string" is
|
|
15
|
-
thisistrue: '{{ "$ANSIBLE_VAULT;1.2;AES256;dev...." is
|
|
14
|
+
thisisfalse: '{{ "any string" is vault_encryped}}'
|
|
15
|
+
thisistrue: '{{ "$ANSIBLE_VAULT;1.2;AES256;dev...." is vault_encrypted}}'
|
|
16
16
|
RETURN:
|
|
17
17
|
_value:
|
|
18
18
|
description: Returns V(True) if the input is a valid ansible vault, V(False) otherwise.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
DOCUMENTATION:
|
|
2
|
+
name: vaulted_file
|
|
3
|
+
author: Ansible Core
|
|
4
|
+
version_added: "2.18"
|
|
5
|
+
short_description: Is this file an encrypted vault
|
|
6
|
+
description:
|
|
7
|
+
- Verifies if the input path is an Ansible vault file.
|
|
8
|
+
options:
|
|
9
|
+
_input:
|
|
10
|
+
description: The path to the possible vault.
|
|
11
|
+
type: path
|
|
12
|
+
required: True
|
|
13
|
+
EXAMPLES: |
|
|
14
|
+
thisisfalse: '{{ "/etc/hosts" is vaulted_file}}'
|
|
15
|
+
thisistrue: '{{ "/path/to/vaulted/file" is vaulted_file}}'
|
|
16
|
+
RETURN:
|
|
17
|
+
_value:
|
|
18
|
+
description: Returns V(True) if the path is a valid ansible vault, V(False) otherwise.
|
|
19
|
+
type: boolean
|
ansible/release.py
CHANGED
ansible/template/__init__.py
CHANGED
|
@@ -480,7 +480,7 @@ class JinjaPluginIntercept(MutableMapping):
|
|
|
480
480
|
if self._pluginloader.type == 'filter':
|
|
481
481
|
# filter need wrapping
|
|
482
482
|
if key in C.STRING_TYPE_FILTERS:
|
|
483
|
-
# avoid
|
|
483
|
+
# avoid literal_eval when you WANT strings
|
|
484
484
|
func = _wrap_native_text(func)
|
|
485
485
|
else:
|
|
486
486
|
# conditionally unroll iterators/generators to avoid having to use `|list` after every filter
|
|
@@ -706,7 +706,7 @@ class Templar:
|
|
|
706
706
|
setattr(obj, key, original[key])
|
|
707
707
|
|
|
708
708
|
def template(self, variable, convert_bare=False, preserve_trailing_newlines=True, escape_backslashes=True, fail_on_undefined=None, overrides=None,
|
|
709
|
-
convert_data=True, static_vars=None,
|
|
709
|
+
convert_data=True, static_vars=None, disable_lookups=False):
|
|
710
710
|
'''
|
|
711
711
|
Templates (possibly recursively) any given data as input. If convert_bare is
|
|
712
712
|
set to True, the given data will be wrapped as a jinja2 variable ('{{foo}}')
|
|
@@ -714,9 +714,6 @@ class Templar:
|
|
|
714
714
|
'''
|
|
715
715
|
static_vars = [] if static_vars is None else static_vars
|
|
716
716
|
|
|
717
|
-
if cache is not None:
|
|
718
|
-
display.deprecated("The `cache` option to `Templar.template` is no longer functional, and will be removed in a future release.", version='2.18')
|
|
719
|
-
|
|
720
717
|
# Don't template unsafe variables, just return them.
|
|
721
718
|
if hasattr(variable, '__UNSAFE__'):
|
|
722
719
|
return variable
|
|
@@ -883,11 +880,9 @@ class Templar:
|
|
|
883
880
|
return [] if wantlist else None
|
|
884
881
|
|
|
885
882
|
if not is_sequence(ran):
|
|
886
|
-
|
|
883
|
+
raise AnsibleLookupError(
|
|
887
884
|
f'The lookup plugin \'{name}\' was expected to return a list, got \'{type(ran)}\' instead. '
|
|
888
885
|
f'The lookup plugin \'{name}\' needs to be changed to return a list. '
|
|
889
|
-
'This will be an error in Ansible 2.18',
|
|
890
|
-
version='2.18'
|
|
891
886
|
)
|
|
892
887
|
|
|
893
888
|
if ran and allow_unsafe is False:
|