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.
Files changed (101) hide show
  1. ansible/_internal/_templating/_jinja_bits.py +16 -1
  2. ansible/_internal/_templating/_jinja_common.py +1 -1
  3. ansible/cli/__init__.py +2 -2
  4. ansible/cli/adhoc.py +6 -3
  5. ansible/cli/console.py +1 -1
  6. ansible/cli/doc.py +2 -2
  7. ansible/config/base.yml +9 -6
  8. ansible/executor/module_common.py +8 -5
  9. ansible/executor/powershell/psrp_put_file.ps1 +1 -1
  10. ansible/executor/task_executor.py +2 -2
  11. ansible/executor/task_queue_manager.py +34 -70
  12. ansible/executor/task_result.py +1 -1
  13. ansible/galaxy/api.py +2 -2
  14. ansible/galaxy/collection/concrete_artifact_manager.py +2 -2
  15. ansible/galaxy/dependency_resolution/providers.py +3 -3
  16. ansible/inventory/group.py +6 -1
  17. ansible/inventory/host.py +6 -1
  18. ansible/module_utils/_internal/_deprecator.py +12 -1
  19. ansible/module_utils/ansible_release.py +1 -1
  20. ansible/module_utils/basic.py +14 -16
  21. ansible/module_utils/common/yaml.py +1 -1
  22. ansible/module_utils/csharp/Ansible.Basic.cs +1 -1
  23. ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
  24. ansible/module_utils/facts/hardware/base.py +1 -1
  25. ansible/module_utils/facts/other/facter.py +1 -1
  26. ansible/module_utils/facts/system/distribution.py +2 -2
  27. ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
  28. ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
  29. ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
  30. ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
  31. ansible/module_utils/urls.py +1 -1
  32. ansible/modules/apt.py +9 -3
  33. ansible/modules/assemble.py +5 -3
  34. ansible/modules/expect.py +5 -5
  35. ansible/modules/hostname.py +2 -2
  36. ansible/modules/pip.py +9 -11
  37. ansible/modules/raw.py +2 -2
  38. ansible/modules/stat.py +1 -1
  39. ansible/modules/wait_for.py +10 -3
  40. ansible/parsing/mod_args.py +38 -20
  41. ansible/parsing/vault/__init__.py +3 -3
  42. ansible/playbook/base.py +0 -2
  43. ansible/playbook/helpers.py +1 -1
  44. ansible/playbook/playbook_include.py +23 -56
  45. ansible/playbook/role/__init__.py +38 -21
  46. ansible/plugins/action/__init__.py +2 -2
  47. ansible/plugins/action/assemble.py +2 -1
  48. ansible/plugins/action/assert.py +2 -2
  49. ansible/plugins/action/script.py +5 -4
  50. ansible/plugins/action/template.py +1 -1
  51. ansible/plugins/callback/__init__.py +77 -87
  52. ansible/plugins/callback/default.py +0 -3
  53. ansible/plugins/callback/junit.py +0 -6
  54. ansible/plugins/connection/ssh.py +1 -1
  55. ansible/plugins/filter/pow.yml +1 -1
  56. ansible/plugins/filter/root.yml +1 -1
  57. ansible/plugins/filter/strftime.yml +3 -3
  58. ansible/plugins/filter/to_uuid.yml +1 -1
  59. ansible/plugins/inventory/script.py +1 -1
  60. ansible/plugins/loader.py +5 -0
  61. ansible/plugins/lookup/password.py +4 -6
  62. ansible/release.py +1 -1
  63. ansible/utils/display.py +16 -26
  64. ansible/utils/path.py +1 -1
  65. ansible/utils/vars.py +4 -1
  66. ansible/vars/manager.py +6 -3
  67. ansible/vars/reserved.py +6 -4
  68. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/METADATA +1 -1
  69. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/RECORD +101 -99
  70. ansible_test/_internal/__init__.py +5 -0
  71. ansible_test/_internal/ansible_util.py +1 -1
  72. ansible_test/_internal/classification/python.py +6 -0
  73. ansible_test/_internal/cli/commands/__init__.py +0 -5
  74. ansible_test/_internal/cli/environments.py +51 -5
  75. ansible_test/_internal/commands/coverage/__init__.py +1 -1
  76. ansible_test/_internal/commands/integration/__init__.py +18 -5
  77. ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
  78. ansible_test/_internal/commands/sanity/__init__.py +3 -1
  79. ansible_test/_internal/commands/sanity/integration_aliases.py +11 -0
  80. ansible_test/_internal/commands/shell/__init__.py +43 -4
  81. ansible_test/_internal/commands/units/__init__.py +4 -1
  82. ansible_test/_internal/config.py +21 -13
  83. ansible_test/_internal/debugging.py +166 -0
  84. ansible_test/_internal/delegation.py +21 -13
  85. ansible_test/_internal/host_profiles.py +197 -6
  86. ansible_test/_internal/inventory.py +4 -0
  87. ansible_test/_internal/metadata.py +94 -4
  88. ansible_test/_internal/processes.py +80 -0
  89. ansible_test/_internal/python_requirements.py +27 -0
  90. ansible_test/_internal/target.py +8 -0
  91. ansible_test/_internal/util_common.py +13 -3
  92. ansible_test/_util/target/injector/python.py +8 -0
  93. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/WHEEL +0 -0
  94. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/entry_points.txt +0 -0
  95. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/COPYING +0 -0
  96. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  97. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
  98. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  99. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  100. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0b7.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  101. {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.utils.display import Display
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 = templar.template(new_obj.import_playbook)
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, play=None, from_files=None, from_include=False, validate=True, public=None, static=True):
101
- self._role_name = None
102
- self._role_path = None
103
- self._role_collection = None
104
- self._role_params = dict()
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 = False
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:
@@ -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
- thats = new_module_args['that']
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 thats:
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
@@ -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 = 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
- raise AnsibleActionFail('non-zero return code', result=result)
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
- # stings
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: