I was inspired to dig into this topic by this ServerFault question.
So you have some Ansible task that supports
diff output (e.g.
But imagine that you copy files that are not human readable by default (like pem-certificates, for example).
In this case Ansible will print some base64 "garbage" as task's diff:
--- before: /tmp/cert.pem +++ after: /path/to/cert.pem @@ -1,13 +1,13 @@ -----BEGIN CERTIFICATE----- -MIIB7DCCAVWgAwIBAgIJAMUAMA8xDTALBgNV -BAMMBHRlc3QwHhcNMTcxMDQ1WjAPMQ0wCwYD -VQQDDAR0ZXN0MIGfMA0GCSCmJCHr6m0CCEjE -mtDD1EHUAo8y0jN9lYdF251k07WH1MKVh2tQ -nxywqt1ktrqI/CPJqItKAerOh897GkOw06Rk -/ufGeYFxr/Ff+fVaL4qq0g== +MIIB7DCCAVWgAwIBAgIJCwUAMA8xDTALBgNV +BAMMBHRlc3QwHhcNMTcxODU0WjAPMQ0wCwYD +VQQDDAR0ZXN0MIGfMA0GgQChH7tIRNrbLEz6 +kPwL+YijDVXgHUjp2rc9j0pbs04s/oJ9L3ah +bwFcpP3FmyabwiWgVOR8KyaITlyBuExhH83D +zPf/JYnGvJw/q94q6/6cEg== -----END CERTIFICATE-----
If we make things simple, every module that support
after strings, that are processed with Python's difflib.unified_diff in default stdout callback.
So to tackle our problem we either need to:
afterstrings on their way from module
afterstrings while they are processed by callback
If you need to modify a single module, you can write an action plugin on top of the module, or even subclass the original action plugin (like
copy) that will alter those strings.
But if we want a more general approach and be able to override diff processing for any task/module, we need to modify callback function.
Here is prediff.py callback plugin that subclasses Ansible's default stdout callback.
The only method that is overridden is
v2_on_file_diff. I check for
prediff_cmd in task variables and if it's there, execute this command to modify
This way if there is no
prediff_cmd variable defined everything work as usual, but if
prediff_cmd is there
after are preprocessed with this command before executing
To allow easy use of
prediff_cmd I dump strings into temporary file with its path available as
Example playbook may look like:
- hosts: localhost gather_facts: no tasks: - copy: src: cert.pem dest: /tmp/cert.pem vars: prediff_cmd: openssl x509 -in %s -noout -text | head -n 10
Next we set our
prediff callback as stdout plugin:
ANSIBLE_STDOUT_CALLBACK=prediff ansible-playbook --check --diff test.yml
And get nice human readable diff:
--- before: /tmp/cert.pem +++ after: /path/to/cert.pem @@ -2,9 +2,9 @@ Data: Version: 3 (0x2) Serial Number: - c6:40:43:a5:99:0d:63:ac + db:e2:e2:8e:a2:b2:49:1f Signature Algorithm: sha256WithRSAEncryption Issuer: CN=test Validity - Not Before: Oct 21 09:18:45 2017 GMT - Not After : Oct 21 09:18:45 2018 GMT + Not Before: Oct 21 09:18:54 2017 GMT + Not After : Oct 21 09:18:54 2018 GMT