prevent fact gathering from breaking on bad caps (#76691)

* prevent fact gathering from breaking on bad caps

 fxies #75832
pull/76765/head
Brian Coca 3 years ago committed by GitHub
parent 2246ed9678
commit 4676c08f18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,4 @@
minor_changes:
- AnsibleModule.run_command() now has a toggle to allow caller to decide to handle exceptions from executing the command itself
bugfixes:
- gather_facts/setup will not fail anymore if capsh is present but not executable

@ -1837,7 +1837,7 @@ class AnsibleModule(object):
def run_command(self, args, check_rc=False, close_fds=True, executable=None, data=None, binary_data=False, path_prefix=None, cwd=None,
use_unsafe_shell=False, prompt_regex=None, environ_update=None, umask=None, encoding='utf-8', errors='surrogate_or_strict',
expand_user_and_vars=True, pass_fds=None, before_communicate_callback=None, ignore_invalid_cwd=True):
expand_user_and_vars=True, pass_fds=None, before_communicate_callback=None, ignore_invalid_cwd=True, handle_exceptions=True):
'''
Execute a command, returns rc, stdout, and stderr.
@ -1891,6 +1891,9 @@ class AnsibleModule(object):
:kw ignore_invalid_cwd: This flag indicates whether an invalid ``cwd``
(non-existent or not a directory) should be ignored or should raise
an exception.
:kw handle_exceptions: This flag indicates whether an exception will
be handled inline and issue a failed_json or if the caller should
handle it.
:returns: A 3-tuple of return code (integer), stdout (native string),
and stderr (native string). On python2, stdout and stderr are both
byte strings. On python3, stdout and stderr are text strings converted
@ -2080,10 +2083,16 @@ class AnsibleModule(object):
rc = cmd.returncode
except (OSError, IOError) as e:
self.log("Error Executing CMD:%s Exception:%s" % (self._clean_args(args), to_native(e)))
self.fail_json(rc=e.errno, stdout=b'', stderr=b'', msg=to_native(e), cmd=self._clean_args(args))
if handle_exceptions:
self.fail_json(rc=e.errno, stdout=b'', stderr=b'', msg=to_native(e), cmd=self._clean_args(args))
else:
raise e
except Exception as e:
self.log("Error Executing CMD:%s Exception:%s" % (self._clean_args(args), to_native(traceback.format_exc())))
self.fail_json(rc=257, stdout=b'', stderr=b'', msg=to_native(e), exception=traceback.format_exc(), cmd=self._clean_args(args))
if handle_exceptions:
self.fail_json(rc=257, stdout=b'', stderr=b'', msg=to_native(e), exception=traceback.format_exc(), cmd=self._clean_args(args))
else:
raise e
if rc != 0 and check_rc:
msg = heuristic_log_sanitize(stderr.rstrip(), self.no_log_values)

@ -19,6 +19,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.module_utils._text import to_text
from ansible.module_utils.facts.collector import BaseFactCollector
@ -28,28 +29,33 @@ class SystemCapabilitiesFactCollector(BaseFactCollector):
'system_capabilities_enforced'])
def collect(self, module=None, collected_facts=None):
facts_dict = {}
if not module:
return facts_dict
capsh_path = module.get_bin_path('capsh')
# NOTE: early exit 'if not crash_path' and unindent rest of method -akl
if capsh_path:
# NOTE: -> get_caps_data()/parse_caps_data() for easier mocking -akl
rc, out, err = module.run_command([capsh_path, "--print"], errors='surrogate_then_replace')
enforced_caps = []
enforced = 'NA'
for line in out.splitlines():
if len(line) < 1:
continue
if line.startswith('Current:'):
if line.split(':')[1].strip() == '=ep':
enforced = 'False'
else:
enforced = 'True'
enforced_caps = [i.strip() for i in line.split('=')[1].split(',')]
facts_dict['system_capabilities_enforced'] = enforced
facts_dict['system_capabilities'] = enforced_caps
rc = -1
facts_dict = {'system_capabilities_enforced': 'N/A',
'system_capabilities': 'N/A'}
if module:
capsh_path = module.get_bin_path('capsh')
if capsh_path:
# NOTE: -> get_caps_data()/parse_caps_data() for easier mocking -akl
try:
rc, out, err = module.run_command([capsh_path, "--print"], errors='surrogate_then_replace', handle_exceptions=False)
except (IOError, OSError) as e:
module.warn('Could not query system capabilities: %s' % str(e))
if rc == 0:
enforced_caps = []
enforced = 'NA'
for line in out.splitlines():
if len(line) < 1:
continue
if line.startswith('Current:'):
if line.split(':')[1].strip() == '=ep':
enforced = 'False'
else:
enforced = 'True'
enforced_caps = [i.strip() for i in line.split('=')[1].split(',')]
facts_dict['system_capabilities_enforced'] = enforced
facts_dict['system_capabilities'] = enforced_caps
return facts_dict

Loading…
Cancel
Save