summaryrefslogtreecommitdiff
path: root/lib/ansible/plugins/action/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/plugins/action/__init__.py')
-rw-r--r--lib/ansible/plugins/action/__init__.py84
1 files changed, 43 insertions, 41 deletions
diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py
index 5ba3bd78..8f923253 100644
--- a/lib/ansible/plugins/action/__init__.py
+++ b/lib/ansible/plugins/action/__init__.py
@@ -27,7 +27,7 @@ from ansible.module_utils.common.arg_spec import ArgumentSpecValidator
from ansible.module_utils.errors import UnsupportedError
from ansible.module_utils.json_utils import _filter_non_json_lines
from ansible.module_utils.six import binary_type, string_types, text_type
-from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
+from ansible.module_utils._text import to_bytes, to_native, to_text
from ansible.parsing.utils.jsonify import jsonify
from ansible.release import __version__
from ansible.utils.collection_loader import resource_from_fqcr
@@ -39,18 +39,6 @@ from ansible.utils.plugin_docs import get_versioned_doclink
display = Display()
-def _validate_utf8_json(d):
- if isinstance(d, text_type):
- # Purposefully not using to_bytes here for performance reasons
- d.encode(encoding='utf-8', errors='strict')
- elif isinstance(d, dict):
- for o in d.items():
- _validate_utf8_json(o)
- elif isinstance(d, (list, tuple)):
- for o in d:
- _validate_utf8_json(o)
-
-
class ActionBase(ABC):
'''
@@ -63,13 +51,6 @@ class ActionBase(ABC):
# A set of valid arguments
_VALID_ARGS = frozenset([]) # type: frozenset[str]
- # behavioral attributes
- BYPASS_HOST_LOOP = False
- TRANSFERS_FILES = False
- _requires_connection = True
- _supports_check_mode = True
- _supports_async = False
-
def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj):
self._task = task
self._connection = connection
@@ -79,16 +60,20 @@ class ActionBase(ABC):
self._shared_loader_obj = shared_loader_obj
self._cleanup_remote_tmp = False
+ self._supports_check_mode = True
+ self._supports_async = False
+
# interpreter discovery state
self._discovered_interpreter_key = None
self._discovered_interpreter = False
self._discovery_deprecation_warnings = []
self._discovery_warnings = []
- self._used_interpreter = None
# Backwards compat: self._display isn't really needed, just import the global display and use that.
self._display = display
+ self._used_interpreter = None
+
@abstractmethod
def run(self, tmp=None, task_vars=None):
""" Action Plugins should implement this method to perform their
@@ -299,8 +284,7 @@ class ActionBase(ABC):
try:
(module_data, module_style, module_shebang) = modify_module(module_name, module_path, module_args, self._templar,
task_vars=use_vars,
- module_compression=C.config.get_config_value('DEFAULT_MODULE_COMPRESSION',
- variables=task_vars),
+ module_compression=self._play_context.module_compression,
async_timeout=self._task.async_val,
environment=final_environment,
remote_is_local=bool(getattr(self._connection, '_remote_is_local', False)),
@@ -739,7 +723,8 @@ class ActionBase(ABC):
return remote_paths
# we'll need this down here
- become_link = get_versioned_doclink('playbook_guide/playbooks_privilege_escalation.html')
+ become_link = get_versioned_doclink('playbook_guide/playbooks_privilege_escalation.html#risks-of-becoming-an-unprivileged-user')
+
# Step 3f: Common group
# Otherwise, we're a normal user. We failed to chown the paths to the
# unprivileged user, but if we have a common group with them, we should
@@ -876,6 +861,38 @@ class ActionBase(ABC):
return mystat['stat']
+ def _remote_checksum(self, path, all_vars, follow=False):
+ """Deprecated. Use _execute_remote_stat() instead.
+
+ Produces a remote checksum given a path,
+ Returns a number 0-4 for specific errors instead of checksum, also ensures it is different
+ 0 = unknown error
+ 1 = file does not exist, this might not be an error
+ 2 = permissions issue
+ 3 = its a directory, not a file
+ 4 = stat module failed, likely due to not finding python
+ 5 = appropriate json module not found
+ """
+ self._display.deprecated("The '_remote_checksum()' method is deprecated. "
+ "The plugin author should update the code to use '_execute_remote_stat()' instead", "2.16")
+ x = "0" # unknown error has occurred
+ try:
+ remote_stat = self._execute_remote_stat(path, all_vars, follow=follow)
+ if remote_stat['exists'] and remote_stat['isdir']:
+ x = "3" # its a directory not a file
+ else:
+ x = remote_stat['checksum'] # if 1, file is missing
+ except AnsibleError as e:
+ errormsg = to_text(e)
+ if errormsg.endswith(u'Permission denied'):
+ x = "2" # cannot read file
+ elif errormsg.endswith(u'MODULE FAILURE'):
+ x = "4" # python not found or module uncaught exception
+ elif 'json' in errormsg:
+ x = "5" # json module needed
+ finally:
+ return x # pylint: disable=lost-exception
+
def _remote_expand_user(self, path, sudoable=True, pathsep=None):
''' takes a remote path and performs tilde/$HOME expansion on the remote host '''
@@ -1215,18 +1232,6 @@ class ActionBase(ABC):
display.warning(w)
data = json.loads(filtered_output)
-
- if C.MODULE_STRICT_UTF8_RESPONSE and not data.pop('_ansible_trusted_utf8', None):
- try:
- _validate_utf8_json(data)
- except UnicodeEncodeError:
- # When removing this, also remove the loop and latin-1 from ansible.module_utils.common.text.converters.jsonify
- display.deprecated(
- f'Module "{self._task.resolved_action or self._task.action}" returned non UTF-8 data in '
- 'the JSON response. This will become an error in the future',
- version='2.18',
- )
-
data['_ansible_parsed'] = True
except ValueError:
# not valid json, lets try to capture error
@@ -1339,7 +1344,7 @@ class ActionBase(ABC):
display.debug(u"_low_level_execute_command() done: rc=%d, stdout=%s, stderr=%s" % (rc, out, err))
return dict(rc=rc, stdout=out, stdout_lines=out.splitlines(), stderr=err, stderr_lines=err.splitlines())
- def _get_diff_data(self, destination, source, task_vars, content, source_file=True):
+ def _get_diff_data(self, destination, source, task_vars, source_file=True):
# Note: Since we do not diff the source and destination before we transform from bytes into
# text the diff between source and destination may not be accurate. To fix this, we'd need
@@ -1397,10 +1402,7 @@ class ActionBase(ABC):
if b"\x00" in src_contents:
diff['src_binary'] = 1
else:
- if content:
- diff['after_header'] = destination
- else:
- diff['after_header'] = source
+ diff['after_header'] = source
diff['after'] = to_text(src_contents)
else:
display.debug(u"source of file passed in")