In my Ansible playbook I have this:

- name: "A: Check to see if we need to run task B"
  [... implementation omitted, not relevant ...]
  register: task_a_result
  check_mode: no  # even run in check mode
  changed_when: no  # this only reads/checks stuff

- name: "B: Write x to file"
  shell: "echo {{ my_var|quote }} > /path/to/file"
  when: task_a_result.stdout_lines[0].startswith('ABCDEF')
  changed_when: yes  # when run, it always changes the state

I do not want to run B in check mode (hence, no check_mode: no), but I want to report it as changed if it would have been run in non-check mode. I want this behaviour, because I do not want surprises when running in non-check mode. However, despite having changed_when: yes and having set a conditional myself, Ansible keeps showing the task as skipped and thus unchanged to me:

skipping: [myhost] => changed=false 
  msg: skipped, running in check mode

(The above in check mode, and it reports 'changed' in regular non-check mode.)

I found this bug report that appears misinterpreted and closed inappropriately: 14950, but I cannot comment on that any longer.

Am I overlooking something basic? Other modules usually report a "would have changed" status perfectly fine in Ansible, but is this also possible for shell/command?

Using Ansible 2.7.12 and 2.8.2 yields the same results.

I am hoping to avoid nasty hacks in the command itself like:

- name: "B: Write x to file"
  shell: "echo {{ my_var|quote }} {{ '>' if task_a_result.stdout_lines[0].startswith('ABCDEF') else '' }} /path/to/file"
  when: task_a_result.stdout_lines[0].startswith('ABCDEF')
  changed_when: yes

And yes I know I can write to a file with the copy/template modules, but I can't seem to overwrite files with it, e.g. echo 1234 > /sys/module/zfs/parameters/zfs_arc_max, because copy/template would attempt to replace the file it seems and setting a kernel parameter wouldn't work like that. And no, this kernel module parameter is not exposed through sysctl on Linux.

  • Why does it matter? – Michael Hampton Jul 24 '19 at 0:41
  • @MichaelHampton Because in a check mode, I'd like to know if something would change if I run it in non-check mode. IOW, without Ansible, if you would run cmd --dry-run which outputs "nothing changed" and you would then do cmd, and it would change something, this would be a bug. – gertvdijk Jul 24 '19 at 12:12
  • But you've set the play to always report changed even if nothing changed (which is redundant). It certainly looks like the actual result is irrelevant, doubly so in check mode. What is missing here? – Michael Hampton Jul 24 '19 at 15:07
  • @MichaelHampton when: my_conditional_var determines whether the task is going to run, and if it runs, it will change. I want to see that in check mode. Perhaps I could improve the wording in the Q? It's basically check mode reports "I'm not going to change anything" and in non-check mode it will change stuff. That's what I want to fix. – gertvdijk Jul 25 '19 at 0:16
  • In the example you gave, it doesn't actually matter! You can just ignore it. Are you doing something else? – Michael Hampton Jul 25 '19 at 6:04

I know this is kind of old, but I'm looking for the solution to this problem. I'm also tired of surprises with command module as OP.

What if we change the 'command' part so that it executes a different command in check mode. And we run the task always, even in check mode.

Note: Before you complain, I know this is a bad example. I know there is a 'creates' option in 'command' module. This is just to give an example.

This is my solution so far:

- name: Get some info
  stat: {path: /tmp/somefile}
  register: file_info

- name: Run the command conditionally
    "{{ 'true' if (file_info['stat']['exists'] or ansible_check_mode)
    else 'touch /tmp/somefile' }}"
  changed_when: not file_info['stat']['exists']
  check_mode: false

It works, but is bloated.

Please tell me if there are better solutions.

  • Yes, thanks, meanwhile I always add a --dry-run argument conditionally if the command executed supports that. If the command supports it, it's even better, because it could test for failures and reduce the level of surprise when run in non-check mode. However, I'm still disappointed I haven't found a way to report-changed-but-not-run as task in Ansible check mode. – gertvdijk Apr 27 at 19:14

I have a similar need. I would like to see if the command would be run so that I get no surprises when not run in check mode.

As a workaround I added a debug task reporting that there would be a change and used the when condition from the command task to set changed_when on the debug task, i.e.

- name: "Report pending change"
    msg: "Change pending"
  changed_when: task_a_result.stdout_lines[0].startswith('ABCDEF')
  when: ansible_check_mode|bool

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.