ansible-core 2.19.4__py3-none-any.whl → 2.20.0__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/_internal/__init__.py +1 -4
- ansible/_internal/_ansiballz/_builder.py +1 -3
- ansible/_internal/_collection_proxy.py +7 -9
- ansible/_internal/_json/__init__.py +3 -4
- ansible/_internal/_templating/_engine.py +1 -1
- ansible/_internal/_templating/_jinja_plugins.py +1 -2
- ansible/_internal/_wrapt.py +105 -301
- ansible/cli/__init__.py +11 -10
- ansible/cli/adhoc.py +1 -2
- ansible/cli/arguments/option_helpers.py +1 -1
- ansible/cli/config.py +5 -6
- ansible/cli/doc.py +67 -67
- ansible/cli/galaxy.py +15 -24
- ansible/cli/inventory.py +0 -1
- ansible/cli/playbook.py +0 -1
- ansible/cli/pull.py +0 -1
- ansible/cli/scripts/ansible_connection_cli_stub.py +1 -1
- ansible/config/base.yml +1 -25
- ansible/config/manager.py +0 -2
- ansible/executor/play_iterator.py +42 -20
- ansible/executor/playbook_executor.py +0 -9
- ansible/executor/task_executor.py +26 -18
- ansible/executor/task_queue_manager.py +1 -3
- ansible/galaxy/api.py +33 -80
- ansible/galaxy/collection/__init__.py +11 -21
- ansible/galaxy/dependency_resolution/__init__.py +10 -9
- ansible/galaxy/dependency_resolution/dataclasses.py +86 -70
- ansible/galaxy/dependency_resolution/providers.py +54 -134
- ansible/galaxy/dependency_resolution/versioning.py +2 -4
- ansible/galaxy/role.py +1 -33
- ansible/inventory/manager.py +2 -3
- ansible/keyword_desc.yml +0 -3
- ansible/module_utils/_internal/_datatag/__init__.py +2 -10
- ansible/module_utils/_internal/_no_six.py +86 -0
- ansible/module_utils/_text.py +28 -8
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/basic.py +26 -23
- ansible/module_utils/common/_collections_compat.py +11 -2
- ansible/module_utils/common/collections.py +8 -3
- ansible/module_utils/common/dict_transformations.py +1 -2
- ansible/module_utils/common/network.py +4 -2
- ansible/module_utils/common/parameters.py +32 -41
- ansible/module_utils/common/text/converters.py +109 -23
- ansible/module_utils/common/text/formatters.py +6 -2
- ansible/module_utils/common/validation.py +11 -9
- ansible/module_utils/connection.py +8 -3
- ansible/module_utils/facts/hardware/linux.py +23 -7
- ansible/module_utils/facts/hardware/netbsd.py +1 -1
- ansible/module_utils/facts/hardware/sunos.py +2 -1
- ansible/module_utils/facts/packages.py +6 -2
- ansible/module_utils/facts/system/distribution.py +2 -1
- ansible/module_utils/facts/system/env.py +6 -3
- ansible/module_utils/facts/system/local.py +3 -1
- ansible/module_utils/parsing/convert_bool.py +6 -2
- ansible/module_utils/service.py +2 -3
- ansible/module_utils/six/__init__.py +11 -6
- ansible/module_utils/yumdnf.py +0 -5
- ansible/modules/apt.py +18 -13
- ansible/modules/apt_repository.py +1 -1
- ansible/modules/assemble.py +5 -9
- ansible/modules/blockinfile.py +39 -23
- ansible/modules/cron.py +26 -35
- ansible/modules/deb822_repository.py +83 -12
- ansible/modules/dnf.py +3 -7
- ansible/modules/dnf5.py +4 -6
- ansible/modules/expect.py +0 -3
- ansible/modules/find.py +1 -2
- ansible/modules/get_url.py +1 -1
- ansible/modules/git.py +4 -5
- ansible/modules/include_vars.py +1 -1
- ansible/modules/known_hosts.py +7 -1
- ansible/modules/lineinfile.py +71 -63
- ansible/modules/package_facts.py +1 -1
- ansible/modules/pip.py +8 -2
- ansible/modules/replace.py +6 -6
- ansible/modules/service.py +3 -4
- ansible/modules/stat.py +20 -0
- ansible/modules/uri.py +9 -10
- ansible/modules/user.py +1 -2
- ansible/modules/wait_for.py +2 -2
- ansible/modules/wait_for_connection.py +2 -1
- ansible/modules/yum_repository.py +1 -16
- ansible/parsing/dataloader.py +24 -31
- ansible/parsing/vault/__init__.py +1 -2
- ansible/playbook/base.py +8 -56
- ansible/playbook/block.py +0 -60
- ansible/playbook/collectionsearch.py +1 -2
- ansible/playbook/handler.py +1 -7
- ansible/playbook/helpers.py +0 -7
- ansible/playbook/included_file.py +1 -1
- ansible/playbook/play.py +102 -36
- ansible/playbook/play_context.py +4 -0
- ansible/playbook/role/__init__.py +10 -65
- ansible/playbook/role/definition.py +3 -4
- ansible/playbook/role/include.py +2 -3
- ansible/playbook/role/metadata.py +1 -12
- ansible/playbook/role/requirement.py +1 -2
- ansible/playbook/role_include.py +1 -2
- ansible/playbook/taggable.py +16 -5
- ansible/playbook/task.py +11 -50
- ansible/plugins/action/__init__.py +20 -19
- ansible/plugins/action/add_host.py +1 -2
- ansible/plugins/action/fetch.py +3 -5
- ansible/plugins/action/group_by.py +1 -2
- ansible/plugins/action/include_vars.py +20 -22
- ansible/plugins/action/script.py +1 -3
- ansible/plugins/action/template.py +1 -2
- ansible/plugins/action/uri.py +4 -2
- ansible/plugins/cache/__init__.py +1 -0
- ansible/plugins/callback/__init__.py +13 -6
- ansible/plugins/connection/__init__.py +3 -7
- ansible/plugins/connection/local.py +2 -3
- ansible/plugins/connection/psrp.py +0 -2
- ansible/plugins/connection/ssh.py +2 -7
- ansible/plugins/connection/winrm.py +0 -2
- ansible/plugins/doc_fragments/result_format_callback.py +15 -0
- ansible/plugins/filter/core.py +4 -5
- ansible/plugins/filter/encryption.py +3 -27
- ansible/plugins/filter/mathstuff.py +1 -2
- ansible/plugins/filter/to_nice_yaml.yml +31 -3
- ansible/plugins/filter/to_yaml.yml +29 -12
- ansible/plugins/inventory/__init__.py +1 -2
- ansible/plugins/inventory/toml.py +3 -6
- ansible/plugins/inventory/yaml.py +1 -2
- ansible/plugins/loader.py +3 -4
- ansible/plugins/lookup/password.py +1 -2
- ansible/plugins/lookup/subelements.py +2 -3
- ansible/plugins/lookup/url.py +1 -1
- ansible/plugins/lookup/varnames.py +1 -2
- ansible/plugins/shell/__init__.py +9 -4
- ansible/plugins/shell/powershell.py +8 -24
- ansible/plugins/strategy/__init__.py +5 -2
- ansible/plugins/test/core.py +4 -1
- ansible/plugins/test/falsy.yml +1 -1
- ansible/plugins/test/regex.yml +18 -6
- ansible/plugins/test/truthy.yml +1 -1
- ansible/release.py +2 -2
- ansible/template/__init__.py +3 -7
- ansible/utils/collection_loader/_collection_config.py +5 -0
- ansible/utils/collection_loader/_collection_finder.py +11 -14
- ansible/utils/context_objects.py +7 -4
- ansible/utils/display.py +7 -6
- ansible/utils/encrypt.py +0 -5
- ansible/utils/helpers.py +6 -2
- ansible/utils/jsonrpc.py +7 -3
- ansible/utils/plugin_docs.py +49 -38
- ansible/utils/ssh_functions.py +0 -19
- ansible/utils/unsafe_proxy.py +7 -7
- ansible/vars/clean.py +2 -3
- ansible/vars/manager.py +28 -22
- ansible/vars/plugins.py +1 -31
- {ansible_core-2.19.4.dist-info → ansible_core-2.20.0.dist-info}/METADATA +4 -4
- {ansible_core-2.19.4.dist-info → ansible_core-2.20.0.dist-info}/RECORD +213 -214
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/network.txt +0 -1
- ansible_test/_data/completion/remote.txt +4 -4
- ansible_test/_data/requirements/ansible-test.txt +1 -1
- ansible_test/_data/requirements/ansible.txt +1 -1
- ansible_test/_data/requirements/sanity.ansible-doc.txt +2 -2
- ansible_test/_data/requirements/sanity.changelog.txt +2 -2
- 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 +6 -6
- ansible_test/_data/requirements/sanity.runtime-metadata.txt +1 -1
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_internal/cache.py +2 -5
- ansible_test/_internal/cli/compat.py +1 -1
- ansible_test/_internal/commands/coverage/combine.py +1 -3
- ansible_test/_internal/commands/integration/__init__.py +3 -7
- ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
- ansible_test/_internal/commands/integration/coverage.py +1 -3
- ansible_test/_internal/commands/integration/filters.py +5 -10
- ansible_test/_internal/commands/sanity/pylint.py +11 -0
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -5
- ansible_test/_internal/commands/units/__init__.py +1 -13
- ansible_test/_internal/compat/packaging.py +2 -2
- ansible_test/_internal/compat/yaml.py +2 -2
- ansible_test/_internal/completion.py +2 -5
- ansible_test/_internal/config.py +2 -7
- ansible_test/_internal/coverage_util.py +1 -1
- ansible_test/_internal/delegation.py +2 -0
- ansible_test/_internal/docker_util.py +1 -1
- ansible_test/_internal/host_profiles.py +6 -11
- ansible_test/_internal/provider/__init__.py +2 -5
- ansible_test/_internal/provisioning.py +2 -5
- ansible_test/_internal/pypi_proxy.py +1 -1
- ansible_test/_internal/python_requirements.py +1 -1
- ansible_test/_internal/target.py +2 -6
- ansible_test/_internal/thread.py +1 -4
- ansible_test/_internal/util.py +9 -14
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +14 -19
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +48 -45
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +9 -7
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +51 -37
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +31 -18
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +1 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +59 -71
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -2
- ansible_test/_util/target/cli/ansible_test_cli_stub.py +4 -2
- ansible_test/_util/target/common/constants.py +2 -2
- ansible_test/_util/target/setup/bootstrap.sh +0 -6
- ansible/utils/py3compat.py +0 -27
- ansible_test/_data/pytest/config/legacy.ini +0 -4
- {ansible_core-2.19.4.dist-info → ansible_core-2.20.0.dist-info}/WHEEL +0 -0
- {ansible_core-2.19.4.dist-info → ansible_core-2.20.0.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.19.4.dist-info → ansible_core-2.20.0.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.19.4.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.19.4.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
- {ansible_core-2.19.4.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.19.4.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.19.4.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.19.4.dist-info → ansible_core-2.20.0.dist-info}/top_level.txt +0 -0
ansible/modules/cron.py
CHANGED
|
@@ -219,20 +219,20 @@ import os
|
|
|
219
219
|
import platform
|
|
220
220
|
import pwd
|
|
221
221
|
import re
|
|
222
|
+
import shlex
|
|
222
223
|
import sys
|
|
223
224
|
import tempfile
|
|
224
225
|
|
|
225
226
|
from ansible.module_utils.basic import AnsibleModule
|
|
226
227
|
from ansible.module_utils.common.file import S_IRWU_RWG_RWO
|
|
227
228
|
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
|
228
|
-
from ansible.module_utils.six.moves import shlex_quote
|
|
229
229
|
|
|
230
230
|
|
|
231
231
|
class CronTabError(Exception):
|
|
232
232
|
pass
|
|
233
233
|
|
|
234
234
|
|
|
235
|
-
class CronTab
|
|
235
|
+
class CronTab:
|
|
236
236
|
"""
|
|
237
237
|
CronTab object to write time based crontab file
|
|
238
238
|
|
|
@@ -243,8 +243,8 @@ class CronTab(object):
|
|
|
243
243
|
def __init__(self, module, user=None, cron_file=None):
|
|
244
244
|
self.module = module
|
|
245
245
|
self.user = user
|
|
246
|
-
self.root =
|
|
247
|
-
self.lines =
|
|
246
|
+
self.root = os.getuid() == 0
|
|
247
|
+
self.lines = []
|
|
248
248
|
self.ansible = "#Ansible: "
|
|
249
249
|
self.n_existing = ''
|
|
250
250
|
self.cron_cmd = self.module.get_bin_path('crontab', required=True)
|
|
@@ -264,7 +264,6 @@ class CronTab(object):
|
|
|
264
264
|
|
|
265
265
|
def read(self):
|
|
266
266
|
# Read in the crontab from the system
|
|
267
|
-
self.lines = []
|
|
268
267
|
if self.cron_file:
|
|
269
268
|
# read the cronfile
|
|
270
269
|
try:
|
|
@@ -280,7 +279,7 @@ class CronTab(object):
|
|
|
280
279
|
# FIXME: using safely quoted shell for now, but this really should be two non-shell calls instead.
|
|
281
280
|
(rc, out, err) = self.module.run_command(self._read_user_execute(), use_unsafe_shell=True)
|
|
282
281
|
|
|
283
|
-
if rc
|
|
282
|
+
if rc not in (0, 1): # 1 can mean that there are no jobs.
|
|
284
283
|
raise CronTabError("Unable to read crontab")
|
|
285
284
|
|
|
286
285
|
self.n_existing = out
|
|
@@ -300,11 +299,10 @@ class CronTab(object):
|
|
|
300
299
|
def is_empty(self):
|
|
301
300
|
if len(self.lines) == 0:
|
|
302
301
|
return True
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
return True
|
|
302
|
+
for line in self.lines:
|
|
303
|
+
if line.strip():
|
|
304
|
+
return False
|
|
305
|
+
return True
|
|
308
306
|
|
|
309
307
|
def write(self, backup_file=None):
|
|
310
308
|
"""
|
|
@@ -451,13 +449,10 @@ class CronTab(object):
|
|
|
451
449
|
if special:
|
|
452
450
|
if self.cron_file:
|
|
453
451
|
return "%s@%s %s %s" % (disable_prefix, special, self.user, job)
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
return "%s%s %s %s %s %s %s %s" % (disable_prefix, minute, hour, day, month, weekday, self.user, job)
|
|
459
|
-
else:
|
|
460
|
-
return "%s%s %s %s %s %s %s" % (disable_prefix, minute, hour, day, month, weekday, job)
|
|
452
|
+
return "%s@%s %s" % (disable_prefix, special, job)
|
|
453
|
+
if self.cron_file:
|
|
454
|
+
return "%s%s %s %s %s %s %s %s" % (disable_prefix, minute, hour, day, month, weekday, self.user, job)
|
|
455
|
+
return "%s%s %s %s %s %s %s" % (disable_prefix, minute, hour, day, month, weekday, job)
|
|
461
456
|
|
|
462
457
|
def get_jobnames(self):
|
|
463
458
|
jobnames = []
|
|
@@ -495,8 +490,7 @@ class CronTab(object):
|
|
|
495
490
|
|
|
496
491
|
if len(newlines) == 0:
|
|
497
492
|
return True
|
|
498
|
-
|
|
499
|
-
return False # TODO add some more error testing
|
|
493
|
+
return False # TODO add some more error testing
|
|
500
494
|
|
|
501
495
|
def _update_env(self, name, decl, addenvfunction):
|
|
502
496
|
newlines = []
|
|
@@ -529,13 +523,13 @@ class CronTab(object):
|
|
|
529
523
|
user = ''
|
|
530
524
|
if self.user:
|
|
531
525
|
if platform.system() == 'SunOS':
|
|
532
|
-
return "su %s -c '%s -l'" % (
|
|
533
|
-
|
|
534
|
-
return "%s -l %s" % (
|
|
535
|
-
|
|
536
|
-
return "%s %s %s" % (self.cron_cmd, '-l',
|
|
537
|
-
|
|
538
|
-
user = '-u %s' %
|
|
526
|
+
return "su %s -c '%s -l'" % (shlex.quote(self.user), shlex.quote(self.cron_cmd))
|
|
527
|
+
if platform.system() == 'AIX':
|
|
528
|
+
return "%s -l %s" % (shlex.quote(self.cron_cmd), shlex.quote(self.user))
|
|
529
|
+
if platform.system() == 'HP-UX':
|
|
530
|
+
return "%s %s %s" % (self.cron_cmd, '-l', shlex.quote(self.user))
|
|
531
|
+
if pwd.getpwuid(os.getuid())[0] != self.user:
|
|
532
|
+
user = '-u %s' % shlex.quote(self.user)
|
|
539
533
|
return "%s %s %s" % (self.cron_cmd, user, '-l')
|
|
540
534
|
|
|
541
535
|
def _write_execute(self, path):
|
|
@@ -546,10 +540,10 @@ class CronTab(object):
|
|
|
546
540
|
if self.user:
|
|
547
541
|
if platform.system() in ['SunOS', 'HP-UX', 'AIX']:
|
|
548
542
|
return "chown %s %s ; su '%s' -c '%s %s'" % (
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
user = '-u %s' %
|
|
552
|
-
return "%s %s %s" % (self.cron_cmd, user,
|
|
543
|
+
shlex.quote(self.user), shlex.quote(path), shlex.quote(self.user), self.cron_cmd, shlex.quote(path))
|
|
544
|
+
if pwd.getpwuid(os.getuid())[0] != self.user:
|
|
545
|
+
user = '-u %s' % shlex.quote(self.user)
|
|
546
|
+
return "%s %s %s" % (self.cron_cmd, user, shlex.quote(path))
|
|
553
547
|
|
|
554
548
|
|
|
555
549
|
def main():
|
|
@@ -668,7 +662,7 @@ def main():
|
|
|
668
662
|
|
|
669
663
|
# if requested make a backup before making a change
|
|
670
664
|
if backup and not module.check_mode:
|
|
671
|
-
(
|
|
665
|
+
(dummy, backup_file) = tempfile.mkstemp(prefix='crontab')
|
|
672
666
|
crontab.write(backup_file)
|
|
673
667
|
|
|
674
668
|
if env:
|
|
@@ -763,9 +757,6 @@ def main():
|
|
|
763
757
|
|
|
764
758
|
module.exit_json(**res_args)
|
|
765
759
|
|
|
766
|
-
# --- should never get here
|
|
767
|
-
module.exit_json(msg="Unable to execute cron task.")
|
|
768
|
-
|
|
769
760
|
|
|
770
761
|
if __name__ == '__main__':
|
|
771
762
|
main()
|
|
@@ -67,6 +67,17 @@ options:
|
|
|
67
67
|
- Determines the path to the C(InRelease) file, relative to the normal
|
|
68
68
|
position of an C(InRelease) file.
|
|
69
69
|
type: str
|
|
70
|
+
install_python_debian:
|
|
71
|
+
description:
|
|
72
|
+
- Whether to automatically try to install the Python C(debian) library or not, if it is not already installed.
|
|
73
|
+
Without this library, the module does not work.
|
|
74
|
+
- Runs C(apt install python3-debian).
|
|
75
|
+
- Only works with the system Python. If you are using a Python on the remote that is not
|
|
76
|
+
the system Python, set O(install_python_debian=false) and ensure that the Python C(debian) library
|
|
77
|
+
for your Python version is installed some other way.
|
|
78
|
+
type: bool
|
|
79
|
+
default: false
|
|
80
|
+
version_added: '2.20'
|
|
70
81
|
languages:
|
|
71
82
|
description:
|
|
72
83
|
- Defines which languages information such as translated
|
|
@@ -228,6 +239,7 @@ key_filename:
|
|
|
228
239
|
|
|
229
240
|
import os
|
|
230
241
|
import re
|
|
242
|
+
import sys
|
|
231
243
|
import tempfile
|
|
232
244
|
import textwrap
|
|
233
245
|
|
|
@@ -235,9 +247,9 @@ from ansible.module_utils.basic import AnsibleModule
|
|
|
235
247
|
from ansible.module_utils.basic import missing_required_lib
|
|
236
248
|
from ansible.module_utils.common.collections import is_sequence
|
|
237
249
|
from ansible.module_utils.common.file import S_IRWXU_RXG_RXO, S_IRWU_RG_RO
|
|
250
|
+
from ansible.module_utils.common.respawn import has_respawned, probe_interpreters_for_module, respawn_module
|
|
238
251
|
from ansible.module_utils.common.text.converters import to_bytes
|
|
239
252
|
from ansible.module_utils.common.text.converters import to_native
|
|
240
|
-
from ansible.module_utils.six import raise_from # type: ignore[attr-defined]
|
|
241
253
|
from ansible.module_utils.urls import generic_urlparse
|
|
242
254
|
from ansible.module_utils.urls import open_url
|
|
243
255
|
from ansible.module_utils.urls import get_user_agent
|
|
@@ -326,7 +338,7 @@ def write_signed_by_key(module, v, slug):
|
|
|
326
338
|
try:
|
|
327
339
|
r = open_url(v, http_agent=get_user_agent())
|
|
328
340
|
except Exception as exc:
|
|
329
|
-
|
|
341
|
+
raise RuntimeError('Could not fetch signed_by key.') from exc
|
|
330
342
|
else:
|
|
331
343
|
b_data = r.read()
|
|
332
344
|
else:
|
|
@@ -357,6 +369,21 @@ def write_signed_by_key(module, v, slug):
|
|
|
357
369
|
return changed, filename, None
|
|
358
370
|
|
|
359
371
|
|
|
372
|
+
def install_python_debian(module, deb_pkg_name):
|
|
373
|
+
|
|
374
|
+
if not module.check_mode:
|
|
375
|
+
apt_path = module.get_bin_path('apt', required=True)
|
|
376
|
+
if apt_path:
|
|
377
|
+
rc, so, se = module.run_command([apt_path, 'update'])
|
|
378
|
+
if rc != 0:
|
|
379
|
+
module.fail_json(msg=f"Failed update while auto installing {deb_pkg_name} due to '{se.strip()}'")
|
|
380
|
+
rc, so, se = module.run_command([apt_path, 'install', deb_pkg_name, '-y', '-q'])
|
|
381
|
+
if rc != 0:
|
|
382
|
+
module.fail_json(msg=f"Failed to auto-install {deb_pkg_name} due to : '{se.strip()}'")
|
|
383
|
+
else:
|
|
384
|
+
module.fail_json(msg=f"{deb_pkg_name} must be installed to use check mode")
|
|
385
|
+
|
|
386
|
+
|
|
360
387
|
def main():
|
|
361
388
|
module = AnsibleModule(
|
|
362
389
|
argument_spec={
|
|
@@ -395,6 +422,10 @@ def main():
|
|
|
395
422
|
'inrelease_path': {
|
|
396
423
|
'type': 'str',
|
|
397
424
|
},
|
|
425
|
+
'install_python_debian': {
|
|
426
|
+
'type': 'bool',
|
|
427
|
+
'default': False,
|
|
428
|
+
},
|
|
398
429
|
'languages': {
|
|
399
430
|
'elements': 'str',
|
|
400
431
|
'type': 'list',
|
|
@@ -453,8 +484,53 @@ def main():
|
|
|
453
484
|
)
|
|
454
485
|
|
|
455
486
|
if not HAS_DEBIAN:
|
|
456
|
-
|
|
457
|
-
|
|
487
|
+
deb_pkg_name = 'python3-debian'
|
|
488
|
+
# This interpreter can't see the debian Python library- we'll do the following to try and fix that as per
|
|
489
|
+
# the apt_repository module:
|
|
490
|
+
# 1) look in common locations for system-owned interpreters that can see it; if we find one, respawn under it
|
|
491
|
+
# 2) finding none, try to install a matching python-debian package for the current interpreter version;
|
|
492
|
+
# we limit to the current interpreter version to try and avoid installing a whole other Python just
|
|
493
|
+
# for deb support
|
|
494
|
+
# 3) if we installed a support package, try to respawn under what we think is the right interpreter (could be
|
|
495
|
+
# the current interpreter again, but we'll let it respawn anyway for simplicity)
|
|
496
|
+
# 4) if still not working, return an error and give up (some corner cases not covered, but this shouldn't be
|
|
497
|
+
# made any more complex than it already is to try and cover more, eg, custom interpreters taking over
|
|
498
|
+
# system locations)
|
|
499
|
+
|
|
500
|
+
if has_respawned():
|
|
501
|
+
# this shouldn't be possible; short-circuit early if it happens...
|
|
502
|
+
module.fail_json(msg=f"{deb_pkg_name} must be installed and visible from {sys.executable}.")
|
|
503
|
+
|
|
504
|
+
interpreters = ['/usr/bin/python3', '/usr/bin/python']
|
|
505
|
+
|
|
506
|
+
interpreter = probe_interpreters_for_module(interpreters, 'debian')
|
|
507
|
+
|
|
508
|
+
if interpreter:
|
|
509
|
+
# found the Python bindings; respawn this module under the interpreter where we found them
|
|
510
|
+
respawn_module(interpreter)
|
|
511
|
+
# this is the end of the line for this process, it will exit here once the respawned module has completed
|
|
512
|
+
|
|
513
|
+
# don't make changes if we're in check_mode
|
|
514
|
+
if module.check_mode:
|
|
515
|
+
module.fail_json(msg=f"{deb_pkg_name} must be installed to use check mode. If run with install_python_debian, this module can auto-install it.")
|
|
516
|
+
|
|
517
|
+
if module.params['install_python_debian']:
|
|
518
|
+
install_python_debian(module, deb_pkg_name)
|
|
519
|
+
else:
|
|
520
|
+
module.fail_json(msg=f'{deb_pkg_name} is not installed, and install_python_debian is False')
|
|
521
|
+
|
|
522
|
+
# try again to find the bindings in common places
|
|
523
|
+
interpreter = probe_interpreters_for_module(interpreters, 'debian')
|
|
524
|
+
|
|
525
|
+
if interpreter:
|
|
526
|
+
# found the Python bindings; respawn this module under the interpreter where we found them
|
|
527
|
+
# NB: respawn is somewhat wasteful if it's this interpreter, but simplifies the code
|
|
528
|
+
respawn_module(interpreter)
|
|
529
|
+
# this is the end of the line for this process, it will exit here once the respawned module has completed
|
|
530
|
+
else:
|
|
531
|
+
# we've done all we can do; just tell the user it's busted and get out
|
|
532
|
+
module.fail_json(msg=missing_required_lib(deb_pkg_name),
|
|
533
|
+
exception=DEBIAN_IMP_ERR)
|
|
458
534
|
|
|
459
535
|
check_mode = module.check_mode
|
|
460
536
|
|
|
@@ -510,14 +586,9 @@ def main():
|
|
|
510
586
|
elif is_sequence(value):
|
|
511
587
|
value = format_list(value)
|
|
512
588
|
elif key == 'signed_by':
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
changed |= key_changed
|
|
517
|
-
except RuntimeError as exc:
|
|
518
|
-
module.fail_json(
|
|
519
|
-
msg='Could not fetch signed_by key: %s' % to_native(exc)
|
|
520
|
-
)
|
|
589
|
+
key_changed, signed_by_filename, signed_by_data = write_signed_by_key(module, value, slug)
|
|
590
|
+
value = signed_by_filename or signed_by_data
|
|
591
|
+
changed |= key_changed
|
|
521
592
|
|
|
522
593
|
if value.count('\n') > 0:
|
|
523
594
|
value = format_multiline(value)
|
ansible/modules/dnf.py
CHANGED
|
@@ -213,13 +213,6 @@ options:
|
|
|
213
213
|
type: bool
|
|
214
214
|
default: "no"
|
|
215
215
|
version_added: "2.7"
|
|
216
|
-
install_repoquery:
|
|
217
|
-
description:
|
|
218
|
-
- This is effectively a no-op in DNF as it is not needed with DNF.
|
|
219
|
-
- This option is deprecated and will be removed in ansible-core 2.20.
|
|
220
|
-
type: bool
|
|
221
|
-
default: "yes"
|
|
222
|
-
version_added: "2.7"
|
|
223
216
|
download_only:
|
|
224
217
|
description:
|
|
225
218
|
- Only download the packages, do not install them.
|
|
@@ -544,6 +537,9 @@ class DnfModule(YumDnf):
|
|
|
544
537
|
conf.sslverify = sslverify
|
|
545
538
|
|
|
546
539
|
# Set installroot
|
|
540
|
+
if not os.path.isdir(installroot):
|
|
541
|
+
self.module.fail_json(msg=f"Installroot {installroot} must be a directory")
|
|
542
|
+
|
|
547
543
|
conf.installroot = installroot
|
|
548
544
|
|
|
549
545
|
# Load substitutions from the filesystem
|
ansible/modules/dnf5.py
CHANGED
|
@@ -182,12 +182,6 @@ options:
|
|
|
182
182
|
using this in combination with wildcard characters in O(name) may result in an unexpected results.
|
|
183
183
|
type: bool
|
|
184
184
|
default: "no"
|
|
185
|
-
install_repoquery:
|
|
186
|
-
description:
|
|
187
|
-
- This is effectively a no-op in DNF as it is not needed with DNF.
|
|
188
|
-
- This option is deprecated and will be removed in ansible-core 2.20.
|
|
189
|
-
type: bool
|
|
190
|
-
default: "yes"
|
|
191
185
|
download_only:
|
|
192
186
|
description:
|
|
193
187
|
- Only download the packages, do not install them.
|
|
@@ -601,6 +595,10 @@ class Dnf5Module(YumDnf):
|
|
|
601
595
|
conf.localpkg_gpgcheck = not self.disable_gpg_check
|
|
602
596
|
conf.sslverify = self.sslverify
|
|
603
597
|
conf.clean_requirements_on_remove = self.autoremove
|
|
598
|
+
|
|
599
|
+
if not os.path.isdir(self.installroot):
|
|
600
|
+
self.module.fail_json(msg=f"Installroot {self.installroot} must be a directory")
|
|
601
|
+
|
|
604
602
|
conf.installroot = self.installroot
|
|
605
603
|
conf.use_host_config = True # needed for installroot
|
|
606
604
|
conf.cacheonly = "all" if self.cacheonly else "none"
|
ansible/modules/expect.py
CHANGED
ansible/modules/find.py
CHANGED
|
@@ -291,7 +291,6 @@ import time
|
|
|
291
291
|
|
|
292
292
|
from ansible.module_utils.common.text.converters import to_text, to_native
|
|
293
293
|
from ansible.module_utils.basic import AnsibleModule
|
|
294
|
-
from ansible.module_utils.six import string_types
|
|
295
294
|
|
|
296
295
|
|
|
297
296
|
class _Object:
|
|
@@ -496,7 +495,7 @@ def main():
|
|
|
496
495
|
|
|
497
496
|
params = module.params
|
|
498
497
|
|
|
499
|
-
if params['mode'] and not isinstance(params['mode'],
|
|
498
|
+
if params['mode'] and not isinstance(params['mode'], str):
|
|
500
499
|
module.fail_json(
|
|
501
500
|
msg="argument 'mode' is not a string and conversion is not allowed, value is of type %s" % params['mode'].__class__.__name__
|
|
502
501
|
)
|
ansible/modules/get_url.py
CHANGED
|
@@ -374,9 +374,9 @@ import shutil
|
|
|
374
374
|
import tempfile
|
|
375
375
|
|
|
376
376
|
from datetime import datetime, timezone
|
|
377
|
+
from urllib.parse import urlsplit
|
|
377
378
|
|
|
378
379
|
from ansible.module_utils.basic import AnsibleModule
|
|
379
|
-
from ansible.module_utils.six.moves.urllib.parse import urlsplit
|
|
380
380
|
from ansible.module_utils.common.text.converters import to_native
|
|
381
381
|
from ansible.module_utils.urls import fetch_url, url_argument_spec
|
|
382
382
|
|
ansible/modules/git.py
CHANGED
|
@@ -343,7 +343,6 @@ from ansible.module_utils.common.text.converters import to_native, to_text
|
|
|
343
343
|
from ansible.module_utils.basic import AnsibleModule
|
|
344
344
|
from ansible.module_utils.common.locale import get_best_parsable_locale
|
|
345
345
|
from ansible.module_utils.common.process import get_bin_path
|
|
346
|
-
from ansible.module_utils.six import b, string_types
|
|
347
346
|
|
|
348
347
|
|
|
349
348
|
def relocate_repo(module, result, repo_dir, old_repo_dir, worktree_dir):
|
|
@@ -443,12 +442,12 @@ def write_ssh_wrapper(module):
|
|
|
443
442
|
fd, wrapper_path = tempfile.mkstemp()
|
|
444
443
|
|
|
445
444
|
# use existing git_ssh/ssh_command, fallback to 'ssh'
|
|
446
|
-
template =
|
|
445
|
+
template = """#!/bin/sh
|
|
447
446
|
%s $GIT_SSH_OPTS "$@"
|
|
448
|
-
""" % os.environ.get('GIT_SSH', os.environ.get('GIT_SSH_COMMAND', 'ssh'))
|
|
447
|
+
""" % os.environ.get('GIT_SSH', os.environ.get('GIT_SSH_COMMAND', 'ssh'))
|
|
449
448
|
|
|
450
449
|
# write it
|
|
451
|
-
with os.fdopen(fd, 'w
|
|
450
|
+
with os.fdopen(fd, 'w') as fh:
|
|
452
451
|
fh.write(template)
|
|
453
452
|
|
|
454
453
|
# set execute
|
|
@@ -1257,7 +1256,7 @@ def main():
|
|
|
1257
1256
|
|
|
1258
1257
|
# evaluate and set the umask before doing anything else
|
|
1259
1258
|
if umask is not None:
|
|
1260
|
-
if not isinstance(umask,
|
|
1259
|
+
if not isinstance(umask, str):
|
|
1261
1260
|
module.fail_json(msg="umask must be defined as a quoted octal integer")
|
|
1262
1261
|
try:
|
|
1263
1262
|
umask = int(umask, 8)
|
ansible/modules/include_vars.py
CHANGED
|
@@ -66,7 +66,7 @@ options:
|
|
|
66
66
|
description:
|
|
67
67
|
- Ignore unknown file extensions within the directory.
|
|
68
68
|
- This allows users to specify a directory containing vars files that are intermingled with non-vars files extension types
|
|
69
|
-
(
|
|
69
|
+
(for example, a directory with a README in it and vars files).
|
|
70
70
|
type: bool
|
|
71
71
|
default: no
|
|
72
72
|
version_added: "2.7"
|
ansible/modules/known_hosts.py
CHANGED
|
@@ -225,7 +225,13 @@ def sanity_check(module, host, key, sshkeygen):
|
|
|
225
225
|
rc, stdout, stderr = module.run_command(sshkeygen_command)
|
|
226
226
|
|
|
227
227
|
if stdout == '': # host not found
|
|
228
|
-
|
|
228
|
+
results = {
|
|
229
|
+
"msg": "Host parameter does not match hashed host field in supplied key",
|
|
230
|
+
"rc": rc,
|
|
231
|
+
}
|
|
232
|
+
if stderr:
|
|
233
|
+
results["stderr"] = stderr
|
|
234
|
+
module.fail_json(**results)
|
|
229
235
|
|
|
230
236
|
|
|
231
237
|
def search_for_host_key(module, host, key, path, sshkeygen):
|