New in 1.1 -- Diff mode for templates! Works with and without --check, but prefers --limit

So --check is a recently added "pseudo dry run" feature which I just
recently talked about.

So far, modules like file, template, and copy respond to --check and
will give you whether things would change or not, and the other
modules just get skipped over with --check.

Whether or not you are using --check, I just added a --diff flag
tonight, so far only to /usr/bin/ansible-playbook.

When this is run, for any template files, it will present a basic
unified diff of the changes made to those templates. To avoid running
against binary files, it is not implemented for file types.

I also suspect the output of diff mode is NOT optimal if running
against multiple machines at the same time (it might interlace), so it
is probably useful to use it with --limit.

Example, to put it all in perspective

ansible-playbook everything.yml --check # just see what might change
on all boxes
ansible-playbook everything.yml --check --limit foo.example.com # see
what might change on just one box
ansible-playbook everything.yml --check --diff # just see what might
change and show diffs on all boxes
ansible-playbook everything.yml --check --diff --limit foo.example.com
# be sane, just show diffs for that one box

There are TODO items here which I am hoping folks may want to help
with, namely, teaching other modules to respond to the "check"
attribute, just like file does now.

Minimally I think this should be done for service, yum, and apt, and
this would be pretty well decently complete.

Given lots of folks may have command tasks and when statements they
also want to simulate, perhaps we should also teach the command module
that when run in 'check' mode that it should return changed with a 0
(success) error code.

We can worry about the other modules having support for --check later,
I'm not super concerned about those. I think most people want to know
when files get modified out of band.

Those developers interested should see this commit

https://github.com/ansible/ansible/commit/a9162a86f2e2b678eaef04501339c037bfc18319

Ideas for improvements in output are welcome. I didn't add this to
/usr/bin/ansible because that doesn't really do templates.

One weird thing I have already ran into, and makes this hard, is dealing with register variables. Not sure the best way to handle there.

--check mode and register variables you mean?

Definitely, I think it's just going to be a limitation (a limitation
as a result of capability does not GREATLY concern me, it's just going
to be a feature with caveats...other tools can't even do this so it's
not an issue to me).

I would welcome creative approaches to making this more useful in
those situations, but it's also one of the reasons I put it off
originally... the whole 'it's not going to be very accurate because
it's a simulation' kind of thing.

I checked changes to the RabbitMQ modules to support --check mode and it works as expected. It was pretty trivial to add the support for it since modules have to be structured for idempotentance.

Here’s an idea related to this. Instead of just showing a diff, how about letting Ansible (in dry run mode, or something similar) parse all templates and generate local copies?

A number of my configuration files are Jinja 2 templates right now. If someone asked me to show them an example config file for something I’m deploying, I’d have to either fetch one from a server where it’s been deployed, or make a copy of the template and “manually” render it (i.e. edit out all the J2 tags and put in dummy values).

I think it might be useful to have Ansible do the template file generation offline, locally. I realize templates that use dynamically fetched data wouldn’t work, but I find all my templates use data from the hosts file, and my vars.

this is its very easy with a local action.

I also have a hack that does this but changes how ansible works with
stdin/stdout

I actually setup a playbook that does this:

ansible-playbook gen_template.yml -e "target=webserver1"

--- gen_template.yml

- hosts: $target
  vars_prompt:
    - name: template
      prompt: "Enter template file name"
      private: false
    - name: templateloc
      prompt: "Enter template file location"
      private: false
  tasks:
      - name: gen template
        local_action: template src=$templateloc/$template dest=/tmp/$template

Sounds like a great thing to use a callback plugin for. It would
show all the other diffs on screen still, but you could also save
them.

This is quite clever, thanks.