3

I run my ansible playbooks through a cron job every night as I add to them every now and then.

I want my output of each to only say changed=(num) if there is actually a change, but a few specific modules say changed when they were not changed at all.

EX:

- name: (name)
  file:
    state: touch
    path: (path)
    group: (group)
    mode: (perms)

The path before the task is run contains the same group and permissions as the requested permissions and group. So they don't change when the task is run, but the result ansible says it has "changed".

I looked this issue up and found https://github.com/ansible/ansible/issues/21124 but I'm running ansible 2.2.1.0. So it's my understanding from this that they are indicating that the file module is idempotent.

Are there any suggestions to make it idempotent?

Dorilds
  • 418
  • 1
  • 7
  • 15

4 Answers4

3

In order to idempotently create a file using the file module in ansible you have to separate checking if the file exists, creating it, and setting any permissions (as you want those to be set correctly whether the file already existed or not).

This can be accomplished using 3 tasks as follows:

- name: Check if file exists
  stat:
    path: /tmp/file
  register: tmp_file

- name: Create file
  file:
    path: /tmp/file
    state: touch
  when: tmp_file.stat.exists == false

- name: Set perms of file
  file:
    path: /tmp/file
    state: file
    owner: user
    group: group
    mode: 0600
vqqnda1
  • 339
  • 3
  • 3
2

The problem is that state: touch by default changes the access and modification time of the target path. So even if nothing else changes, touch result in a change.

Since Ansible 2.7 you can use the variables access_time and modification_time to make file with touch idempotent.

- name: Touch file
  file:
    path: /etc/file.conf
    state: touch
    access_time: preserve
    modification_time: preserve

(original solution by Nklya)

fap
  • 663
  • 1
  • 5
  • 14
1

they don't change when the task is run, but the result Ansible says it has "changed".

It says it changed, because when you run a touch command against a file, the timestamps change.

Don't use touch, use another appropriate state (file, directory, link).


Otherwise you can set changed_when: false, but I don't think it makes sense considering you want check the output.

techraf
  • 64,883
  • 27
  • 193
  • 198
  • I figured it out I wanted to use the touch state to make sure it existed, but then I just run a stat module before now to check if it exists – Dorilds Jul 12 '18 at 15:10
1

A simple idempotent option of how to touch a file would be

    - ansible.builtin.command: touch file
      args:
        creates: file
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63