mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-23 05:10:22 -07:00
Improve parsing of 'systemctl show' output
This commit is contained in:
parent
fc0bf87c20
commit
2d9d1762ba
2 changed files with 86 additions and 20 deletions
|
@ -259,6 +259,40 @@ def is_running_service(service_status):
|
|||
def request_was_ignored(out):
|
||||
return '=' not in out and 'ignoring request' in out
|
||||
|
||||
def parse_systemctl_show(lines):
|
||||
# The output of 'systemctl show' can contain values that span multiple lines. At first glance it
|
||||
# appears that such values are always surrounded by {}, so the previous version of this code
|
||||
# assumed that any value starting with { was a multi-line value; it would then consume lines
|
||||
# until it saw a line that ended with }. However, it is possible to have a single-line value
|
||||
# that starts with { but does not end with } (this could happen in the value for Description=,
|
||||
# for example), and the previous version of this code would then consume all remaining lines as
|
||||
# part of that value. Cryptically, this would lead to Ansible reporting that the service file
|
||||
# couldn't be found.
|
||||
#
|
||||
# To avoid this issue, the following code only accepts multi-line values for keys whose names
|
||||
# start with Exec (e.g., ExecStart=), since these are the only keys whose values are known to
|
||||
# span multiple lines.
|
||||
parsed = {}
|
||||
multival = []
|
||||
k = None
|
||||
for line in lines:
|
||||
if k is None:
|
||||
if '=' in line:
|
||||
k, v = line.split('=', 1)
|
||||
if k.startswith('Exec') and v.lstrip().startswith('{'):
|
||||
if not v.rstrip().endswith('}'):
|
||||
multival.append(v)
|
||||
continue
|
||||
parsed[k] = v.strip()
|
||||
k = None
|
||||
else:
|
||||
multival.append(line)
|
||||
if line.rstrip().endswith('}'):
|
||||
parsed[k] = '\n'.join(multival).strip()
|
||||
multival = []
|
||||
k = None
|
||||
return parsed
|
||||
|
||||
|
||||
# ===========================================
|
||||
# Main control flow
|
||||
|
@ -320,27 +354,8 @@ def main():
|
|||
|
||||
elif rc == 0:
|
||||
# load return of systemctl show into dictionary for easy access and return
|
||||
multival = []
|
||||
if out:
|
||||
k = None
|
||||
for line in to_native(out).split('\n'): # systemd can have multiline values delimited with {}
|
||||
if line.strip():
|
||||
if k is None:
|
||||
if '=' in line:
|
||||
k,v = line.split('=', 1)
|
||||
if v.lstrip().startswith('{'):
|
||||
if not v.rstrip().endswith('}'):
|
||||
multival.append(line)
|
||||
continue
|
||||
result['status'][k] = v.strip()
|
||||
k = None
|
||||
else:
|
||||
if line.rstrip().endswith('}'):
|
||||
result['status'][k] = '\n'.join(multival).strip()
|
||||
multival = []
|
||||
k = None
|
||||
else:
|
||||
multival.append(line)
|
||||
result['status'] = parse_systemctl_show(to_native(out).split('\n'))
|
||||
|
||||
is_systemd = 'LoadState' in result['status'] and result['status']['LoadState'] != 'not-found'
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue