From 281f957ece95fae16bb7d12b863e6e9b89523b14 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sat, 8 Apr 2023 08:01:06 -0400 Subject: [PATCH] json[l] callback: add parameter to set JSON prettyprint indent level Add ANSIBLE_JSON_INDENT parameter to both the json and jsonl callback plugins. The default values are different between the two modules to maintain their existing behavior: * json: indent==4, causing a prettyprint output * jsonl: indent==0, causing a 1-line output One specific use-case that is enabled by this feature: if a user chooses to use the jsonl plugin so that they still get output at the end of each task (vs. only at the end of the play), they may also want human-readable output so that they can monitor the status of their play. For example, setting the jsonl indent level to 4 gives a) output at the end of each task, and b) making that output be both machine readable and human readable. Signed-off-by: Jeff Squyres --- .../441-json-add-indent-parameter.yaml | 2 ++ plugins/callback/json.py | 18 +++++++++++++++++- plugins/callback/jsonl.py | 18 +++++++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/441-json-add-indent-parameter.yaml diff --git a/changelogs/fragments/441-json-add-indent-parameter.yaml b/changelogs/fragments/441-json-add-indent-parameter.yaml new file mode 100644 index 0000000..8a0359b --- /dev/null +++ b/changelogs/fragments/441-json-add-indent-parameter.yaml @@ -0,0 +1,2 @@ +minor_changes: + - json and jsonl - Add the ``ANSIBLE_JSON_INDENT`` parameter diff --git a/plugins/callback/json.py b/plugins/callback/json.py index f0c56b4..f57a7d6 100644 --- a/plugins/callback/json.py +++ b/plugins/callback/json.py @@ -25,6 +25,16 @@ DOCUMENTATION = ''' - key: show_custom_stats section: defaults type: bool + json_indent: + name: Use indenting for the JSON output + description: 'If specified, use this many spaces for indenting in the JSON output. If <= 0, write to a single line.' + default: 4 + env: + - name: ANSIBLE_JSON_INDENT + ini: + - key: json_indent + section: defaults + type: integer notes: - When using a strategy such as free, host_pinned, or a custom strategy, host results will be added to new task results in ``.plays[].tasks[]``. As such, there will exist duplicate @@ -61,6 +71,12 @@ class CallbackModule(CallbackBase): self._task_map = {} self._is_lockstep = False + self.set_options() + + self._json_indent = self.get_option('json_indent') + if self._json_indent <= 0: + self._json_indent = None + def _new_play(self, play): self._is_lockstep = play.strategy in LOCKSTEP_CALLBACKS return { @@ -143,7 +159,7 @@ class CallbackModule(CallbackBase): 'global_custom_stats': global_custom_stats, } - self._display.display(json.dumps(output, cls=AnsibleJSONEncoder, indent=4, sort_keys=True)) + self._display.display(json.dumps(output, cls=AnsibleJSONEncoder, indent=self._json_indent, sort_keys=True)) def _record_task_result(self, on_info, result, **kwargs): """This function is used as a partial to add failed/skipped info in a single method""" diff --git a/plugins/callback/jsonl.py b/plugins/callback/jsonl.py index 2403dba..febeca1 100644 --- a/plugins/callback/jsonl.py +++ b/plugins/callback/jsonl.py @@ -26,6 +26,16 @@ DOCUMENTATION = ''' - key: show_custom_stats section: defaults type: bool + json_indent: + name: Use indenting for the JSON output + description: 'If specified, use this many spaces for indenting in the JSON output. If not specified or <= 0, write to a single line.' + default: 0 + env: + - name: ANSIBLE_JSON_INDENT + ini: + - key: json_indent + section: defaults + type: integer notes: - When using a strategy such as free, host_pinned, or a custom strategy, host results will be added to new task results in ``.plays[].tasks[]``. As such, there will exist duplicate @@ -63,6 +73,12 @@ class CallbackModule(CallbackBase): self._task_map = {} self._is_lockstep = False + self.set_options() + + self._json_indent = self.get_option('json_indent') + if self._json_indent <= 0: + self._json_indent = None + def _new_play(self, play): self._is_lockstep = play.strategy in LOCKSTEP_CALLBACKS return { @@ -156,7 +172,7 @@ class CallbackModule(CallbackBase): def _write_event(self, event_name, output): output['_event'] = event_name output['_timestamp'] = current_time() - self._display.display(json.dumps(output, cls=AnsibleJSONEncoder, separators=',:', sort_keys=True)) + self._display.display(json.dumps(output, cls=AnsibleJSONEncoder, indent=self._json_indent, separators=',:', sort_keys=True)) def _record_task_result(self, event_name, on_info, result, **kwargs): """This function is used as a partial to add failed/skipped info in a single method"""