ansible-core 2.19.2rc1__py3-none-any.whl → 2.19.3__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/_display_utils.py +145 -0
- ansible/executor/powershell/async_watchdog.ps1 +24 -4
- ansible/executor/task_executor.py +6 -4
- ansible/module_utils/ansible_release.py +1 -1
- ansible/module_utils/basic.py +1 -1
- ansible/module_utils/urls.py +6 -2
- ansible/plugins/inventory/script.py +2 -1
- ansible/plugins/list.py +10 -3
- ansible/plugins/loader.py +3 -2
- ansible/release.py +1 -1
- ansible/utils/display.py +22 -162
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/METADATA +1 -1
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/RECORD +22 -21
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/WHEEL +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
|
|
5
|
+
from ansible.module_utils._internal import _ambient_context, _messages
|
|
6
|
+
from . import _event_formatting
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DeferredWarningContext(_ambient_context.AmbientContextBase):
|
|
10
|
+
"""
|
|
11
|
+
Calls to `Display.warning()` and `Display.deprecated()` within this context will cause the resulting warnings to be captured and not displayed.
|
|
12
|
+
The intended use is for task-initiated warnings to be recorded with the task result, which makes them visible to registered results, callbacks, etc.
|
|
13
|
+
The active display callback is responsible for communicating any warnings to the user.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
# DTFIX-FUTURE: once we start implementing nested scoped contexts for our own bookkeeping, this should be an interface facade that forwards to the nearest
|
|
17
|
+
# context that actually implements the warnings collection capability
|
|
18
|
+
|
|
19
|
+
def __init__(self, *, variables: dict[str, object]) -> None:
|
|
20
|
+
self._variables = variables # DTFIX-FUTURE: move this to an AmbientContext-derived TaskContext (once it exists)
|
|
21
|
+
self._deprecation_warnings: list[_messages.DeprecationSummary] = []
|
|
22
|
+
self._warnings: list[_messages.WarningSummary] = []
|
|
23
|
+
self._seen: set[_messages.WarningSummary] = set()
|
|
24
|
+
|
|
25
|
+
def capture(self, warning: _messages.WarningSummary) -> None:
|
|
26
|
+
"""Add the warning/deprecation to the context if it has not already been seen by this context."""
|
|
27
|
+
if warning in self._seen:
|
|
28
|
+
return
|
|
29
|
+
|
|
30
|
+
self._seen.add(warning)
|
|
31
|
+
|
|
32
|
+
if isinstance(warning, _messages.DeprecationSummary):
|
|
33
|
+
self._deprecation_warnings.append(warning)
|
|
34
|
+
else:
|
|
35
|
+
self._warnings.append(warning)
|
|
36
|
+
|
|
37
|
+
def get_warnings(self) -> list[_messages.WarningSummary]:
|
|
38
|
+
"""Return a list of the captured non-deprecation warnings."""
|
|
39
|
+
# DTFIX-FUTURE: return a read-only list proxy instead
|
|
40
|
+
return self._warnings
|
|
41
|
+
|
|
42
|
+
def get_deprecation_warnings(self) -> list[_messages.DeprecationSummary]:
|
|
43
|
+
"""Return a list of the captured deprecation warnings."""
|
|
44
|
+
# DTFIX-FUTURE: return a read-only list proxy instead
|
|
45
|
+
return self._deprecation_warnings
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def format_message(summary: _messages.SummaryBase, include_traceback: bool) -> str:
|
|
49
|
+
if isinstance(summary, _messages.DeprecationSummary):
|
|
50
|
+
deprecation_message = get_deprecation_message_with_plugin_info(
|
|
51
|
+
msg=summary.event.msg,
|
|
52
|
+
version=summary.version,
|
|
53
|
+
date=summary.date,
|
|
54
|
+
deprecator=summary.deprecator,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
event = dataclasses.replace(summary.event, msg=deprecation_message)
|
|
58
|
+
else:
|
|
59
|
+
event = summary.event
|
|
60
|
+
|
|
61
|
+
return _event_formatting.format_event(event, include_traceback)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def get_deprecation_message_with_plugin_info(
|
|
65
|
+
*,
|
|
66
|
+
msg: str,
|
|
67
|
+
version: str | None,
|
|
68
|
+
removed: bool = False,
|
|
69
|
+
date: str | None,
|
|
70
|
+
deprecator: _messages.PluginInfo | None,
|
|
71
|
+
) -> str:
|
|
72
|
+
"""Internal use only. Return a deprecation message and help text for display."""
|
|
73
|
+
# DTFIX-FUTURE: the logic for omitting date/version doesn't apply to the payload, so it shows up in vars in some cases when it should not
|
|
74
|
+
|
|
75
|
+
if removed:
|
|
76
|
+
removal_fragment = 'This feature was removed'
|
|
77
|
+
else:
|
|
78
|
+
removal_fragment = 'This feature will be removed'
|
|
79
|
+
|
|
80
|
+
if not deprecator or not deprecator.type:
|
|
81
|
+
# indeterminate has no resolved_name or type
|
|
82
|
+
# collections have a resolved_name but no type
|
|
83
|
+
collection = deprecator.resolved_name if deprecator else None
|
|
84
|
+
plugin_fragment = ''
|
|
85
|
+
elif deprecator.resolved_name == 'ansible.builtin':
|
|
86
|
+
# core deprecations from base classes (the API) have no plugin name, only 'ansible.builtin'
|
|
87
|
+
plugin_type_name = str(deprecator.type) if deprecator.type is _messages.PluginType.MODULE else f'{deprecator.type} plugin'
|
|
88
|
+
|
|
89
|
+
collection = deprecator.resolved_name
|
|
90
|
+
plugin_fragment = f'the {plugin_type_name} API'
|
|
91
|
+
else:
|
|
92
|
+
parts = deprecator.resolved_name.split('.')
|
|
93
|
+
plugin_name = parts[-1]
|
|
94
|
+
plugin_type_name = str(deprecator.type) if deprecator.type is _messages.PluginType.MODULE else f'{deprecator.type} plugin'
|
|
95
|
+
|
|
96
|
+
collection = '.'.join(parts[:2]) if len(parts) > 2 else None
|
|
97
|
+
plugin_fragment = f'{plugin_type_name} {plugin_name!r}'
|
|
98
|
+
|
|
99
|
+
if collection and plugin_fragment:
|
|
100
|
+
plugin_fragment += ' in'
|
|
101
|
+
|
|
102
|
+
if collection == 'ansible.builtin':
|
|
103
|
+
collection_fragment = 'ansible-core'
|
|
104
|
+
elif collection:
|
|
105
|
+
collection_fragment = f'collection {collection!r}'
|
|
106
|
+
else:
|
|
107
|
+
collection_fragment = ''
|
|
108
|
+
|
|
109
|
+
if not collection:
|
|
110
|
+
when_fragment = 'in the future' if not removed else ''
|
|
111
|
+
elif date:
|
|
112
|
+
when_fragment = f'in a release after {date}'
|
|
113
|
+
elif version:
|
|
114
|
+
when_fragment = f'version {version}'
|
|
115
|
+
else:
|
|
116
|
+
when_fragment = 'in a future release' if not removed else ''
|
|
117
|
+
|
|
118
|
+
if plugin_fragment or collection_fragment:
|
|
119
|
+
from_fragment = 'from'
|
|
120
|
+
else:
|
|
121
|
+
from_fragment = ''
|
|
122
|
+
|
|
123
|
+
deprecation_msg = ' '.join(f for f in [removal_fragment, from_fragment, plugin_fragment, collection_fragment, when_fragment] if f) + '.'
|
|
124
|
+
|
|
125
|
+
return join_sentences(msg, deprecation_msg)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def join_sentences(first: str | None, second: str | None) -> str:
|
|
129
|
+
"""Join two sentences together."""
|
|
130
|
+
first = (first or '').strip()
|
|
131
|
+
second = (second or '').strip()
|
|
132
|
+
|
|
133
|
+
if first and first[-1] not in ('!', '?', '.'):
|
|
134
|
+
first += '.'
|
|
135
|
+
|
|
136
|
+
if second and second[-1] not in ('!', '?', '.'):
|
|
137
|
+
second += '.'
|
|
138
|
+
|
|
139
|
+
if first and not second:
|
|
140
|
+
return first
|
|
141
|
+
|
|
142
|
+
if not first and second:
|
|
143
|
+
return second
|
|
144
|
+
|
|
145
|
+
return ' '.join((first, second))
|
|
@@ -67,14 +67,34 @@ try {
|
|
|
67
67
|
$result.finished = $true
|
|
68
68
|
|
|
69
69
|
if ($jobAsyncResult.IsCompleted) {
|
|
70
|
-
$jobOutput = $ps.EndInvoke($jobAsyncResult)
|
|
70
|
+
$jobOutput = @($ps.EndInvoke($jobAsyncResult) | Out-String) -join "`n"
|
|
71
71
|
$jobError = $ps.Streams.Error
|
|
72
72
|
|
|
73
73
|
# write success/output/error to result object
|
|
74
|
-
|
|
75
|
-
$
|
|
74
|
+
$moduleResultJson = $jobOutput
|
|
75
|
+
$startJsonChar = $moduleResultJson.IndexOf([char]'{')
|
|
76
|
+
if ($startJsonChar -eq -1) {
|
|
77
|
+
throw "No start of json char found in module result"
|
|
78
|
+
}
|
|
79
|
+
$moduleResultJson = $moduleResultJson.Substring($startJsonChar)
|
|
80
|
+
|
|
81
|
+
$endJsonChar = $moduleResultJson.LastIndexOf([char]'}')
|
|
82
|
+
if ($endJsonChar -eq -1) {
|
|
83
|
+
throw "No end of json char found in module result"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
$trailingJunk = $moduleResultJson.Substring($endJsonChar + 1).Trim()
|
|
87
|
+
$moduleResultJson = $moduleResultJson.Substring(0, $endJsonChar + 1)
|
|
88
|
+
$moduleResult = $moduleResultJson | ConvertFrom-Json | Convert-JsonObject
|
|
76
89
|
# TODO: check for conflicting keys
|
|
77
90
|
$result = $result + $moduleResult
|
|
91
|
+
|
|
92
|
+
if ($trailingJunk) {
|
|
93
|
+
if (-not $result.warnings) {
|
|
94
|
+
$result.warnings = @()
|
|
95
|
+
}
|
|
96
|
+
$result.warnings += "Module invocation had junk after the JSON data: $trailingJunk"
|
|
97
|
+
}
|
|
78
98
|
}
|
|
79
99
|
else {
|
|
80
100
|
# We can't call Stop() as pwsh won't respond if it is busy calling a .NET
|
|
@@ -103,7 +123,7 @@ catch {
|
|
|
103
123
|
$result.failed = $true
|
|
104
124
|
$result.msg = "failure during async watchdog: $_"
|
|
105
125
|
# return output back, if available, to Ansible to help with debugging errors
|
|
106
|
-
$result.stdout = $jobOutput
|
|
126
|
+
$result.stdout = $jobOutput
|
|
107
127
|
$result.stderr = $jobError | Out-String
|
|
108
128
|
}
|
|
109
129
|
finally {
|
|
@@ -19,6 +19,8 @@ from ansible.errors import (
|
|
|
19
19
|
AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleTaskError,
|
|
20
20
|
AnsibleValueOmittedError,
|
|
21
21
|
)
|
|
22
|
+
|
|
23
|
+
from ansible._internal import _display_utils
|
|
22
24
|
from ansible.executor.task_result import _RawTaskResult
|
|
23
25
|
from ansible._internal._datatag import _utils
|
|
24
26
|
from ansible.module_utils._internal import _messages
|
|
@@ -35,7 +37,7 @@ from ansible._internal._templating._jinja_plugins import _invoke_lookup, _Direct
|
|
|
35
37
|
from ansible._internal._templating._engine import TemplateEngine
|
|
36
38
|
from ansible.template import Templar
|
|
37
39
|
from ansible.utils.collection_loader import AnsibleCollectionConfig
|
|
38
|
-
from ansible.utils.display import Display
|
|
40
|
+
from ansible.utils.display import Display
|
|
39
41
|
from ansible.utils.vars import combine_vars
|
|
40
42
|
from ansible.vars.clean import namespace_facts, clean_facts
|
|
41
43
|
from ansible.vars.manager import _deprecate_top_level_fact
|
|
@@ -416,7 +418,7 @@ class TaskExecutor:
|
|
|
416
418
|
def _execute(self, templar: TemplateEngine, variables: dict[str, t.Any]) -> dict[str, t.Any]:
|
|
417
419
|
result: dict[str, t.Any]
|
|
418
420
|
|
|
419
|
-
with
|
|
421
|
+
with _display_utils.DeferredWarningContext(variables=variables) as warning_ctx:
|
|
420
422
|
try:
|
|
421
423
|
# DTFIX-FUTURE: improve error handling to prioritize the earliest exception, turning the remaining ones into warnings
|
|
422
424
|
result = self._execute_internal(templar, variables)
|
|
@@ -431,7 +433,7 @@ class TaskExecutor:
|
|
|
431
433
|
|
|
432
434
|
self._task.update_result_no_log(templar, result)
|
|
433
435
|
|
|
434
|
-
# The warnings/deprecations in the result have already been captured in the
|
|
436
|
+
# The warnings/deprecations in the result have already been captured in the DeferredWarningContext by _apply_task_result_compat.
|
|
435
437
|
# The captured warnings/deprecations are a superset of the ones from the result, and may have been converted from a dict to a dataclass.
|
|
436
438
|
# These are then used to supersede the entries in the result.
|
|
437
439
|
|
|
@@ -788,7 +790,7 @@ class TaskExecutor:
|
|
|
788
790
|
return result
|
|
789
791
|
|
|
790
792
|
@staticmethod
|
|
791
|
-
def _apply_task_result_compat(result: dict[str, t.Any], warning_ctx:
|
|
793
|
+
def _apply_task_result_compat(result: dict[str, t.Any], warning_ctx: _display_utils.DeferredWarningContext) -> None:
|
|
792
794
|
"""Apply backward-compatibility mutations to the supplied task result."""
|
|
793
795
|
if warnings := result.get('warnings'):
|
|
794
796
|
if isinstance(warnings, list):
|
ansible/module_utils/basic.py
CHANGED
|
@@ -2090,7 +2090,7 @@ class AnsibleModule(object):
|
|
|
2090
2090
|
stdout_changed = False
|
|
2091
2091
|
for key, event in events:
|
|
2092
2092
|
b_chunk = key.fileobj.read(32768)
|
|
2093
|
-
if not b_chunk:
|
|
2093
|
+
if not b_chunk and b_chunk is not None:
|
|
2094
2094
|
selector.unregister(key.fileobj)
|
|
2095
2095
|
elif key.fileobj == cmd.stdout:
|
|
2096
2096
|
stdout += b_chunk
|
ansible/module_utils/urls.py
CHANGED
|
@@ -1358,7 +1358,8 @@ def _split_multiext(name, min=3, max=4, count=2):
|
|
|
1358
1358
|
|
|
1359
1359
|
def fetch_file(module, url, data=None, headers=None, method=None,
|
|
1360
1360
|
use_proxy=True, force=False, last_mod_time=None, timeout=10,
|
|
1361
|
-
unredirected_headers=None, decompress=True, ciphers=None
|
|
1361
|
+
unredirected_headers=None, decompress=True, ciphers=None,
|
|
1362
|
+
ca_path=None, cookies=None):
|
|
1362
1363
|
"""Download and save a file via HTTP(S) or FTP (needs the module as parameter).
|
|
1363
1364
|
This is basically a wrapper around fetch_url().
|
|
1364
1365
|
|
|
@@ -1375,6 +1376,8 @@ def fetch_file(module, url, data=None, headers=None, method=None,
|
|
|
1375
1376
|
:kwarg unredirected_headers: (optional) A list of headers to not attach on a redirected request
|
|
1376
1377
|
:kwarg decompress: (optional) Whether to attempt to decompress gzip content-encoded responses
|
|
1377
1378
|
:kwarg ciphers: (optional) List of ciphers to use
|
|
1379
|
+
:kwarg ca_path: (optional) Path to CA bundle
|
|
1380
|
+
:kwarg cookies: (optional) CookieJar object to send with the request
|
|
1378
1381
|
|
|
1379
1382
|
:returns: A string, the path to the downloaded file.
|
|
1380
1383
|
"""
|
|
@@ -1386,7 +1389,8 @@ def fetch_file(module, url, data=None, headers=None, method=None,
|
|
|
1386
1389
|
module.add_cleanup_file(fetch_temp_file.name)
|
|
1387
1390
|
try:
|
|
1388
1391
|
rsp, info = fetch_url(module, url, data, headers, method, use_proxy, force, last_mod_time, timeout,
|
|
1389
|
-
unredirected_headers=unredirected_headers, decompress=decompress, ciphers=ciphers
|
|
1392
|
+
unredirected_headers=unredirected_headers, decompress=decompress, ciphers=ciphers,
|
|
1393
|
+
ca_path=ca_path, cookies=cookies)
|
|
1390
1394
|
if not rsp or (rsp.code and rsp.code >= 400):
|
|
1391
1395
|
module.fail_json(msg="Failure downloading %s, %s" % (url, info['msg']))
|
|
1392
1396
|
data = rsp.read(bufsize)
|
|
@@ -256,9 +256,10 @@ class InventoryModule(BaseInventoryPlugin):
|
|
|
256
256
|
group = self.inventory.add_group(group)
|
|
257
257
|
|
|
258
258
|
if not isinstance(data, dict):
|
|
259
|
+
original_type = native_type_name(data)
|
|
259
260
|
data = {'hosts': data}
|
|
260
261
|
display.deprecated(
|
|
261
|
-
msg=f"Group {group!r} was converted to {native_type_name(dict)!r} from {
|
|
262
|
+
msg=f"Group {group!r} was converted to {native_type_name(dict)!r} from {original_type!r}.",
|
|
262
263
|
version='2.23',
|
|
263
264
|
obj=origin,
|
|
264
265
|
)
|
ansible/plugins/list.py
CHANGED
|
@@ -105,18 +105,25 @@ def _list_plugins_from_paths(ptype, dirs, collection, depth=0, docs=False):
|
|
|
105
105
|
]):
|
|
106
106
|
continue
|
|
107
107
|
|
|
108
|
+
resource_dir = to_native(os.path.dirname(full_path))
|
|
109
|
+
resource_name = get_composite_name(collection, plugin, resource_dir, depth)
|
|
110
|
+
|
|
108
111
|
if ptype in ('test', 'filter'):
|
|
112
|
+
# NOTE: pass the composite resource to ensure any relative
|
|
113
|
+
# imports it contains are interpreted in the correct context
|
|
114
|
+
if collection:
|
|
115
|
+
resource_name = '.'.join(resource_name.split('.')[2:])
|
|
109
116
|
try:
|
|
110
|
-
file_plugins = _list_j2_plugins_from_file(collection, full_path, ptype,
|
|
117
|
+
file_plugins = _list_j2_plugins_from_file(collection, full_path, ptype, resource_name)
|
|
111
118
|
except KeyError as e:
|
|
112
119
|
display.warning('Skipping file %s: %s' % (full_path, to_native(e)))
|
|
113
120
|
continue
|
|
114
121
|
|
|
115
122
|
for plugin in file_plugins:
|
|
116
|
-
plugin_name = get_composite_name(collection, plugin.ansible_name,
|
|
123
|
+
plugin_name = get_composite_name(collection, plugin.ansible_name, resource_dir, depth)
|
|
117
124
|
plugins[plugin_name] = full_path
|
|
118
125
|
else:
|
|
119
|
-
plugin_name =
|
|
126
|
+
plugin_name = resource_name
|
|
120
127
|
plugins[plugin_name] = full_path
|
|
121
128
|
else:
|
|
122
129
|
display.debug("Skip listing plugins in '{0}' as it is not a directory".format(path))
|
ansible/plugins/loader.py
CHANGED
|
@@ -36,6 +36,7 @@ from ansible.utils.collection_loader._collection_finder import _AnsibleCollectio
|
|
|
36
36
|
from ansible.utils.display import Display
|
|
37
37
|
from ansible.utils.plugin_docs import add_fragments
|
|
38
38
|
from ansible._internal._datatag import _tags
|
|
39
|
+
from ansible._internal import _display_utils
|
|
39
40
|
|
|
40
41
|
from . import _AnsiblePluginInfoMixin
|
|
41
42
|
from .filter import AnsibleJinja2Filter
|
|
@@ -606,7 +607,7 @@ class PluginLoader:
|
|
|
606
607
|
warning_text = tombstone.get('warning_text') or ''
|
|
607
608
|
warning_plugin_type = "module" if self.type == "modules" else f'{self.type} plugin'
|
|
608
609
|
warning_text = f'The {fq_name!r} {warning_plugin_type} has been removed.{" " if warning_text else ""}{warning_text}'
|
|
609
|
-
removed_msg =
|
|
610
|
+
removed_msg = _display_utils.get_deprecation_message_with_plugin_info(
|
|
610
611
|
msg=warning_text,
|
|
611
612
|
version=removal_version,
|
|
612
613
|
date=removal_date,
|
|
@@ -1411,7 +1412,7 @@ class Jinja2Loader(PluginLoader):
|
|
|
1411
1412
|
removal_version = tombstone_entry.get('removal_version')
|
|
1412
1413
|
warning_text = f'The {key!r} {self.type} plugin has been removed.{" " if warning_text else ""}{warning_text}'
|
|
1413
1414
|
|
|
1414
|
-
exc_msg =
|
|
1415
|
+
exc_msg = _display_utils.get_deprecation_message_with_plugin_info(
|
|
1415
1416
|
msg=warning_text,
|
|
1416
1417
|
version=removal_version,
|
|
1417
1418
|
date=removal_date,
|
ansible/release.py
CHANGED
ansible/utils/display.py
CHANGED
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
import contextlib
|
|
21
|
-
import dataclasses
|
|
22
21
|
|
|
23
22
|
try:
|
|
24
23
|
import curses
|
|
@@ -52,8 +51,8 @@ from ansible import constants as C
|
|
|
52
51
|
from ansible.constants import config
|
|
53
52
|
from ansible.errors import AnsibleAssertionError, AnsiblePromptInterrupt, AnsiblePromptNoninteractive, AnsibleError
|
|
54
53
|
from ansible._internal._errors import _error_utils, _error_factory
|
|
55
|
-
from ansible._internal import
|
|
56
|
-
from ansible.module_utils._internal import
|
|
54
|
+
from ansible._internal import _display_utils
|
|
55
|
+
from ansible.module_utils._internal import _deprecator, _messages
|
|
57
56
|
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
|
58
57
|
from ansible.module_utils.datatag import deprecator_from_collection_name
|
|
59
58
|
from ansible._internal._datatag._tags import TrustedAsTemplate
|
|
@@ -100,6 +99,17 @@ def _is_controller_traceback_enabled(event: _traceback.TracebackEvent) -> bool:
|
|
|
100
99
|
_traceback._is_traceback_enabled = _is_controller_traceback_enabled
|
|
101
100
|
|
|
102
101
|
|
|
102
|
+
def _deprecation_warnings_enabled() -> bool:
|
|
103
|
+
"""Return True if deprecation warnings are enabled for the current calling context, otherwise False."""
|
|
104
|
+
# DTFIX-FUTURE: move this capability into config using an AmbientContext-derived TaskContext (once it exists)
|
|
105
|
+
if warning_ctx := _display_utils.DeferredWarningContext.current(optional=True):
|
|
106
|
+
variables = warning_ctx._variables
|
|
107
|
+
else:
|
|
108
|
+
variables = None
|
|
109
|
+
|
|
110
|
+
return C.config.get_config_value('DEPRECATION_WARNINGS', variables=variables)
|
|
111
|
+
|
|
112
|
+
|
|
103
113
|
def get_text_width(text: str) -> int:
|
|
104
114
|
"""Function that utilizes ``wcswidth`` or ``wcwidth`` to determine the
|
|
105
115
|
number of columns used to display a text string.
|
|
@@ -582,7 +592,7 @@ class Display(metaclass=Singleton):
|
|
|
582
592
|
version="2.23",
|
|
583
593
|
)
|
|
584
594
|
|
|
585
|
-
msg =
|
|
595
|
+
msg = _display_utils.get_deprecation_message_with_plugin_info(
|
|
586
596
|
msg=msg,
|
|
587
597
|
version=version,
|
|
588
598
|
removed=removed,
|
|
@@ -597,70 +607,6 @@ class Display(metaclass=Singleton):
|
|
|
597
607
|
|
|
598
608
|
return msg
|
|
599
609
|
|
|
600
|
-
def _get_deprecation_message_with_plugin_info(
|
|
601
|
-
self,
|
|
602
|
-
*,
|
|
603
|
-
msg: str,
|
|
604
|
-
version: str | None,
|
|
605
|
-
removed: bool = False,
|
|
606
|
-
date: str | None,
|
|
607
|
-
deprecator: _messages.PluginInfo | None,
|
|
608
|
-
) -> str:
|
|
609
|
-
"""Internal use only. Return a deprecation message and help text for display."""
|
|
610
|
-
# DTFIX-FUTURE: the logic for omitting date/version doesn't apply to the payload, so it shows up in vars in some cases when it should not
|
|
611
|
-
|
|
612
|
-
if removed:
|
|
613
|
-
removal_fragment = 'This feature was removed'
|
|
614
|
-
else:
|
|
615
|
-
removal_fragment = 'This feature will be removed'
|
|
616
|
-
|
|
617
|
-
if not deprecator or not deprecator.type:
|
|
618
|
-
# indeterminate has no resolved_name or type
|
|
619
|
-
# collections have a resolved_name but no type
|
|
620
|
-
collection = deprecator.resolved_name if deprecator else None
|
|
621
|
-
plugin_fragment = ''
|
|
622
|
-
elif deprecator.resolved_name == 'ansible.builtin':
|
|
623
|
-
# core deprecations from base classes (the API) have no plugin name, only 'ansible.builtin'
|
|
624
|
-
plugin_type_name = str(deprecator.type) if deprecator.type is _messages.PluginType.MODULE else f'{deprecator.type} plugin'
|
|
625
|
-
|
|
626
|
-
collection = deprecator.resolved_name
|
|
627
|
-
plugin_fragment = f'the {plugin_type_name} API'
|
|
628
|
-
else:
|
|
629
|
-
parts = deprecator.resolved_name.split('.')
|
|
630
|
-
plugin_name = parts[-1]
|
|
631
|
-
plugin_type_name = str(deprecator.type) if deprecator.type is _messages.PluginType.MODULE else f'{deprecator.type} plugin'
|
|
632
|
-
|
|
633
|
-
collection = '.'.join(parts[:2]) if len(parts) > 2 else None
|
|
634
|
-
plugin_fragment = f'{plugin_type_name} {plugin_name!r}'
|
|
635
|
-
|
|
636
|
-
if collection and plugin_fragment:
|
|
637
|
-
plugin_fragment += ' in'
|
|
638
|
-
|
|
639
|
-
if collection == 'ansible.builtin':
|
|
640
|
-
collection_fragment = 'ansible-core'
|
|
641
|
-
elif collection:
|
|
642
|
-
collection_fragment = f'collection {collection!r}'
|
|
643
|
-
else:
|
|
644
|
-
collection_fragment = ''
|
|
645
|
-
|
|
646
|
-
if not collection:
|
|
647
|
-
when_fragment = 'in the future' if not removed else ''
|
|
648
|
-
elif date:
|
|
649
|
-
when_fragment = f'in a release after {date}'
|
|
650
|
-
elif version:
|
|
651
|
-
when_fragment = f'version {version}'
|
|
652
|
-
else:
|
|
653
|
-
when_fragment = 'in a future release' if not removed else ''
|
|
654
|
-
|
|
655
|
-
if plugin_fragment or collection_fragment:
|
|
656
|
-
from_fragment = 'from'
|
|
657
|
-
else:
|
|
658
|
-
from_fragment = ''
|
|
659
|
-
|
|
660
|
-
deprecation_msg = ' '.join(f for f in [removal_fragment, from_fragment, plugin_fragment, collection_fragment, when_fragment] if f) + '.'
|
|
661
|
-
|
|
662
|
-
return _join_sentences(msg, deprecation_msg)
|
|
663
|
-
|
|
664
610
|
@staticmethod
|
|
665
611
|
def _deduplicate(msg: str, messages: set[str]) -> bool:
|
|
666
612
|
"""
|
|
@@ -729,7 +675,7 @@ class Display(metaclass=Singleton):
|
|
|
729
675
|
_skip_stackwalk = True
|
|
730
676
|
|
|
731
677
|
if removed:
|
|
732
|
-
formatted_msg =
|
|
678
|
+
formatted_msg = _display_utils.get_deprecation_message_with_plugin_info(
|
|
733
679
|
msg=msg,
|
|
734
680
|
version=version,
|
|
735
681
|
removed=removed,
|
|
@@ -756,7 +702,7 @@ class Display(metaclass=Singleton):
|
|
|
756
702
|
deprecator=deprecator,
|
|
757
703
|
)
|
|
758
704
|
|
|
759
|
-
if warning_ctx :=
|
|
705
|
+
if warning_ctx := _display_utils.DeferredWarningContext.current(optional=True):
|
|
760
706
|
warning_ctx.capture(deprecation)
|
|
761
707
|
return
|
|
762
708
|
|
|
@@ -769,12 +715,12 @@ class Display(metaclass=Singleton):
|
|
|
769
715
|
# This is the post-proxy half of the `deprecated` implementation.
|
|
770
716
|
# Any logic that must occur in the primary controller process needs to be implemented here.
|
|
771
717
|
|
|
772
|
-
if not
|
|
718
|
+
if not _deprecation_warnings_enabled():
|
|
773
719
|
return
|
|
774
720
|
|
|
775
721
|
self.warning('Deprecation warnings can be disabled by setting `deprecation_warnings=False` in ansible.cfg.')
|
|
776
722
|
|
|
777
|
-
msg =
|
|
723
|
+
msg = _display_utils.format_message(warning, _traceback.is_traceback_enabled(_traceback.TracebackEvent.DEPRECATED))
|
|
778
724
|
msg = f'[DEPRECATION WARNING]: {msg}'
|
|
779
725
|
|
|
780
726
|
if self._deduplicate(msg, self._deprecations):
|
|
@@ -812,7 +758,7 @@ class Display(metaclass=Singleton):
|
|
|
812
758
|
),
|
|
813
759
|
)
|
|
814
760
|
|
|
815
|
-
if warning_ctx :=
|
|
761
|
+
if warning_ctx := _display_utils.DeferredWarningContext.current(optional=True):
|
|
816
762
|
warning_ctx.capture(warning)
|
|
817
763
|
return
|
|
818
764
|
|
|
@@ -825,7 +771,7 @@ class Display(metaclass=Singleton):
|
|
|
825
771
|
# This is the post-proxy half of the `warning` implementation.
|
|
826
772
|
# Any logic that must occur in the primary controller process needs to be implemented here.
|
|
827
773
|
|
|
828
|
-
msg =
|
|
774
|
+
msg = _display_utils.format_message(warning, _traceback.is_traceback_enabled(_traceback.TracebackEvent.WARNING))
|
|
829
775
|
msg = f"[WARNING]: {msg}"
|
|
830
776
|
|
|
831
777
|
if self._deduplicate(msg, self._warns):
|
|
@@ -915,7 +861,7 @@ class Display(metaclass=Singleton):
|
|
|
915
861
|
event=event,
|
|
916
862
|
)
|
|
917
863
|
|
|
918
|
-
if warning_ctx :=
|
|
864
|
+
if warning_ctx := _display_utils.DeferredWarningContext.current(optional=True):
|
|
919
865
|
warning_ctx.capture(warning)
|
|
920
866
|
return
|
|
921
867
|
|
|
@@ -952,7 +898,7 @@ class Display(metaclass=Singleton):
|
|
|
952
898
|
# This is the post-proxy half of the `error` implementation.
|
|
953
899
|
# Any logic that must occur in the primary controller process needs to be implemented here.
|
|
954
900
|
|
|
955
|
-
msg =
|
|
901
|
+
msg = _display_utils.format_message(error, _traceback.is_traceback_enabled(_traceback.TracebackEvent.ERROR))
|
|
956
902
|
msg = f'[ERROR]: {msg}'
|
|
957
903
|
|
|
958
904
|
if self._deduplicate(msg, self._errors):
|
|
@@ -1173,92 +1119,6 @@ class Display(metaclass=Singleton):
|
|
|
1173
1119
|
_display = Display()
|
|
1174
1120
|
|
|
1175
1121
|
|
|
1176
|
-
class _DeferredWarningContext(_ambient_context.AmbientContextBase):
|
|
1177
|
-
"""
|
|
1178
|
-
Calls to `Display.warning()` and `Display.deprecated()` within this context will cause the resulting warnings to be captured and not displayed.
|
|
1179
|
-
The intended use is for task-initiated warnings to be recorded with the task result, which makes them visible to registered results, callbacks, etc.
|
|
1180
|
-
The active display callback is responsible for communicating any warnings to the user.
|
|
1181
|
-
"""
|
|
1182
|
-
|
|
1183
|
-
# DTFIX-FUTURE: once we start implementing nested scoped contexts for our own bookkeeping, this should be an interface facade that forwards to the nearest
|
|
1184
|
-
# context that actually implements the warnings collection capability
|
|
1185
|
-
|
|
1186
|
-
def __init__(self, *, variables: dict[str, object]) -> None:
|
|
1187
|
-
self._variables = variables # DTFIX-FUTURE: move this to an AmbientContext-derived TaskContext (once it exists)
|
|
1188
|
-
self._deprecation_warnings: list[_messages.DeprecationSummary] = []
|
|
1189
|
-
self._warnings: list[_messages.WarningSummary] = []
|
|
1190
|
-
self._seen: set[_messages.WarningSummary] = set()
|
|
1191
|
-
|
|
1192
|
-
@classmethod
|
|
1193
|
-
def deprecation_warnings_enabled(cls) -> bool:
|
|
1194
|
-
"""Return True if deprecation warnings are enabled for the current calling context, otherwise False."""
|
|
1195
|
-
# DTFIX-FUTURE: move this capability into config using an AmbientContext-derived TaskContext (once it exists)
|
|
1196
|
-
if warning_ctx := cls.current(optional=True):
|
|
1197
|
-
variables = warning_ctx._variables
|
|
1198
|
-
else:
|
|
1199
|
-
variables = None
|
|
1200
|
-
|
|
1201
|
-
return C.config.get_config_value('DEPRECATION_WARNINGS', variables=variables)
|
|
1202
|
-
|
|
1203
|
-
def capture(self, warning: _messages.WarningSummary) -> None:
|
|
1204
|
-
"""Add the warning/deprecation to the context if it has not already been seen by this context."""
|
|
1205
|
-
if warning in self._seen:
|
|
1206
|
-
return
|
|
1207
|
-
|
|
1208
|
-
self._seen.add(warning)
|
|
1209
|
-
|
|
1210
|
-
if isinstance(warning, _messages.DeprecationSummary):
|
|
1211
|
-
self._deprecation_warnings.append(warning)
|
|
1212
|
-
else:
|
|
1213
|
-
self._warnings.append(warning)
|
|
1214
|
-
|
|
1215
|
-
def get_warnings(self) -> list[_messages.WarningSummary]:
|
|
1216
|
-
"""Return a list of the captured non-deprecation warnings."""
|
|
1217
|
-
# DTFIX-FUTURE: return a read-only list proxy instead
|
|
1218
|
-
return self._warnings
|
|
1219
|
-
|
|
1220
|
-
def get_deprecation_warnings(self) -> list[_messages.DeprecationSummary]:
|
|
1221
|
-
"""Return a list of the captured deprecation warnings."""
|
|
1222
|
-
# DTFIX-FUTURE: return a read-only list proxy instead
|
|
1223
|
-
return self._deprecation_warnings
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
def _join_sentences(first: str | None, second: str | None) -> str:
|
|
1227
|
-
"""Join two sentences together."""
|
|
1228
|
-
first = (first or '').strip()
|
|
1229
|
-
second = (second or '').strip()
|
|
1230
|
-
|
|
1231
|
-
if first and first[-1] not in ('!', '?', '.'):
|
|
1232
|
-
first += '.'
|
|
1233
|
-
|
|
1234
|
-
if second and second[-1] not in ('!', '?', '.'):
|
|
1235
|
-
second += '.'
|
|
1236
|
-
|
|
1237
|
-
if first and not second:
|
|
1238
|
-
return first
|
|
1239
|
-
|
|
1240
|
-
if not first and second:
|
|
1241
|
-
return second
|
|
1242
|
-
|
|
1243
|
-
return ' '.join((first, second))
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
def _format_message(summary: _messages.SummaryBase, include_traceback: bool) -> str:
|
|
1247
|
-
if isinstance(summary, _messages.DeprecationSummary):
|
|
1248
|
-
deprecation_message = _display._get_deprecation_message_with_plugin_info(
|
|
1249
|
-
msg=summary.event.msg,
|
|
1250
|
-
version=summary.version,
|
|
1251
|
-
date=summary.date,
|
|
1252
|
-
deprecator=summary.deprecator,
|
|
1253
|
-
)
|
|
1254
|
-
|
|
1255
|
-
event = dataclasses.replace(summary.event, msg=deprecation_message)
|
|
1256
|
-
else:
|
|
1257
|
-
event = summary.event
|
|
1258
|
-
|
|
1259
|
-
return _event_formatting.format_event(event, include_traceback)
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
1122
|
def _report_config_warnings(deprecator: _messages.PluginInfo) -> None:
|
|
1263
1123
|
"""Called by config to report warnings/deprecations collected during a config parse."""
|
|
1264
1124
|
while config._errors:
|
|
@@ -3,9 +3,10 @@ ansible/__main__.py,sha256=24j-7-YT4lZ2fmV80JD-VRoYBnxR7YoP_VP-orJtDt0,796
|
|
|
3
3
|
ansible/constants.py,sha256=qef45QpHi-yFFMvllvNKmqFpXdKKr304e5fEZnjgwZc,7989
|
|
4
4
|
ansible/context.py,sha256=oKYyfjfWpy8vDeProtqfnqSmuij_t75_5e5t0U_hQ1g,1933
|
|
5
5
|
ansible/keyword_desc.yml,sha256=5rGCsr-0B8w2D67qBD6q_2WFxfqj9ieb0V_2J-dZJ5E,7547
|
|
6
|
-
ansible/release.py,sha256=
|
|
6
|
+
ansible/release.py,sha256=Xgr1-JjfOeMfCIvJCcOKH_JeYDXWWa39EE7RLsaJ_8A,852
|
|
7
7
|
ansible/_internal/__init__.py,sha256=J3yCEAZoJLwxHMPEIWHwX6seRTCQ4Sr7cfHSw11ik9k,2208
|
|
8
8
|
ansible/_internal/_collection_proxy.py,sha256=V3Zns3jdWR1hTP6q4mrNWoIKL67ayiQFPDOb6F7igsc,1228
|
|
9
|
+
ansible/_internal/_display_utils.py,sha256=2dOknOQpt_GW2AkoMUJxPvmQUCAVYv911KwX6Dwrh0c,5651
|
|
9
10
|
ansible/_internal/_event_formatting.py,sha256=cHMsuYi6v2W3fgEYdKLSe8O34kW5bZE26zyj7FOt268,4222
|
|
10
11
|
ansible/_internal/_locking.py,sha256=8jMXsKSNCKVZRUesZWb5Hx45g9UVVZ9JXUa_fq2004Q,669
|
|
11
12
|
ansible/_internal/_task.py,sha256=NCEF3sPxt99n4Gk-e00A9Ce52duffThJm0qlmgkm0nQ,3293
|
|
@@ -104,12 +105,12 @@ ansible/executor/module_common.py,sha256=sXMOvKj_9ubeBaCPVBHh76uHaRYZm-8mOhsSG55
|
|
|
104
105
|
ansible/executor/play_iterator.py,sha256=ybui896hQFJ4wLsYC3fZoJY4KEsX69QkCoMfomQyEqE,32310
|
|
105
106
|
ansible/executor/playbook_executor.py,sha256=5wjvqw22RG4g_JlYDQnLFrUEa8aYQBWdgKhEpNonhKQ,14806
|
|
106
107
|
ansible/executor/stats.py,sha256=Rw-Q73xYvXnYOt-LJFnHAR03NvVR3ESgbMkHnVGhIPI,3180
|
|
107
|
-
ansible/executor/task_executor.py,sha256=
|
|
108
|
+
ansible/executor/task_executor.py,sha256=xjW5oy2oRRZZSxp1kfqK3hjDLe1iv7bwHr6n1HJEKY0,61485
|
|
108
109
|
ansible/executor/task_queue_manager.py,sha256=QiakfDZUCyrhJLSNxUGNjUlsqscCI-YM1G2cLqVb_Qk,18805
|
|
109
110
|
ansible/executor/task_result.py,sha256=e73P110j8hcw9wv8O7p-z6St5VIvyP6iOV4cW4sswV8,10254
|
|
110
111
|
ansible/executor/discovery/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
111
112
|
ansible/executor/powershell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
112
|
-
ansible/executor/powershell/async_watchdog.ps1,sha256=
|
|
113
|
+
ansible/executor/powershell/async_watchdog.ps1,sha256=3jjFtjmoRWolXRXaKCYLapdw-Uy6MQ3qGvqAum0zBhw,4440
|
|
113
114
|
ansible/executor/powershell/async_wrapper.ps1,sha256=ad3dWEWj4ahH9yfvUvK4V7F5FzXwk2riAmWhPckTb-8,9112
|
|
114
115
|
ansible/executor/powershell/become_wrapper.ps1,sha256=z3L2RcabnwQhsEehU6NkRvGZSKVbdTTdDOMYPhr3y2Y,3864
|
|
115
116
|
ansible/executor/powershell/bootstrap_wrapper.ps1,sha256=11xDPllLkSRfYeSqcAAYu2DkmlKMSMDpwcRU2VwfEUs,1669
|
|
@@ -211,9 +212,9 @@ ansible/inventory/host.py,sha256=cZw906LeMYe6oF3ZxW6K2HWoW2Qc0jxHssg_C8cRumE,493
|
|
|
211
212
|
ansible/inventory/manager.py,sha256=fxg2sq7s-VBJnn9TvJCgv-xvYIu0DLJTix_y3w0wLcc,31811
|
|
212
213
|
ansible/module_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
213
214
|
ansible/module_utils/_text.py,sha256=VkWgAnSNVCbTQqZgllUObBFsH3uM4EUW5srl1UR9t1g,544
|
|
214
|
-
ansible/module_utils/ansible_release.py,sha256=
|
|
215
|
+
ansible/module_utils/ansible_release.py,sha256=Xgr1-JjfOeMfCIvJCcOKH_JeYDXWWa39EE7RLsaJ_8A,852
|
|
215
216
|
ansible/module_utils/api.py,sha256=8BmCzQtp9rClsLGlDn4I9iJrUFLCdnoEIxYX59_IL9c,5756
|
|
216
|
-
ansible/module_utils/basic.py,sha256=
|
|
217
|
+
ansible/module_utils/basic.py,sha256=wdA7c-JBcn4obTlQQugJuiJAVtEZtOmMBpV02Izl_CM,90137
|
|
217
218
|
ansible/module_utils/connection.py,sha256=ZwtQEs-TtT-XecoEmFWiDevSkJLIj348YkiW6PP7G9E,7471
|
|
218
219
|
ansible/module_utils/datatag.py,sha256=tEwBXm75G_Hrk7I0dj_B1htFmIFCGDB_ifO-3MPPSHs,1659
|
|
219
220
|
ansible/module_utils/errors.py,sha256=cOVAUZaQTeYaSGhKnYsT3L8vshayQHbCXzkT6HIVi_o,3345
|
|
@@ -221,7 +222,7 @@ ansible/module_utils/json_utils.py,sha256=DzkQvlXMD_clOPxRXv7rZwAwMAUii3XH_MvhS4
|
|
|
221
222
|
ansible/module_utils/service.py,sha256=tjsQW8jbaCXr7hG-echcnCASdbdrlmAK2kfb9SI7R_g,9797
|
|
222
223
|
ansible/module_utils/splitter.py,sha256=MnvQVnEZ_ceiso1JsesGjaK-PTKcSPOd2FH9FKX8wLA,9468
|
|
223
224
|
ansible/module_utils/testing.py,sha256=BbQdvHibcqCtze3XrX7eXYbyGF3UKRmNqfPviosSVNk,1144
|
|
224
|
-
ansible/module_utils/urls.py,sha256=
|
|
225
|
+
ansible/module_utils/urls.py,sha256=oZSLYArN3AdS6rRKLPEKgBxpNXGYKZp34z9CxN_7ywA,55872
|
|
225
226
|
ansible/module_utils/yumdnf.py,sha256=dgMG2ASj5CdWgkxt8skEw9kTMt6cQVanhr4oVBSMH7M,7091
|
|
226
227
|
ansible/module_utils/_internal/__init__.py,sha256=zCUoK0GPIBa-O45g5CLZkXBASFcwLrkuZnh6ljdWIto,2124
|
|
227
228
|
ansible/module_utils/_internal/_ambient_context.py,sha256=sZe6kovlSCfiqZm6T-AX_kgKuTaLf8KP7a5gTVf9fV8,2579
|
|
@@ -501,8 +502,8 @@ ansible/playbook/role/include.py,sha256=yGBXglTQDtCpZ2XO1mVxp2UtsdLpLTt30KVR2AbB
|
|
|
501
502
|
ansible/playbook/role/metadata.py,sha256=h439HGUucs2gOMUJlp2M0OO0_wnWWlQmTs_sOe8h6Sc,5018
|
|
502
503
|
ansible/playbook/role/requirement.py,sha256=CNgLa0J6zZk2YQ_aeALnjQvehkkFXhrK8LQQZs7Ztzc,4173
|
|
503
504
|
ansible/plugins/__init__.py,sha256=Rxl7OPg_ndRCRc9mvS9gwogy4wTlR00kaJ9KnUSNCeo,8042
|
|
504
|
-
ansible/plugins/list.py,sha256=
|
|
505
|
-
ansible/plugins/loader.py,sha256=
|
|
505
|
+
ansible/plugins/list.py,sha256=yfAg8xseUyTSH68IV4NbbXRjYJxDcDyfVXgD8l5Eh9o,11410
|
|
506
|
+
ansible/plugins/loader.py,sha256=0TVRpIvAF_pBTOJOCFAjPwf-B1zAosUCk18qViI1IZU,82247
|
|
506
507
|
ansible/plugins/action/__init__.py,sha256=OR_i4YbdEYD8YQQIm0Dav_yDX9rHaN0YKSHsc9zZGJE,69391
|
|
507
508
|
ansible/plugins/action/add_host.py,sha256=Pil69LPaJpUulx-483MkZBRaiFaf14CkT0cCVw6aa_s,3575
|
|
508
509
|
ansible/plugins/action/assemble.py,sha256=gai336EN6ipGdoRPk6sLTBUrHUzviyMnj9UfMvYgg1Y,6153
|
|
@@ -656,7 +657,7 @@ ansible/plugins/inventory/constructed.py,sha256=N1oj4IDE6rXqTd3r0yGtuwLNYtuzbBRb
|
|
|
656
657
|
ansible/plugins/inventory/generator.py,sha256=90Zhmt3MK5_Nfz4lL3jjozO0p8eiIlz2WqoyH7ITygI,5824
|
|
657
658
|
ansible/plugins/inventory/host_list.py,sha256=DZayr155_Izfb5YGvzL7OMyWc-QQwyg04h5eDaFq8P8,2348
|
|
658
659
|
ansible/plugins/inventory/ini.py,sha256=7kkySGQYkXDISkh2JrK0izI8HfeMnSzD8nY28ZunQok,19358
|
|
659
|
-
ansible/plugins/inventory/script.py,sha256=
|
|
660
|
+
ansible/plugins/inventory/script.py,sha256=kYQdNHM16TZXOGNNHEXYC0xuaDknylcZcj3DQBHFahQ,15227
|
|
660
661
|
ansible/plugins/inventory/toml.py,sha256=xZnpzVtxtCEZ1aBB0SpAjy2iO0qpL01-QVnCihiCBfQ,5577
|
|
661
662
|
ansible/plugins/inventory/yaml.py,sha256=Z6ANo6E20DM6Axs1cd6z7jUv5Tur-dHEtRsx0LmGm58,7530
|
|
662
663
|
ansible/plugins/lookup/__init__.py,sha256=95ildPoHi21L34ULD1h6mNknuQ3yrjZCBaE5rPdODi8,5523
|
|
@@ -758,7 +759,7 @@ ansible/utils/_junit_xml.py,sha256=5op7cjGK7Et0OSjcAAuUEqNWNAv5ZoNI0rkLx2ERXwM,8
|
|
|
758
759
|
ansible/utils/cmd_functions.py,sha256=VmGs5ntdVaaqAJHcCTpGG3rYAAcTNl1b2-Iw4YVOt9Y,2180
|
|
759
760
|
ansible/utils/color.py,sha256=LjJO_12OsJiavBxwSDVXtLxdTzdwd2YWUp1OJ6KcM2g,4057
|
|
760
761
|
ansible/utils/context_objects.py,sha256=vYulSJkzR3zxsQF_6_AqbPCCMy8WGC5dSqLFXJZqGIo,3034
|
|
761
|
-
ansible/utils/display.py,sha256=
|
|
762
|
+
ansible/utils/display.py,sha256=R_GQSus5faUsL0JhyZKT9HyRyQPHvJoPRR3TiQa8j34,43433
|
|
762
763
|
ansible/utils/encrypt.py,sha256=67J5Q7rRk5wz1mNTNuMu7wWOGbMMZJS7VHFJqMfMqdg,7719
|
|
763
764
|
ansible/utils/fqcn.py,sha256=_wPNWMkR0mqRdkr6fn9FRgEkaCQHw40yardWe97FfEc,1215
|
|
764
765
|
ansible/utils/galaxy.py,sha256=xdfYGrHAz0KJB2N0zvAFAx5ZXNldDZnA8F4L3to7Q40,3859
|
|
@@ -789,12 +790,12 @@ ansible/vars/hostvars.py,sha256=cRK_4dssUwIN4aDxxYXEj7KzTazrykQ4PbJotne5oJc,4364
|
|
|
789
790
|
ansible/vars/manager.py,sha256=1SNGcwMTT7m8aPC45DHdkOZRtnf7OEcuExBtocJusq4,28023
|
|
790
791
|
ansible/vars/plugins.py,sha256=8svEABS2yBPzEdymdsrZ-0D70boUoCNvcgkWasvtVNo,4533
|
|
791
792
|
ansible/vars/reserved.py,sha256=NgxlMBm_tloqDVb5TEX4eGhpYsz_AO6-Fmyi3kJpIFk,3107
|
|
792
|
-
ansible_core-2.19.
|
|
793
|
-
ansible_core-2.19.
|
|
794
|
-
ansible_core-2.19.
|
|
795
|
-
ansible_core-2.19.
|
|
796
|
-
ansible_core-2.19.
|
|
797
|
-
ansible_core-2.19.
|
|
793
|
+
ansible_core-2.19.3.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
794
|
+
ansible_core-2.19.3.dist-info/licenses/licenses/Apache-License.txt,sha256=y16Ofl9KOYjhBjwULGDcLfdWBfTEZRXnduOspt-XbhQ,11325
|
|
795
|
+
ansible_core-2.19.3.dist-info/licenses/licenses/BSD-3-Clause.txt,sha256=la0N3fE3Se8vBiuvUcFKA8b-E41G7flTic6P8CkUroE,1548
|
|
796
|
+
ansible_core-2.19.3.dist-info/licenses/licenses/MIT-license.txt,sha256=jLXp2XurnyZKbye40g9tfmLGtVlxh3pPD4n8xNqX8xc,1023
|
|
797
|
+
ansible_core-2.19.3.dist-info/licenses/licenses/PSF-license.txt,sha256=g7BC_H1qyg8Q1o5F76Vrm8ChSWYI5-dyj-CdGlNKBUo,2484
|
|
798
|
+
ansible_core-2.19.3.dist-info/licenses/licenses/simplified_bsd.txt,sha256=8R5R7R7sOa0h1Fi6RNgFgHowHBfun-OVOMzJ4rKAk2w,1237
|
|
798
799
|
ansible_test/__init__.py,sha256=20VPOj11c6Ut1Av9RaurgwJvFhMqkWG3vAvcCbecNKw,66
|
|
799
800
|
ansible_test/_data/ansible.cfg,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
800
801
|
ansible_test/_data/coveragerc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -1091,8 +1092,8 @@ ansible_test/config/cloud-config-vultr.ini.template,sha256=XLKHk3lg_8ReQMdWfZzhh
|
|
|
1091
1092
|
ansible_test/config/config.yml,sha256=1zdGucnIl6nIecZA7ISIANvqXiHWqq6Dthsk_6MUwNc,2642
|
|
1092
1093
|
ansible_test/config/inventory.networking.template,sha256=bFNSk8zNQOaZ_twaflrY0XZ9mLwUbRLuNT0BdIFwvn4,1335
|
|
1093
1094
|
ansible_test/config/inventory.winrm.template,sha256=1QU8W-GFLnYEw8yY9bVIvUAVvJYPM3hyoijf6-M7T00,1098
|
|
1094
|
-
ansible_core-2.19.
|
|
1095
|
-
ansible_core-2.19.
|
|
1096
|
-
ansible_core-2.19.
|
|
1097
|
-
ansible_core-2.19.
|
|
1098
|
-
ansible_core-2.19.
|
|
1095
|
+
ansible_core-2.19.3.dist-info/METADATA,sha256=6ZLvqxNXas6vc2Voroik0QPpH07uEuze3W2o_ZNP2K0,7730
|
|
1096
|
+
ansible_core-2.19.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
1097
|
+
ansible_core-2.19.3.dist-info/entry_points.txt,sha256=S9yJij5Im6FgRQxzkqSCnPQokC7PcWrDW_NSygZczJU,451
|
|
1098
|
+
ansible_core-2.19.3.dist-info/top_level.txt,sha256=IFbRLjAvih1DYzJWg3_F6t4sCzEMxRO7TOMNs6GkYHo,21
|
|
1099
|
+
ansible_core-2.19.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/licenses/licenses/MIT-license.txt
RENAMED
|
File without changes
|
{ansible_core-2.19.2rc1.dist-info → ansible_core-2.19.3.dist-info}/licenses/licenses/PSF-license.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|