ui: Improve display for result diffs

Fixes: https://github.com/ansible-community/ara/issues/29

Change-Id: Id4442f0f9c4dcb5520f63970bb9fb17a03d5ec0d
This commit is contained in:
David Moreau Simard 2020-06-22 19:44:40 -04:00
parent 5086b29086
commit 13837784e3
No known key found for this signature in database
GPG Key ID: 7D4729EC4E64E8B7
2 changed files with 67 additions and 1 deletions

View File

@ -3,6 +3,7 @@
{% include "partials/playbook_card.html" with playbook=result.playbook %}
{% load pygments_highlights %}
{% load datetime_formatting %}
{% load diff_result %}
<div class="pf-c-card" style="margin: 1em 0;">
<div class="pf-c-card__header pf-c-title pf-m-md">
@ -35,7 +36,11 @@
<a href="#{{ field }}">{{ field }}</a>
</td>
<td role="cell" data-label="Value" class="pf-m-width-80">
{{ value | format_data | safe }}
{% if field == "diff" %}
{{ value | diff_result | format_data | safe }}
{% else %}
{{ value | format_data | safe }}
{% endif %}
</td>
</tr>
{% endfor %}

View File

@ -0,0 +1,61 @@
# Copyright (c) 2020 The ARA Records Ansible authors
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
import difflib
import json
from django import template
register = template.Library()
def render_diff(before="", after="", before_header="before", after_header="after"):
"""
Renders a diff provided by Ansible task results
"""
# fmt: off
# Some modules, such as file, might provide a diff in a dict format
if isinstance(before, dict) and isinstance(after, dict):
return difflib.unified_diff(
json.dumps(before, indent=4).splitlines(),
json.dumps(after, indent=4).splitlines(),
fromfile=before_header,
tofile=after_header
)
else:
return difflib.unified_diff(
before.splitlines(),
after.splitlines(),
fromfile=before_header,
tofile=after_header
)
# fmt: on
@register.filter(name="diff_result")
def diff_result(diff):
"""
Renders a diff (or a list of diffs) provided by Ansible task results
"""
diffs = []
# Modules are free to provide their own diff key which might not respect the convention set by modules such
# as "file", "ini_file", "lineinfile, "template" or "copy" causing a parsing failure.
# If that happens, give up and return value as it was provided so we don't raise an
# exception/internal server error.
try:
if isinstance(diff, list):
diffs = [render_diff(**result) for result in diff]
elif isinstance(diff, dict):
diffs = [render_diff(**diff)]
except (TypeError, AttributeError):
return diff
# The unified diff is a generator, we need to iterate through it to return
# the entire diff.
lines = []
for d in diffs:
for line in d:
lines.append(line)
return "\n".join(lines)