ansible-core 2.19.4rc1__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.4rc1.dist-info → ansible_core-2.20.0.dist-info}/METADATA +4 -4
- {ansible_core-2.19.4rc1.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.4rc1.dist-info → ansible_core-2.20.0.dist-info}/WHEEL +0 -0
- {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
- {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/top_level.txt +0 -0
|
@@ -24,13 +24,13 @@ import re
|
|
|
24
24
|
import sys
|
|
25
25
|
import time
|
|
26
26
|
|
|
27
|
+
from ansible.module_utils._internal import _no_six
|
|
27
28
|
from ansible.module_utils._internal._concurrent import _futures
|
|
28
29
|
from ansible.module_utils.common.locale import get_best_parsable_locale
|
|
29
30
|
from ansible.module_utils.common.text.converters import to_text
|
|
30
31
|
from ansible.module_utils.common.text.formatters import bytes_to_human
|
|
31
32
|
from ansible.module_utils.facts.hardware.base import Hardware, HardwareCollector
|
|
32
33
|
from ansible.module_utils.facts.utils import get_file_content, get_file_lines, get_mount_size
|
|
33
|
-
from ansible.module_utils.six import iteritems
|
|
34
34
|
|
|
35
35
|
# import this as a module to ensure we get the same module instance
|
|
36
36
|
from ansible.module_utils.facts import timeout
|
|
@@ -653,7 +653,7 @@ class LinuxHardware(Hardware):
|
|
|
653
653
|
retval[target].add(entry)
|
|
654
654
|
except OSError:
|
|
655
655
|
continue
|
|
656
|
-
return dict((k, list(sorted(v))) for (k, v) in
|
|
656
|
+
return dict((k, list(sorted(v))) for (k, v) in retval.items())
|
|
657
657
|
except OSError:
|
|
658
658
|
return {}
|
|
659
659
|
|
|
@@ -665,7 +665,7 @@ class LinuxHardware(Hardware):
|
|
|
665
665
|
device = elements[3]
|
|
666
666
|
target = elements[5]
|
|
667
667
|
retval[target].add(device)
|
|
668
|
-
return dict((k, list(sorted(v))) for (k, v) in
|
|
668
|
+
return dict((k, list(sorted(v))) for (k, v) in retval.items())
|
|
669
669
|
except OSError:
|
|
670
670
|
return {}
|
|
671
671
|
|
|
@@ -750,7 +750,7 @@ class LinuxHardware(Hardware):
|
|
|
750
750
|
d = {}
|
|
751
751
|
d['virtual'] = virtual
|
|
752
752
|
d['links'] = {}
|
|
753
|
-
for (link_type, link_values) in
|
|
753
|
+
for (link_type, link_values) in links.items():
|
|
754
754
|
d['links'][link_type] = link_values.get(block, [])
|
|
755
755
|
diskname = os.path.basename(sysdir)
|
|
756
756
|
for key in ['vendor', 'model', 'sas_address', 'sas_device_handle']:
|
|
@@ -801,7 +801,7 @@ class LinuxHardware(Hardware):
|
|
|
801
801
|
part_sysdir = sysdir + "/" + partname
|
|
802
802
|
|
|
803
803
|
part['links'] = {}
|
|
804
|
-
for (link_type, link_values) in
|
|
804
|
+
for (link_type, link_values) in links.items():
|
|
805
805
|
part['links'][link_type] = link_values.get(partname, [])
|
|
806
806
|
|
|
807
807
|
part['start'] = get_file_content(part_sysdir + "/start", 0)
|
|
@@ -890,7 +890,8 @@ class LinuxHardware(Hardware):
|
|
|
890
890
|
'size_g': items[-2],
|
|
891
891
|
'free_g': items[-1],
|
|
892
892
|
'num_lvs': items[2],
|
|
893
|
-
'num_pvs': items[1]
|
|
893
|
+
'num_pvs': items[1],
|
|
894
|
+
'lvs': {},
|
|
894
895
|
}
|
|
895
896
|
|
|
896
897
|
lvs_path = self.module.get_bin_path('lvs')
|
|
@@ -901,7 +902,18 @@ class LinuxHardware(Hardware):
|
|
|
901
902
|
rc, lv_lines, err = self.module.run_command('%s %s' % (lvs_path, lvm_util_options))
|
|
902
903
|
for lv_line in lv_lines.splitlines():
|
|
903
904
|
items = lv_line.strip().split(',')
|
|
904
|
-
|
|
905
|
+
vg_name = items[1]
|
|
906
|
+
lv_name = items[0]
|
|
907
|
+
# The LV name is only unique per VG, so the top level fact lvs can be misleading.
|
|
908
|
+
# TODO: deprecate lvs in favor of vgs
|
|
909
|
+
lvs[lv_name] = {'size_g': items[3], 'vg': vg_name}
|
|
910
|
+
try:
|
|
911
|
+
vgs[vg_name]['lvs'][lv_name] = {'size_g': items[3]}
|
|
912
|
+
except KeyError:
|
|
913
|
+
self.module.warn(
|
|
914
|
+
"An LVM volume group was created while gathering LVM facts, "
|
|
915
|
+
"and is not included in ansible_facts['vgs']."
|
|
916
|
+
)
|
|
905
917
|
|
|
906
918
|
pvs_path = self.module.get_bin_path('pvs')
|
|
907
919
|
# pvs fields: PV VG #Fmt #Attr PSize PFree
|
|
@@ -925,3 +937,7 @@ class LinuxHardwareCollector(HardwareCollector):
|
|
|
925
937
|
_fact_class = LinuxHardware
|
|
926
938
|
|
|
927
939
|
required_facts = set(['platform'])
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
def __getattr__(importable_name):
|
|
943
|
+
return _no_six.deprecate(importable_name, __name__, "iteritems")
|
|
@@ -19,7 +19,7 @@ import os
|
|
|
19
19
|
import re
|
|
20
20
|
import time
|
|
21
21
|
|
|
22
|
-
from
|
|
22
|
+
from functools import reduce
|
|
23
23
|
|
|
24
24
|
from ansible.module_utils.facts.hardware.base import Hardware, HardwareCollector
|
|
25
25
|
from ansible.module_utils.facts.timeout import TimeoutError, timeout
|
|
@@ -18,12 +18,13 @@ from __future__ import annotations
|
|
|
18
18
|
import re
|
|
19
19
|
import time
|
|
20
20
|
|
|
21
|
+
from functools import reduce
|
|
22
|
+
|
|
21
23
|
from ansible.module_utils.common.locale import get_best_parsable_locale
|
|
22
24
|
from ansible.module_utils.common.text.formatters import bytes_to_human
|
|
23
25
|
from ansible.module_utils.facts.utils import get_file_content, get_mount_size
|
|
24
26
|
from ansible.module_utils.facts.hardware.base import Hardware, HardwareCollector
|
|
25
27
|
from ansible.module_utils.facts import timeout
|
|
26
|
-
from ansible.module_utils.six.moves import reduce
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
class SunOSHardware(Hardware):
|
|
@@ -7,7 +7,7 @@ import ansible.module_utils.compat.typing as t
|
|
|
7
7
|
|
|
8
8
|
from abc import ABCMeta, abstractmethod
|
|
9
9
|
|
|
10
|
-
from ansible.module_utils.
|
|
10
|
+
from ansible.module_utils._internal import _no_six
|
|
11
11
|
from ansible.module_utils.basic import missing_required_lib
|
|
12
12
|
from ansible.module_utils.common.process import get_bin_path
|
|
13
13
|
from ansible.module_utils.common.respawn import has_respawned, probe_interpreters_for_module, respawn_module
|
|
@@ -19,7 +19,7 @@ def get_all_pkg_managers():
|
|
|
19
19
|
return {obj.__name__.lower(): obj for obj in get_all_subclasses(PkgMgr) if obj not in (CLIMgr, LibMgr, RespawningLibMgr)}
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class PkgMgr(
|
|
22
|
+
class PkgMgr(metaclass=ABCMeta):
|
|
23
23
|
|
|
24
24
|
@abstractmethod
|
|
25
25
|
def is_available(self, handle_exceptions):
|
|
@@ -125,3 +125,7 @@ class CLIMgr(PkgMgr):
|
|
|
125
125
|
if not handle_exceptions:
|
|
126
126
|
raise
|
|
127
127
|
return found
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def __getattr__(importable_name):
|
|
131
|
+
return _no_six.deprecate(importable_name, __name__, "with_metaclass")
|
|
@@ -529,7 +529,8 @@ class Distribution(object):
|
|
|
529
529
|
'EuroLinux', 'Kylin Linux Advanced Server', 'MIRACLE'],
|
|
530
530
|
'Debian': ['Debian', 'Ubuntu', 'Raspbian', 'Neon', 'KDE neon',
|
|
531
531
|
'Linux Mint', 'SteamOS', 'Devuan', 'Kali', 'Cumulus Linux',
|
|
532
|
-
'Pop!_OS', 'Parrot', 'Pardus GNU/Linux', 'Uos', 'Deepin', 'OSMC',
|
|
532
|
+
'Pop!_OS', 'Parrot', 'Pardus GNU/Linux', 'Uos', 'Deepin', 'OSMC',
|
|
533
|
+
'Linux Mint Debian Edition', 'Univention Corporate Server'],
|
|
533
534
|
'Suse': ['SuSE', 'SLES', 'SLED', 'openSUSE', 'openSUSE Tumbleweed',
|
|
534
535
|
'SLES_SAP', 'SUSE_LINUX', 'openSUSE Leap', 'ALP-Dolomite', 'SL-Micro',
|
|
535
536
|
'openSUSE MicroOS'],
|
|
@@ -18,8 +18,7 @@ from __future__ import annotations
|
|
|
18
18
|
import os
|
|
19
19
|
import typing as t
|
|
20
20
|
|
|
21
|
-
from ansible.module_utils.
|
|
22
|
-
|
|
21
|
+
from ansible.module_utils._internal import _no_six
|
|
23
22
|
from ansible.module_utils.facts.collector import BaseFactCollector
|
|
24
23
|
|
|
25
24
|
|
|
@@ -31,7 +30,11 @@ class EnvFactCollector(BaseFactCollector):
|
|
|
31
30
|
env_facts = {}
|
|
32
31
|
env_facts['env'] = {}
|
|
33
32
|
|
|
34
|
-
for k, v in
|
|
33
|
+
for k, v in os.environ.items():
|
|
35
34
|
env_facts['env'][k] = v
|
|
36
35
|
|
|
37
36
|
return env_facts
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def __getattr__(importable_name):
|
|
40
|
+
return _no_six.deprecate(importable_name, __name__, "iteritems")
|
|
@@ -3,16 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
|
+
import configparser
|
|
6
7
|
import glob
|
|
7
8
|
import json
|
|
8
9
|
import os
|
|
9
10
|
import stat
|
|
10
11
|
import typing as t
|
|
11
12
|
|
|
13
|
+
from io import StringIO
|
|
14
|
+
|
|
12
15
|
from ansible.module_utils.common.text.converters import to_text
|
|
13
16
|
from ansible.module_utils.facts.utils import get_file_content
|
|
14
17
|
from ansible.module_utils.facts.collector import BaseFactCollector
|
|
15
|
-
from ansible.module_utils.six.moves import configparser, StringIO
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
class LocalFactCollector(BaseFactCollector):
|
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
|
|
6
6
|
import collections.abc as c
|
|
7
7
|
|
|
8
|
-
from ansible.module_utils.
|
|
8
|
+
from ansible.module_utils._internal import _no_six
|
|
9
9
|
from ansible.module_utils.common.text.converters import to_text
|
|
10
10
|
|
|
11
11
|
|
|
@@ -20,7 +20,7 @@ def boolean(value, strict=True):
|
|
|
20
20
|
|
|
21
21
|
normalized_value = value
|
|
22
22
|
|
|
23
|
-
if isinstance(value, (
|
|
23
|
+
if isinstance(value, (str, bytes)):
|
|
24
24
|
normalized_value = to_text(value, errors='surrogate_or_strict').lower().strip()
|
|
25
25
|
|
|
26
26
|
if not isinstance(value, c.Hashable):
|
|
@@ -32,3 +32,7 @@ def boolean(value, strict=True):
|
|
|
32
32
|
return False
|
|
33
33
|
|
|
34
34
|
raise TypeError("The value '%s' is not a valid boolean. Valid booleans include: %s" % (to_text(value), ', '.join(repr(i) for i in BOOLEANS)))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def __getattr__(importable_name):
|
|
38
|
+
return _no_six.deprecate(importable_name, __name__, "binary_type", "text_type")
|
ansible/module_utils/service.py
CHANGED
|
@@ -36,7 +36,6 @@ import select
|
|
|
36
36
|
import shlex
|
|
37
37
|
import subprocess
|
|
38
38
|
|
|
39
|
-
from ansible.module_utils.six import b
|
|
40
39
|
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
|
41
40
|
|
|
42
41
|
|
|
@@ -200,7 +199,7 @@ def daemonize(module, cmd):
|
|
|
200
199
|
fds = [p.stdout, p.stderr]
|
|
201
200
|
|
|
202
201
|
# loop reading output till it is done
|
|
203
|
-
output = {p.stdout: b
|
|
202
|
+
output = {p.stdout: b"", p.stderr: b""}
|
|
204
203
|
while fds:
|
|
205
204
|
rfd, wfd, efd = select.select(fds, [], fds, 1)
|
|
206
205
|
if (rfd + wfd + efd) or p.poll() is None:
|
|
@@ -234,7 +233,7 @@ def daemonize(module, cmd):
|
|
|
234
233
|
os.waitpid(pid, 0)
|
|
235
234
|
|
|
236
235
|
# Grab response data after child finishes
|
|
237
|
-
return_data = b
|
|
236
|
+
return_data = b""
|
|
238
237
|
while True:
|
|
239
238
|
rfd, wfd, efd = select.select([pipe[0]], [], [pipe[0]])
|
|
240
239
|
if pipe[0] in rfd:
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# upstream vendored file that we're not going to modify on our own
|
|
4
4
|
# pylint: disable=undefined-variable
|
|
5
5
|
#
|
|
6
|
-
# Copyright (c) 2010-
|
|
6
|
+
# Copyright (c) 2010-2024 Benjamin Peterson
|
|
7
7
|
#
|
|
8
8
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
9
|
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -35,10 +35,10 @@ import types
|
|
|
35
35
|
|
|
36
36
|
# The following makes it easier for us to script updates of the bundled code. It is not part of
|
|
37
37
|
# upstream six
|
|
38
|
-
_BUNDLED_METADATA = {"pypi_name": "six", "version": "1.
|
|
38
|
+
_BUNDLED_METADATA = {"pypi_name": "six", "version": "1.17.0"}
|
|
39
39
|
|
|
40
40
|
__author__ = "Benjamin Peterson <benjamin@python.org>"
|
|
41
|
-
__version__ = "1.
|
|
41
|
+
__version__ = "1.17.0"
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
# Useful for very coarse version differentiation.
|
|
@@ -273,7 +273,7 @@ _moved_attributes = [
|
|
|
273
273
|
MovedAttribute("reduce", "__builtin__", "functools"),
|
|
274
274
|
MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
|
|
275
275
|
MovedAttribute("StringIO", "StringIO", "io"),
|
|
276
|
-
MovedAttribute("UserDict", "UserDict", "collections"),
|
|
276
|
+
MovedAttribute("UserDict", "UserDict", "collections", "IterableUserDict", "UserDict"),
|
|
277
277
|
MovedAttribute("UserList", "UserList", "collections"),
|
|
278
278
|
MovedAttribute("UserString", "UserString", "collections"),
|
|
279
279
|
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
|
|
@@ -445,12 +445,17 @@ _urllib_request_moved_attributes = [
|
|
|
445
445
|
MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
|
|
446
446
|
MovedAttribute("urlretrieve", "urllib", "urllib.request"),
|
|
447
447
|
MovedAttribute("urlcleanup", "urllib", "urllib.request"),
|
|
448
|
-
MovedAttribute("URLopener", "urllib", "urllib.request"),
|
|
449
|
-
MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
|
|
450
448
|
MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
|
|
451
449
|
MovedAttribute("parse_http_list", "urllib2", "urllib.request"),
|
|
452
450
|
MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"),
|
|
453
451
|
]
|
|
452
|
+
if sys.version_info[:2] < (3, 14):
|
|
453
|
+
_urllib_request_moved_attributes.extend(
|
|
454
|
+
[
|
|
455
|
+
MovedAttribute("URLopener", "urllib", "urllib.request"),
|
|
456
|
+
MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
|
|
457
|
+
]
|
|
458
|
+
)
|
|
454
459
|
for attr in _urllib_request_moved_attributes:
|
|
455
460
|
setattr(Module_six_moves_urllib_request, attr.name, attr)
|
|
456
461
|
del attr
|
ansible/module_utils/yumdnf.py
CHANGED
|
@@ -32,10 +32,6 @@ yumdnf_argument_spec = dict(
|
|
|
32
32
|
enablerepo=dict(type='list', elements='str', default=[]),
|
|
33
33
|
exclude=dict(type='list', elements='str', default=[]),
|
|
34
34
|
installroot=dict(type='str', default="/"),
|
|
35
|
-
install_repoquery=dict(
|
|
36
|
-
type='bool', default=True,
|
|
37
|
-
removed_in_version='2.20', removed_from_collection='ansible.builtin',
|
|
38
|
-
),
|
|
39
35
|
install_weak_deps=dict(type='bool', default=True),
|
|
40
36
|
list=dict(type='str'),
|
|
41
37
|
name=dict(type='list', elements='str', aliases=['pkg'], default=[]),
|
|
@@ -85,7 +81,6 @@ class YumDnf(metaclass=ABCMeta):
|
|
|
85
81
|
self.enablerepo = self.module.params.get('enablerepo', [])
|
|
86
82
|
self.exclude = self.module.params['exclude']
|
|
87
83
|
self.installroot = self.module.params['installroot']
|
|
88
|
-
self.install_repoquery = self.module.params['install_repoquery']
|
|
89
84
|
self.install_weak_deps = self.module.params['install_weak_deps']
|
|
90
85
|
self.list = self.module.params['list']
|
|
91
86
|
self.names = [p.strip() for p in self.module.params['name']]
|
ansible/modules/apt.py
CHANGED
|
@@ -372,6 +372,7 @@ import locale as locale_module
|
|
|
372
372
|
import os
|
|
373
373
|
import re
|
|
374
374
|
import secrets
|
|
375
|
+
import shlex
|
|
375
376
|
import shutil
|
|
376
377
|
import sys
|
|
377
378
|
import tempfile
|
|
@@ -382,7 +383,6 @@ from ansible.module_utils.common.file import S_IRWXU_RXG_RXO
|
|
|
382
383
|
from ansible.module_utils.common.locale import get_best_parsable_locale
|
|
383
384
|
from ansible.module_utils.common.respawn import has_respawned, probe_interpreters_for_module, respawn_module
|
|
384
385
|
from ansible.module_utils.common.text.converters import to_native, to_text
|
|
385
|
-
from ansible.module_utils.six import string_types
|
|
386
386
|
from ansible.module_utils.urls import fetch_file
|
|
387
387
|
|
|
388
388
|
DPKG_OPTIONS = 'force-confdef,force-confold'
|
|
@@ -390,8 +390,6 @@ APT_GET_ZERO = "\n0 upgraded, 0 newly installed, 0 to remove"
|
|
|
390
390
|
APTITUDE_ZERO = "\n0 packages upgraded, 0 newly installed, 0 to remove"
|
|
391
391
|
APT_LISTS_PATH = "/var/lib/apt/lists"
|
|
392
392
|
APT_UPDATE_SUCCESS_STAMP_PATH = "/var/lib/apt/periodic/update-success-stamp"
|
|
393
|
-
APT_MARK_INVALID_OP = 'Invalid operation'
|
|
394
|
-
APT_MARK_INVALID_OP_DEB6 = 'Usage: apt-mark [options] {markauto|unmarkauto} packages'
|
|
395
393
|
|
|
396
394
|
CLEAN_OP_CHANGED_STR = dict(
|
|
397
395
|
autoremove='The following packages will be REMOVED',
|
|
@@ -634,7 +632,7 @@ def expand_pkgspec_from_fnmatches(m, pkgspec, cache):
|
|
|
634
632
|
if pkgspec:
|
|
635
633
|
for pkgspec_pattern in pkgspec:
|
|
636
634
|
|
|
637
|
-
if not isinstance(pkgspec_pattern,
|
|
635
|
+
if not isinstance(pkgspec_pattern, str):
|
|
638
636
|
m.fail_json(msg="Invalid type for package name, expected string but got %s" % type(pkgspec_pattern))
|
|
639
637
|
|
|
640
638
|
pkgname_pattern, version_cmp, version = package_split(pkgspec_pattern)
|
|
@@ -690,26 +688,30 @@ def parse_diff(output):
|
|
|
690
688
|
return {'prepared': '\n'.join(diff[diff_start:diff_end])}
|
|
691
689
|
|
|
692
690
|
|
|
693
|
-
def
|
|
691
|
+
def mark_installed(m: AnsibleModule, packages: list[str], manual: bool) -> None:
|
|
692
|
+
"""Mark packages as manually or automatically installed."""
|
|
694
693
|
if not packages:
|
|
695
694
|
return
|
|
696
695
|
|
|
696
|
+
if manual:
|
|
697
|
+
mark_msg = "manually"
|
|
698
|
+
mark_op = "manual"
|
|
699
|
+
else:
|
|
700
|
+
mark_msg = "auto"
|
|
701
|
+
mark_op = "auto"
|
|
702
|
+
|
|
697
703
|
apt_mark_cmd_path = m.get_bin_path("apt-mark")
|
|
698
704
|
|
|
699
705
|
# https://github.com/ansible/ansible/issues/40531
|
|
700
706
|
if apt_mark_cmd_path is None:
|
|
701
|
-
m.warn("Could not find apt-mark binary, not marking package(s) as
|
|
707
|
+
m.warn(f"Could not find apt-mark binary, not marking package(s) as {mark_msg} installed.")
|
|
702
708
|
return
|
|
703
709
|
|
|
704
|
-
cmd =
|
|
710
|
+
cmd = [apt_mark_cmd_path, mark_op] + packages
|
|
705
711
|
rc, out, err = m.run_command(cmd)
|
|
706
712
|
|
|
707
|
-
if APT_MARK_INVALID_OP in err or APT_MARK_INVALID_OP_DEB6 in err:
|
|
708
|
-
cmd = "%s unmarkauto %s" % (apt_mark_cmd_path, ' '.join(packages))
|
|
709
|
-
rc, out, err = m.run_command(cmd)
|
|
710
|
-
|
|
711
713
|
if rc != 0:
|
|
712
|
-
m.fail_json(msg="
|
|
714
|
+
m.fail_json(msg=f"Command {shlex.join(cmd)!r} failed.", stdout=out, stderr=err, rc=rc)
|
|
713
715
|
|
|
714
716
|
|
|
715
717
|
def install(m, pkgspec, cache, upgrade=False, default_release=None,
|
|
@@ -835,7 +837,7 @@ def install(m, pkgspec, cache, upgrade=False, default_release=None,
|
|
|
835
837
|
data = dict(changed=False)
|
|
836
838
|
|
|
837
839
|
if not build_dep and not m.check_mode:
|
|
838
|
-
|
|
840
|
+
mark_installed(m, package_names, manual=True)
|
|
839
841
|
|
|
840
842
|
return (status, data)
|
|
841
843
|
|
|
@@ -914,6 +916,9 @@ def install_deb(
|
|
|
914
916
|
dpkg_options=install_dpkg_options)
|
|
915
917
|
if not success:
|
|
916
918
|
m.fail_json(**retvals)
|
|
919
|
+
# Mark the dependencies as auto installed
|
|
920
|
+
# https://github.com/ansible/ansible/issues/78123
|
|
921
|
+
mark_installed(m, deps_to_install, manual=False)
|
|
917
922
|
changed = retvals.get('changed', False)
|
|
918
923
|
|
|
919
924
|
if pkgs_to_install:
|
|
@@ -508,7 +508,7 @@ class UbuntuSourcesList(SourcesList):
|
|
|
508
508
|
try:
|
|
509
509
|
rc, out, err = self.module.run_command([self.gpg_bin, '--list-packets', key_file])
|
|
510
510
|
except OSError as ex:
|
|
511
|
-
self.debug(f"Could check key against file {key_file!r}: {ex}")
|
|
511
|
+
self.module.debug(f"Could check key against file {key_file!r}: {ex}")
|
|
512
512
|
continue
|
|
513
513
|
|
|
514
514
|
if key_fingerprint in out:
|
ansible/modules/assemble.py
CHANGED
|
@@ -131,7 +131,6 @@ import re
|
|
|
131
131
|
import tempfile
|
|
132
132
|
|
|
133
133
|
from ansible.module_utils.basic import AnsibleModule
|
|
134
|
-
from ansible.module_utils.six import b, indexbytes
|
|
135
134
|
from ansible.module_utils.common.text.converters import to_native
|
|
136
135
|
|
|
137
136
|
|
|
@@ -141,6 +140,7 @@ def assemble_from_fragments(src_path, delimiter=None, compiled_regexp=None, igno
|
|
|
141
140
|
tmp = os.fdopen(tmpfd, 'wb')
|
|
142
141
|
delimit_me = False
|
|
143
142
|
add_newline = False
|
|
143
|
+
b_linesep = os.linesep.encode()
|
|
144
144
|
|
|
145
145
|
for f in sorted(os.listdir(src_path)):
|
|
146
146
|
if compiled_regexp and not compiled_regexp.search(f):
|
|
@@ -153,7 +153,7 @@ def assemble_from_fragments(src_path, delimiter=None, compiled_regexp=None, igno
|
|
|
153
153
|
|
|
154
154
|
# always put a newline between fragments if the previous fragment didn't end with a newline.
|
|
155
155
|
if add_newline:
|
|
156
|
-
tmp.write(
|
|
156
|
+
tmp.write(b_linesep)
|
|
157
157
|
|
|
158
158
|
# delimiters should only appear between fragments
|
|
159
159
|
if delimit_me:
|
|
@@ -163,16 +163,12 @@ def assemble_from_fragments(src_path, delimiter=None, compiled_regexp=None, igno
|
|
|
163
163
|
tmp.write(delimiter)
|
|
164
164
|
# always make sure there's a newline after the
|
|
165
165
|
# delimiter, so lines don't run together
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
# use indexbytes for compat
|
|
169
|
-
# chr(10) == '\n'
|
|
170
|
-
if indexbytes(delimiter, -1) != 10:
|
|
171
|
-
tmp.write(b('\n'))
|
|
166
|
+
if not delimiter.endswith(b_linesep):
|
|
167
|
+
tmp.write(b_linesep)
|
|
172
168
|
|
|
173
169
|
tmp.write(fragment_content)
|
|
174
170
|
delimit_me = True
|
|
175
|
-
if fragment_content.endswith(
|
|
171
|
+
if fragment_content.endswith(b_linesep):
|
|
176
172
|
add_newline = False
|
|
177
173
|
else:
|
|
178
174
|
add_newline = True
|
ansible/modules/blockinfile.py
CHANGED
|
@@ -102,6 +102,13 @@ options:
|
|
|
102
102
|
type: bool
|
|
103
103
|
default: no
|
|
104
104
|
version_added: '2.16'
|
|
105
|
+
encoding:
|
|
106
|
+
description:
|
|
107
|
+
- The character set in which the target file is encoded.
|
|
108
|
+
- For a list of available built-in encodings, see U(https://docs.python.org/3/library/codecs.html#standard-encodings)
|
|
109
|
+
type: str
|
|
110
|
+
default: utf-8
|
|
111
|
+
version_added: '2.20'
|
|
105
112
|
notes:
|
|
106
113
|
- When using C(with_*) loops be aware that if you do not set a unique mark the block will be overwritten on each iteration.
|
|
107
114
|
- As of Ansible 2.3, the O(dest) option has been changed to O(path) as default, but O(dest) still works as well.
|
|
@@ -192,15 +199,16 @@ EXAMPLES = r"""
|
|
|
192
199
|
import re
|
|
193
200
|
import os
|
|
194
201
|
import tempfile
|
|
195
|
-
|
|
202
|
+
|
|
196
203
|
from ansible.module_utils.basic import AnsibleModule
|
|
197
|
-
from ansible.module_utils.common.text.converters import
|
|
204
|
+
from ansible.module_utils.common.text.converters import to_native
|
|
198
205
|
|
|
199
206
|
|
|
200
|
-
def write_changes(module, contents, path):
|
|
207
|
+
def write_changes(module, contents, path, encoding=None):
|
|
201
208
|
|
|
202
209
|
tmpfd, tmpfile = tempfile.mkstemp(dir=module.tmpdir)
|
|
203
|
-
with
|
|
210
|
+
# newline param set to translate newline sequences with system default line separator
|
|
211
|
+
with os.fdopen(tmpfd, 'w', encoding=encoding, newline=None) as tf:
|
|
204
212
|
tf.write(contents)
|
|
205
213
|
|
|
206
214
|
validate = module.params.get('validate', None)
|
|
@@ -246,6 +254,7 @@ def main():
|
|
|
246
254
|
marker_end=dict(type='str', default='END'),
|
|
247
255
|
append_newline=dict(type='bool', default=False),
|
|
248
256
|
prepend_newline=dict(type='bool', default=False),
|
|
257
|
+
encoding=dict(type='str', default='utf-8'),
|
|
249
258
|
),
|
|
250
259
|
mutually_exclusive=[['insertbefore', 'insertafter']],
|
|
251
260
|
add_file_common_args=True,
|
|
@@ -254,6 +263,8 @@ def main():
|
|
|
254
263
|
params = module.params
|
|
255
264
|
path = params['path']
|
|
256
265
|
|
|
266
|
+
encoding = module.params.get('encoding', None)
|
|
267
|
+
|
|
257
268
|
if os.path.isdir(path):
|
|
258
269
|
module.fail_json(rc=256,
|
|
259
270
|
msg='Path %s is a directory !' % path)
|
|
@@ -274,7 +285,8 @@ def main():
|
|
|
274
285
|
original = None
|
|
275
286
|
lines = []
|
|
276
287
|
else:
|
|
277
|
-
|
|
288
|
+
# newline param set to preserve newline sequences read from file
|
|
289
|
+
with open(path, 'r', encoding=encoding, newline='') as f:
|
|
278
290
|
original = f.read()
|
|
279
291
|
lines = original.splitlines(True)
|
|
280
292
|
|
|
@@ -288,10 +300,12 @@ def main():
|
|
|
288
300
|
|
|
289
301
|
insertbefore = params['insertbefore']
|
|
290
302
|
insertafter = params['insertafter']
|
|
291
|
-
block =
|
|
292
|
-
marker =
|
|
303
|
+
block = params['block']
|
|
304
|
+
marker = params['marker']
|
|
293
305
|
present = params['state'] == 'present'
|
|
294
|
-
|
|
306
|
+
|
|
307
|
+
line_separator = os.linesep
|
|
308
|
+
blank_line = [line_separator]
|
|
295
309
|
|
|
296
310
|
if not present and not path_exists:
|
|
297
311
|
module.exit_json(changed=False, msg="File %s not present" % path)
|
|
@@ -300,17 +314,19 @@ def main():
|
|
|
300
314
|
insertafter = 'EOF'
|
|
301
315
|
|
|
302
316
|
if insertafter not in (None, 'EOF'):
|
|
303
|
-
insertre = re.compile(
|
|
317
|
+
insertre = re.compile(insertafter)
|
|
304
318
|
elif insertbefore not in (None, 'BOF'):
|
|
305
|
-
insertre = re.compile(
|
|
319
|
+
insertre = re.compile(insertbefore)
|
|
306
320
|
else:
|
|
307
321
|
insertre = None
|
|
308
322
|
|
|
309
|
-
marker0 = re.sub(
|
|
310
|
-
marker1 = re.sub(
|
|
323
|
+
marker0 = re.sub(r'{mark}', params['marker_begin'], marker) + line_separator
|
|
324
|
+
marker1 = re.sub(r'{mark}', params['marker_end'], marker) + line_separator
|
|
325
|
+
|
|
311
326
|
if present and block:
|
|
312
|
-
if not block.endswith(
|
|
313
|
-
block +=
|
|
327
|
+
if not block.endswith(line_separator):
|
|
328
|
+
block += line_separator
|
|
329
|
+
|
|
314
330
|
blocklines = [marker0] + block.splitlines(True) + [marker1]
|
|
315
331
|
else:
|
|
316
332
|
blocklines = []
|
|
@@ -329,9 +345,9 @@ def main():
|
|
|
329
345
|
match = insertre.search(original)
|
|
330
346
|
if match:
|
|
331
347
|
if insertafter:
|
|
332
|
-
n0 =
|
|
348
|
+
n0 = original.count('\n', 0, match.end())
|
|
333
349
|
elif insertbefore:
|
|
334
|
-
n0 =
|
|
350
|
+
n0 = original.count('\n', 0, match.start())
|
|
335
351
|
else:
|
|
336
352
|
for i, line in enumerate(lines):
|
|
337
353
|
if insertre.search(line):
|
|
@@ -352,15 +368,15 @@ def main():
|
|
|
352
368
|
|
|
353
369
|
# Ensure there is a line separator before the block of lines to be inserted
|
|
354
370
|
if n0 > 0:
|
|
355
|
-
if not lines[n0 - 1].endswith(
|
|
356
|
-
lines[n0 - 1] +=
|
|
371
|
+
if not lines[n0 - 1].endswith(line_separator):
|
|
372
|
+
lines[n0 - 1] += line_separator
|
|
357
373
|
|
|
358
374
|
# Before the block: check if we need to prepend a blank line
|
|
359
375
|
# If yes, we need to add the blank line if we are not at the beginning of the file
|
|
360
376
|
# and the previous line is not a blank line
|
|
361
377
|
# In both cases, we need to shift by one on the right the inserting position of the block
|
|
362
378
|
if params['prepend_newline'] and present:
|
|
363
|
-
if n0 != 0 and lines[n0 - 1] !=
|
|
379
|
+
if n0 != 0 and lines[n0 - 1] != line_separator:
|
|
364
380
|
lines[n0:n0] = blank_line
|
|
365
381
|
n0 += 1
|
|
366
382
|
|
|
@@ -372,13 +388,13 @@ def main():
|
|
|
372
388
|
# and the line right after is not a blank line
|
|
373
389
|
if params['append_newline'] and present:
|
|
374
390
|
line_after_block = n0 + len(blocklines)
|
|
375
|
-
if line_after_block < len(lines) and lines[line_after_block] !=
|
|
391
|
+
if line_after_block < len(lines) and lines[line_after_block] != line_separator:
|
|
376
392
|
lines[line_after_block:line_after_block] = blank_line
|
|
377
393
|
|
|
378
394
|
if lines:
|
|
379
|
-
result =
|
|
395
|
+
result = ''.join(lines)
|
|
380
396
|
else:
|
|
381
|
-
result =
|
|
397
|
+
result = ''
|
|
382
398
|
|
|
383
399
|
if module._diff:
|
|
384
400
|
diff['after'] = result
|
|
@@ -402,7 +418,7 @@ def main():
|
|
|
402
418
|
backup_file = module.backup_local(path)
|
|
403
419
|
# We should always follow symlinks so that we change the real file
|
|
404
420
|
real_path = os.path.realpath(params['path'])
|
|
405
|
-
write_changes(module, result, real_path)
|
|
421
|
+
write_changes(module, result, real_path, encoding)
|
|
406
422
|
|
|
407
423
|
if module.check_mode and not path_exists:
|
|
408
424
|
module.exit_json(changed=changed, msg=msg, diff=diff)
|