ansible-core 2.19.0b6__py3-none-any.whl → 2.19.0b7__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.
- ansible/_internal/_templating/_jinja_bits.py +16 -1
- ansible/_internal/_templating/_jinja_common.py +1 -1
- ansible/cli/__init__.py +2 -2
- ansible/cli/adhoc.py +6 -3
- ansible/cli/console.py +1 -1
- ansible/cli/doc.py +2 -2
- ansible/config/base.yml +9 -6
- ansible/executor/module_common.py +8 -5
- ansible/executor/powershell/psrp_put_file.ps1 +1 -1
- ansible/executor/task_executor.py +2 -2
- ansible/executor/task_queue_manager.py +34 -70
- ansible/executor/task_result.py +1 -1
- ansible/galaxy/api.py +2 -2
- ansible/galaxy/collection/concrete_artifact_manager.py +2 -2
- ansible/galaxy/dependency_resolution/providers.py +3 -3
- ansible/inventory/group.py +6 -1
- ansible/inventory/host.py +6 -1
- ansible/module_utils/_internal/_deprecator.py +12 -1
- ansible/module_utils/ansible_release.py +1 -1
- ansible/module_utils/basic.py +14 -16
- ansible/module_utils/common/yaml.py +1 -1
- ansible/module_utils/csharp/Ansible.Basic.cs +1 -1
- ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
- ansible/module_utils/facts/hardware/base.py +1 -1
- ansible/module_utils/facts/other/facter.py +1 -1
- ansible/module_utils/facts/system/distribution.py +2 -2
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
- ansible/module_utils/urls.py +1 -1
- ansible/modules/apt.py +9 -3
- ansible/modules/assemble.py +5 -3
- ansible/modules/expect.py +5 -5
- ansible/modules/hostname.py +2 -2
- ansible/modules/pip.py +9 -11
- ansible/modules/raw.py +2 -2
- ansible/modules/stat.py +1 -1
- ansible/modules/wait_for.py +10 -3
- ansible/parsing/mod_args.py +38 -20
- ansible/parsing/vault/__init__.py +3 -3
- ansible/playbook/base.py +0 -2
- ansible/playbook/helpers.py +1 -1
- ansible/playbook/playbook_include.py +23 -56
- ansible/playbook/role/__init__.py +38 -21
- ansible/plugins/action/__init__.py +2 -2
- ansible/plugins/action/assemble.py +2 -1
- ansible/plugins/action/assert.py +2 -2
- ansible/plugins/action/script.py +5 -4
- ansible/plugins/action/template.py +1 -1
- ansible/plugins/callback/__init__.py +77 -87
- ansible/plugins/callback/default.py +0 -3
- ansible/plugins/callback/junit.py +0 -6
- ansible/plugins/connection/ssh.py +1 -1
- ansible/plugins/filter/pow.yml +1 -1
- ansible/plugins/filter/root.yml +1 -1
- ansible/plugins/filter/strftime.yml +3 -3
- ansible/plugins/filter/to_uuid.yml +1 -1
- ansible/plugins/inventory/script.py +1 -1
- ansible/plugins/loader.py +5 -0
- ansible/plugins/lookup/password.py +4 -6
- ansible/release.py +1 -1
- ansible/utils/display.py +16 -26
- ansible/utils/path.py +1 -1
- ansible/utils/vars.py +4 -1
- ansible/vars/manager.py +6 -3
- ansible/vars/reserved.py +6 -4
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/METADATA +1 -1
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/RECORD +101 -99
- ansible_test/_internal/__init__.py +5 -0
- ansible_test/_internal/ansible_util.py +1 -1
- ansible_test/_internal/classification/python.py +6 -0
- ansible_test/_internal/cli/commands/__init__.py +0 -5
- ansible_test/_internal/cli/environments.py +51 -5
- ansible_test/_internal/commands/coverage/__init__.py +1 -1
- ansible_test/_internal/commands/integration/__init__.py +18 -5
- ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
- ansible_test/_internal/commands/sanity/__init__.py +3 -1
- ansible_test/_internal/commands/sanity/integration_aliases.py +11 -0
- ansible_test/_internal/commands/shell/__init__.py +43 -4
- ansible_test/_internal/commands/units/__init__.py +4 -1
- ansible_test/_internal/config.py +21 -13
- ansible_test/_internal/debugging.py +166 -0
- ansible_test/_internal/delegation.py +21 -13
- ansible_test/_internal/host_profiles.py +197 -6
- ansible_test/_internal/inventory.py +4 -0
- ansible_test/_internal/metadata.py +94 -4
- ansible_test/_internal/processes.py +80 -0
- ansible_test/_internal/python_requirements.py +27 -0
- ansible_test/_internal/target.py +8 -0
- ansible_test/_internal/util_common.py +13 -3
- ansible_test/_util/target/injector/python.py +8 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/WHEEL +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/top_level.txt +0 -0
@@ -19,12 +19,7 @@ from __future__ import annotations
|
|
19
19
|
|
20
20
|
import os
|
21
21
|
|
22
|
-
import ansible.constants as C
|
23
|
-
from ansible.errors import AnsibleParserError, AnsibleAssertionError
|
24
22
|
from ansible.module_utils.common.text.converters import to_bytes
|
25
|
-
from ansible.module_utils._internal._datatag import AnsibleTagHelper
|
26
|
-
from ansible.module_utils.six import string_types
|
27
|
-
from ansible.parsing.splitter import split_args
|
28
23
|
from ansible.playbook.attribute import NonInheritableFieldAttribute
|
29
24
|
from ansible.playbook.base import Base
|
30
25
|
from ansible.playbook.conditional import Conditional
|
@@ -32,16 +27,29 @@ from ansible.playbook.taggable import Taggable
|
|
32
27
|
from ansible.utils.collection_loader import AnsibleCollectionConfig
|
33
28
|
from ansible.utils.collection_loader._collection_finder import _get_collection_name_from_path, _get_collection_playbook_path
|
34
29
|
from ansible._internal._templating._engine import TemplateEngine
|
35
|
-
from ansible.
|
36
|
-
|
37
|
-
display = Display()
|
30
|
+
from ansible.errors import AnsibleError
|
31
|
+
from ansible import constants as C
|
38
32
|
|
39
33
|
|
40
34
|
class PlaybookInclude(Base, Conditional, Taggable):
|
41
35
|
|
42
|
-
import_playbook = NonInheritableFieldAttribute(isa='string')
|
36
|
+
import_playbook = NonInheritableFieldAttribute(isa='string', required=True)
|
43
37
|
vars_val = NonInheritableFieldAttribute(isa='dict', default=dict, alias='vars')
|
44
38
|
|
39
|
+
_post_validate_object = True # manually post_validate to get free arg validation/coercion
|
40
|
+
|
41
|
+
def preprocess_data(self, ds):
|
42
|
+
keys = {action for action in C._ACTION_IMPORT_PLAYBOOK if action in ds}
|
43
|
+
|
44
|
+
if len(keys) != 1:
|
45
|
+
raise AnsibleError(f'Found conflicting import_playbook actions: {", ".join(sorted(keys))}')
|
46
|
+
|
47
|
+
key = next(iter(keys))
|
48
|
+
|
49
|
+
ds['import_playbook'] = ds.pop(key)
|
50
|
+
|
51
|
+
return ds
|
52
|
+
|
45
53
|
@staticmethod
|
46
54
|
def load(data, basedir, variable_manager=None, loader=None):
|
47
55
|
return PlaybookInclude().load_data(ds=data, basedir=basedir, variable_manager=variable_manager, loader=loader)
|
@@ -62,18 +70,22 @@ class PlaybookInclude(Base, Conditional, Taggable):
|
|
62
70
|
new_obj = super(PlaybookInclude, self).load_data(ds, variable_manager, loader)
|
63
71
|
|
64
72
|
all_vars = self.vars.copy()
|
73
|
+
|
65
74
|
if variable_manager:
|
66
75
|
all_vars |= variable_manager.get_vars()
|
67
76
|
|
68
77
|
templar = TemplateEngine(loader=loader, variables=all_vars)
|
69
78
|
|
79
|
+
new_obj.post_validate(templar)
|
80
|
+
|
70
81
|
# then we use the object to load a Playbook
|
71
82
|
pb = Playbook(loader=loader)
|
72
83
|
|
73
|
-
file_name =
|
84
|
+
file_name = new_obj.import_playbook
|
74
85
|
|
75
86
|
# check for FQCN
|
76
87
|
resource = _get_collection_playbook_path(file_name)
|
88
|
+
|
77
89
|
if resource is not None:
|
78
90
|
playbook = resource[1]
|
79
91
|
playbook_collection = resource[2]
|
@@ -92,6 +104,7 @@ class PlaybookInclude(Base, Conditional, Taggable):
|
|
92
104
|
else:
|
93
105
|
# it is NOT a collection playbook, setup adjacent paths
|
94
106
|
AnsibleCollectionConfig.playbook_paths.append(os.path.dirname(os.path.abspath(to_bytes(playbook, errors='surrogate_or_strict'))))
|
107
|
+
# broken, see: https://github.com/ansible/ansible/issues/85357
|
95
108
|
|
96
109
|
pb._load_playbook_data(file_name=playbook, variable_manager=variable_manager, vars=self.vars.copy())
|
97
110
|
|
@@ -120,49 +133,3 @@ class PlaybookInclude(Base, Conditional, Taggable):
|
|
120
133
|
task_block._when = new_obj.when[:] + task_block.when[:]
|
121
134
|
|
122
135
|
return pb
|
123
|
-
|
124
|
-
def preprocess_data(self, ds):
|
125
|
-
"""
|
126
|
-
Reorganizes the data for a PlaybookInclude datastructure to line
|
127
|
-
up with what we expect the proper attributes to be
|
128
|
-
"""
|
129
|
-
|
130
|
-
if not isinstance(ds, dict):
|
131
|
-
raise AnsibleAssertionError('ds (%s) should be a dict but was a %s' % (ds, type(ds)))
|
132
|
-
|
133
|
-
# the new, cleaned datastructure, which will have legacy items reduced to a standard structure suitable for the
|
134
|
-
# attributes of the task class; copy any tagged data to preserve things like origin
|
135
|
-
new_ds = AnsibleTagHelper.tag_copy(ds, {})
|
136
|
-
|
137
|
-
for (k, v) in ds.items():
|
138
|
-
if k in C._ACTION_IMPORT_PLAYBOOK:
|
139
|
-
self._preprocess_import(ds, new_ds, k, v)
|
140
|
-
else:
|
141
|
-
# some basic error checking, to make sure vars are properly
|
142
|
-
# formatted and do not conflict with k=v parameters
|
143
|
-
if k == 'vars':
|
144
|
-
if 'vars' in new_ds:
|
145
|
-
raise AnsibleParserError("import_playbook parameters cannot be mixed with 'vars' entries for import statements", obj=ds)
|
146
|
-
elif not isinstance(v, dict):
|
147
|
-
raise AnsibleParserError("vars for import_playbook statements must be specified as a dictionary", obj=ds)
|
148
|
-
new_ds[k] = v
|
149
|
-
|
150
|
-
return super(PlaybookInclude, self).preprocess_data(new_ds)
|
151
|
-
|
152
|
-
def _preprocess_import(self, ds, new_ds, k, v):
|
153
|
-
"""
|
154
|
-
Splits the playbook import line up into filename and parameters
|
155
|
-
"""
|
156
|
-
if v is None:
|
157
|
-
raise AnsibleParserError("playbook import parameter is missing", obj=ds)
|
158
|
-
elif not isinstance(v, string_types):
|
159
|
-
raise AnsibleParserError("playbook import parameter must be a string indicating a file path, got %s instead" % type(v), obj=ds)
|
160
|
-
|
161
|
-
# The import_playbook line must include at least one item, which is the filename
|
162
|
-
# to import. Anything after that should be regarded as a parameter to the import
|
163
|
-
items = split_args(v)
|
164
|
-
if len(items) == 0:
|
165
|
-
raise AnsibleParserError("import_playbook statements must specify the file name to import", obj=ds)
|
166
|
-
|
167
|
-
# DTFIX3: investigate this as a possible "problematic strip"
|
168
|
-
new_ds['import_playbook'] = AnsibleTagHelper.tag_copy(v, items[0].strip())
|
@@ -18,6 +18,7 @@
|
|
18
18
|
from __future__ import annotations
|
19
19
|
|
20
20
|
import os
|
21
|
+
import typing as _t
|
21
22
|
|
22
23
|
from collections.abc import Container, Mapping, Set, Sequence
|
23
24
|
from types import MappingProxyType
|
@@ -39,6 +40,16 @@ from ansible.utils.collection_loader import AnsibleCollectionConfig
|
|
39
40
|
from ansible.utils.path import is_subpath
|
40
41
|
from ansible.utils.vars import combine_vars
|
41
42
|
|
43
|
+
# NOTE: This import is only needed for the type-checking in __init__. While there's an alternative
|
44
|
+
# available by using forward references this seems not to work well with commonly used IDEs.
|
45
|
+
# Therefore the TYPE_CHECKING hack seems to be a more universal approach, even if not being very elegant.
|
46
|
+
# References:
|
47
|
+
# * https://stackoverflow.com/q/39740632/199513
|
48
|
+
# * https://peps.python.org/pep-0484/#forward-references
|
49
|
+
if _t.TYPE_CHECKING:
|
50
|
+
from ansible.playbook.block import Block
|
51
|
+
from ansible.playbook.play import Play
|
52
|
+
|
42
53
|
__all__ = ['Role', 'hash_params']
|
43
54
|
|
44
55
|
# TODO: this should be a utility function, but can't be a member of
|
@@ -97,13 +108,19 @@ def hash_params(params):
|
|
97
108
|
|
98
109
|
class Role(Base, Conditional, Taggable, CollectionSearch, Delegatable):
|
99
110
|
|
100
|
-
def __init__(self,
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
111
|
+
def __init__(self,
|
112
|
+
play: Play = None,
|
113
|
+
from_files: dict[str, list[str]] = None,
|
114
|
+
from_include: bool = False,
|
115
|
+
validate: bool = True,
|
116
|
+
public: bool = None,
|
117
|
+
static: bool = True) -> None:
|
118
|
+
self._role_name: str = None
|
119
|
+
self._role_path: str = None
|
120
|
+
self._role_collection: str = None
|
121
|
+
self._role_params: dict[str, dict[str, str]] = dict()
|
105
122
|
self._loader = None
|
106
|
-
self.static = static
|
123
|
+
self.static: bool = static
|
107
124
|
|
108
125
|
# includes (static=false) default to private, while imports (static=true) default to public
|
109
126
|
# but both can be overridden by global config if set
|
@@ -116,26 +133,26 @@ class Role(Base, Conditional, Taggable, CollectionSearch, Delegatable):
|
|
116
133
|
else:
|
117
134
|
self.public = public
|
118
135
|
|
119
|
-
self._metadata = RoleMetadata()
|
120
|
-
self._play = play
|
121
|
-
self._parents = []
|
122
|
-
self._dependencies = []
|
123
|
-
self._all_dependencies = None
|
124
|
-
self._task_blocks = []
|
125
|
-
self._handler_blocks = []
|
126
|
-
self._compiled_handler_blocks = None
|
127
|
-
self._default_vars = dict()
|
128
|
-
self._role_vars = dict()
|
129
|
-
self._had_task_run = dict()
|
130
|
-
self._completed = dict()
|
131
|
-
self._should_validate = validate
|
136
|
+
self._metadata: RoleMetadata = RoleMetadata()
|
137
|
+
self._play: Play = play
|
138
|
+
self._parents: list[Role] = []
|
139
|
+
self._dependencies: list[Role] = []
|
140
|
+
self._all_dependencies: list[Role] | None = None
|
141
|
+
self._task_blocks: list[Block] = []
|
142
|
+
self._handler_blocks: list[Block] = []
|
143
|
+
self._compiled_handler_blocks: list[Block] | None = None
|
144
|
+
self._default_vars: dict[str, str] | None = dict()
|
145
|
+
self._role_vars: dict[str, str] | None = dict()
|
146
|
+
self._had_task_run: dict[str, bool] = dict()
|
147
|
+
self._completed: dict[str, bool] = dict()
|
148
|
+
self._should_validate: bool = validate
|
132
149
|
|
133
150
|
if from_files is None:
|
134
151
|
from_files = {}
|
135
|
-
self._from_files = from_files
|
152
|
+
self._from_files: dict[str, list[str]] = from_files
|
136
153
|
|
137
154
|
# Indicates whether this role was included via include/import_role
|
138
|
-
self.from_include = from_include
|
155
|
+
self.from_include: bool = from_include
|
139
156
|
|
140
157
|
self._hash = None
|
141
158
|
|
@@ -103,7 +103,7 @@ class ActionBase(ABC, _AnsiblePluginInfoMixin):
|
|
103
103
|
self._display = display
|
104
104
|
|
105
105
|
@abstractmethod
|
106
|
-
def run(self, tmp=None, task_vars=None):
|
106
|
+
def run(self, tmp: str | None = None, task_vars: dict[str, t.Any] | None = None) -> dict[str, t.Any]:
|
107
107
|
""" Action Plugins should implement this method to perform their
|
108
108
|
tasks. Everything else in this base class is a helper method for the
|
109
109
|
action plugin to do that.
|
@@ -120,7 +120,7 @@ class ActionBase(ABC, _AnsiblePluginInfoMixin):
|
|
120
120
|
* Module parameters. These are stored in self._task.args
|
121
121
|
"""
|
122
122
|
# does not default to {'changed': False, 'failed': False}, as it used to break async
|
123
|
-
result = {}
|
123
|
+
result: dict[str, t.Any] = {}
|
124
124
|
|
125
125
|
if tmp is not None:
|
126
126
|
display.warning('ActionModule.run() no longer honors the tmp parameter. Action'
|
@@ -81,9 +81,10 @@ class ActionModule(ActionBase):
|
|
81
81
|
|
82
82
|
def run(self, tmp=None, task_vars=None):
|
83
83
|
|
84
|
-
self._supports_check_mode =
|
84
|
+
self._supports_check_mode = True
|
85
85
|
|
86
86
|
super(ActionModule, self).run(tmp, task_vars)
|
87
|
+
|
87
88
|
del tmp # tmp no longer has any effect
|
88
89
|
|
89
90
|
if task_vars is None:
|
ansible/plugins/action/assert.py
CHANGED
@@ -72,12 +72,12 @@ class ActionModule(ActionBase):
|
|
72
72
|
fail_msg = new_module_args['fail_msg']
|
73
73
|
success_msg = new_module_args['success_msg']
|
74
74
|
quiet = new_module_args['quiet']
|
75
|
-
|
75
|
+
that_list = new_module_args['that']
|
76
76
|
|
77
77
|
if not quiet:
|
78
78
|
result['_ansible_verbose_always'] = True
|
79
79
|
|
80
|
-
for that in
|
80
|
+
for that in that_list:
|
81
81
|
test_result = self._templar.evaluate_conditional(conditional=that)
|
82
82
|
if not test_result:
|
83
83
|
result['failed'] = True
|
ansible/plugins/action/script.py
CHANGED
@@ -20,6 +20,7 @@ import os
|
|
20
20
|
import pathlib
|
21
21
|
import re
|
22
22
|
import shlex
|
23
|
+
import typing as _t
|
23
24
|
|
24
25
|
from ansible.errors import AnsibleError, AnsibleActionFail, AnsibleActionSkip
|
25
26
|
from ansible.executor.powershell import module_manifest as ps_manifest
|
@@ -35,7 +36,7 @@ class ActionModule(ActionBase):
|
|
35
36
|
# after chopping off a potential drive letter.
|
36
37
|
windows_absolute_path_detection = re.compile(r'^(?:[a-zA-Z]\:)?(\\|\/)')
|
37
38
|
|
38
|
-
def run(self, tmp=None, task_vars=None):
|
39
|
+
def run(self, tmp: str | None = None, task_vars: dict[str, _t.Any] | None = None) -> dict[str, _t.Any]:
|
39
40
|
""" handler for file transfer operations """
|
40
41
|
if task_vars is None:
|
41
42
|
task_vars = dict()
|
@@ -130,7 +131,7 @@ class ActionModule(ActionBase):
|
|
130
131
|
self._fixup_perms2((self._connection._shell.tmpdir, tmp_src), execute=True)
|
131
132
|
|
132
133
|
# add preparation steps to one ssh roundtrip executing the script
|
133
|
-
env_dict =
|
134
|
+
env_dict: dict[str, _t.Any] = {}
|
134
135
|
env_string = self._compute_environment_string(env_dict)
|
135
136
|
|
136
137
|
if executable:
|
@@ -164,10 +165,10 @@ class ActionModule(ActionBase):
|
|
164
165
|
script_cmd = self._connection._shell.build_module_command(env_string='', shebang='#!powershell', cmd='')
|
165
166
|
|
166
167
|
# now we execute script, always assume changed.
|
167
|
-
result = dict(self._low_level_execute_command(cmd=script_cmd, in_data=exec_data, sudoable=True, chdir=chdir), changed=True)
|
168
|
+
result: dict[str, object] = dict(self._low_level_execute_command(cmd=script_cmd, in_data=exec_data, sudoable=True, chdir=chdir), changed=True)
|
168
169
|
|
169
170
|
if 'rc' in result and result['rc'] != 0:
|
170
|
-
|
171
|
+
result.update(msg='non-zero return code', failed=True)
|
171
172
|
|
172
173
|
return result
|
173
174
|
finally:
|
@@ -44,7 +44,7 @@ class ActionModule(ActionBase):
|
|
44
44
|
del tmp # tmp no longer has any effect
|
45
45
|
|
46
46
|
# Options type validation
|
47
|
-
#
|
47
|
+
# strings
|
48
48
|
for s_type in ('src', 'dest', 'state', 'newline_sequence', 'variable_start_string', 'variable_end_string', 'block_start_string',
|
49
49
|
'block_end_string', 'comment_start_string', 'comment_end_string'):
|
50
50
|
if s_type in self._task.args:
|