[oracle@oel01db ansible-project]$ ansible-playbook -i ./inventory/hosts ./playbooks/command_non_idempotent.yml
PLAY [Create directory using command module] *********************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************
ok: [oelggvm01]
TASK [Create a directory] ****************************************************************************************************************************************************
[WARNING]: Consider using the file module with state=directory rather than running 'mkdir'. If you need to use command because file is insufficient you can add 'warn:
false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
changed: [oelggvm01]
PLAY RECAP *******************************************************************************************************************************************************************
oelggvm01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[oracle@oel01db ansible-project]$
Lets re-run and see how it behaves.
[oracle@oel01db ansible-project]$ ansible-playbook -i ./inventory/hosts ./playbooks/command_non_idempotent.yml
PLAY [Create directory using command module] *********************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************
ok: [oelggvm01]
TASK [Create a directory] ****************************************************************************************************************************************************
[WARNING]: Consider using the file module with state=directory rather than running 'mkdir'. If you need to use command because file is insufficient you can add 'warn:
false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
fatal: [oelggvm01]: FAILED! => {"changed": true, "cmd": ["mkdir", "/tmp/log"], "delta": "0:00:00.053740", "end": "2025-12-22 12:14:29.821650", "msg": "non-zero return code", "rc": 1, "start": "2025-12-22 12:14:29.767910", "stderr": "mkdir: cannot create directory ‘/tmp/log’: File exists", "stderr_lines": ["mkdir: cannot create directory ‘/tmp/log’: File exists"], "stdout": "", "stdout_lines": []}
PLAY RECAP *******************************************************************************************************************************************************************
oelggvm01 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
[oracle@oel01db ansible-project]$
This time it failed as command module is not idempotent.
Let's make the command module idempotent by using the creates argument
[oracle@oel01db ansible-project]$ cat ./playbooks/command_non_idempotent.yml
---
- name: Create directory using command module
hosts: all
tasks:
- name: Create a directory
command: mkdir /tmp/log
args:
creates: /tmp/log
[oracle@oel01db ansible-project]$ ansible-playbook -i ./inventory/hosts ./playbooks/command_non_idempotent.yml
PLAY [Create directory using command module] *********************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************
ok: [oelggvm01]
TASK [Create a directory] ****************************************************************************************************************************************************
ok: [oelggvm01]
PLAY RECAP *******************************************************************************************************************************************************************
oelggvm01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[oracle@oel01db ansible-project]$
This time task is reported as OK.
Create a playbook using the file module which is idempotent in nature.
[oracle@oel01db ansible-project]$ cat ./playbooks/file_idempotent.yml
---
- name: Ensure directory exists (idempotent)
hosts: all
tasks:
- name: Ensure /tmp/mydir exists
ansible.builtin.file:
path: /tmp/mydir
state: directory
mode: '0755'
[oracle@oel01db ansible-project]$
[oracle@oel01db ansible-project]$ ansible-playbook -i ./inventory/hosts ./playbooks/file_idempotent.yml
PLAY [Ensure directory exists (idempotent)] **********************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************
ok: [oelggvm01]
TASK [Ensure /tmp/mydir exists] **********************************************************************************************************************************************
changed: [oelggvm01]
PLAY RECAP *******************************************************************************************************************************************************************
oelggvm01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[oracle@oel01db ansible-project]$
So in the first execution, its updated as changed=1
Let's re-run
[oracle@oel01db ansible-project]$ ansible-playbook -i ./inventory/hosts ./playbooks/file_idempotent.yml
PLAY [Ensure directory exists (idempotent)] **********************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************
ok: [oelggvm01]
TASK [Ensure /tmp/mydir exists] **********************************************************************************************************************************************
ok: [oelggvm01]
PLAY RECAP *******************************************************************************************************************************************************************
oelggvm01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[oracle@oel01db ansible-project]$
So system is already in the desired state, Ansible did nothing and report "ok" rather than "changed."
Now let's see a simple example for:
Use the stat module to check for a file's existence and then use the when directive on a subsequent task to run it only if the file is absent along with command module.
[oracle@oel01db ansible-project]$ cat ./playbooks/stats_idempotent.yml
---
- name: Use stat and when to control task execution
hosts: all
tasks:
- name: Check if /tmp/mydir2 exists
ansible.builtin.stat:
path: /tmp/mydir2
register: mydir_stat
- name: Create directory only if absent
ansible.builtin.command: mkdir /tmp/mydir2
when: not mydir_stat.stat.exists
[oracle@oel01db ansible-project]$
[oracle@oel01db ansible-project]$ ansible-playbook -i ./inventory/hosts ./playbooks/stats_idempotent.yml
PLAY [Use stat and when to control task execution] *************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************************
ok: [oelggvm01]
TASK [Check if /tmp/mydir2 exists] *****************************************************************************************************************************************************************
ok: [oelggvm01]
TASK [Create directory only if absent] *************************************************************************************************************************************************************
[WARNING]: Consider using the file module with state=directory rather than running 'mkdir'. If you need to use command because file is insufficient you can add 'warn: false' to this command task
or set 'command_warnings=False' in ansible.cfg to get rid of this message.
changed: [oelggvm01]
PLAY RECAP *****************************************************************************************************************************************************************************************
oelggvm01 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[oracle@oel01db ansible-project]$
How does it work ?
1️⃣ stat task
This collects metadata and stores it in mydir_stat.
Important fields:
2️⃣ when condition
Meaning:
“Run this task only if /tmp/mydir2 does NOT exist”
Execution behavior
| Situation | mkdir runs? | Result |
|---|
/tmp/mydir does not exist | ✅ Yes | Directory created |
/tmp/mydir exists | ❌ No | Task skipped |
/tmp/mydir is a file | ❌ No | Task skipped (⚠️ wrong state not fixed) |
⚠️ Important limitation (interview point)
This method:
If /tmp/mydir exists as a file, Ansible skips — but system is wrong.
No comments:
Post a Comment