Open
Description
Summary
The "creates" constraint in shell
behaves differently depending on where the listed files are located.
When a single file is given, it appears to behave as expected, i.e., if the file already exists then the task is not performed.
When multiple files are given, and they are in the task path, behavior is as above.
When multiple files are given, and they are not in the task path, the task is run even though the files already exist.
See playbook in section "Steps to reproduce". Run that playbook twice to reproduce.
Issue Type
Bug Report
Component Name
shell
Ansible Version
$ ansible --version
ansible [core 2.16.3]
config file = None
configured module search path = ['/home/ubuntu/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /home/ubuntu/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.12.3 (main, Nov 6 2024, 18:32:19) [GCC 13.2.0] (/usr/bin/python3)
jinja version = 3.1.2
libyaml = True
Configuration
# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
CONFIG_FILE() = None
OS / Environment
Ubuntu 24.04
Steps to Reproduce
- hosts:
- '127.0.0.1'
tasks:
- name: success - Create single file in ~
args:
creates: /home/ubuntu/a
ansible.builtin.shell: |
touch /home/ubuntu/a
- name: success - Create multiple files in current directory
args:
creates:
- a
- b
ansible.builtin.shell: |
touch a b
- name: failure - Create multiple files in ~
args:
creates:
- /home/ubuntu/a
- /home/ubuntu/b
ansible.builtin.shell: |
touch /home/ubuntu/a /home/ubuntu/b
Expected Results
See the section "Summary".
Actual Results
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'
ansible-playbook [core 2.16.3]
config file = None
configured module search path = ['/home/ubuntu/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /home/ubuntu/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible-playbook
python version = 3.12.3 (main, Nov 6 2024, 18:32:19) [GCC 13.2.0] (/usr/bin/python3)
jinja version = 3.1.2
libyaml = True
No config file found; using defaults
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
yaml declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
ini declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
toml declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.
PLAYBOOK: main.yml *************************************************************
1 plays in ansible/main.yml
PLAY [127.0.0.1] ***************************************************************
TASK [Gathering Facts] *********************************************************
task path: /home/ubuntu/.dotfiles/ansible/main.yml:1
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: ubuntu
<127.0.0.1> EXEC /bin/sh -c 'echo ~ubuntu && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ubuntu/.ansible/tmp `"&& mkdir "` echo /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.0545905-2753-218625252217575 `" && echo ansible-tmp-1735297572.0545905-2753-218625252217575="` echo /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.0545905-2753-218625252217575 `" ) && sleep 0'
Using module file /usr/lib/python3/dist-packages/ansible/modules/setup.py
<127.0.0.1> PUT /home/ubuntu/.ansible/tmp/ansible-local-27508expt46y/tmpn0vwkjic TO /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.0545905-2753-218625252217575/AnsiballZ_setup.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.0545905-2753-218625252217575/ /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.0545905-2753-218625252217575/AnsiballZ_setup.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.0545905-2753-218625252217575/AnsiballZ_setup.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.0545905-2753-218625252217575/ > /dev/null 2>&1 && sleep 0'
ok: [127.0.0.1]
TASK [success - Create single file in ~] ***************************************
task path: /home/ubuntu/.dotfiles/ansible/main.yml:5
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: ubuntu
<127.0.0.1> EXEC /bin/sh -c 'echo ~ubuntu && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ubuntu/.ansible/tmp `"&& mkdir "` echo /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.6977189-2832-40327463316247 `" && echo ansible-tmp-1735297572.6977189-2832-40327463316247="` echo /home/ubuntu/.ansible/tmp
834E
/ansible-tmp-1735297572.6977189-2832-40327463316247 `" ) && sleep 0'
Using module file /usr/lib/python3/dist-packages/ansible/modules/command.py
<127.0.0.1> PUT /home/ubuntu/.ansible/tmp/ansible-local-27508expt46y/tmp3s5a50wb TO /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.6977189-2832-40327463316247/AnsiballZ_command.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.6977189-2832-40327463316247/ /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.6977189-2832-40327463316247/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.6977189-2832-40327463316247/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.6977189-2832-40327463316247/ > /dev/null 2>&1 && sleep 0'
ok: [127.0.0.1] => {
"changed": false,
"cmd": "touch /home/ubuntu/a\n",
"delta": null,
"end": null,
"invocation": {
"module_args": {
"_raw_params": "touch /home/ubuntu/a\n",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": "/home/ubuntu/a",
"executable": null,
"expand_argument_vars": true,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true
}
},
"msg": "Did not run command since '/home/ubuntu/a' exists",
"rc": 0,
"start": null,
"stderr": "",
"stderr_lines": [],
"stdout": "skipped, since /home/ubuntu/a exists",
"stdout_lines": [
"skipped, since /home/ubuntu/a exists"
]
}
TASK [success - Create multiple files in current directory] ********************
task path: /home/ubuntu/.dotfiles/ansible/main.yml:11
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: ubuntu
<127.0.0.1> EXEC /bin/sh -c 'echo ~ubuntu && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ubuntu/.ansible/tmp `"&& mkdir "` echo /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.8988683-2857-167062530684105 `" && echo ansible-tmp-1735297572.8988683-2857-167062530684105="` echo /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.8988683-2857-167062530684105 `" ) && sleep 0'
Using module file /usr/lib/python3/dist-packages/ansible/modules/command.py
<127.0.0.1> PUT /home/ubuntu/.ansible/tmp/ansible-local-27508expt46y/tmp65ji5wt4 TO /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.8988683-2857-167062530684105/AnsiballZ_command.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.8988683-2857-167062530684105/ /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.8988683-2857-167062530684105/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.8988683-2857-167062530684105/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /home/ubuntu/.ansible/tmp/ansible-tmp-1735297572.8988683-2857-167062530684105/ > /dev/null 2>&1 && sleep 0'
ok: [127.0.0.1] => {
"changed": false,
"cmd": "touch a b\n",
"delta": null,
"end": null,
"invocation": {
"module_args": {
"_raw_params": "touch a b\n",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": "['a', 'b']",
"executable": null,
"expand_argument_vars": true,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true
}
},
"msg": "Did not run command since '['a', 'b']' exists",
"rc": 0,
"start": null,
"stderr": "",
"stderr_lines": [],
"stdout": "skipped, since ['a', 'b'] exists",
"stdout_lines": [
"skipped, since ['a', 'b'] exists"
]
}
TASK [failure - Create multiple files in ~] ************************************
task path: /home/ubuntu/.dotfiles/ansible/main.yml:19
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: ubuntu
<127.0.0.1> EXEC /bin/sh -c 'echo ~ubuntu && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ubuntu/.ansible/tmp `"&& mkdir "` echo /home/ubuntu/.ansible/tmp/ansible-tmp-1735297573.0390477-2882-220125337962637 `" && echo ansible-tmp-1735297573.0390477-2882-220125337962637="` echo /home/ubuntu/.ansible/tmp/ansible-tmp-1735297573.0390477-2882-220125337962637 `" ) && sleep 0'
Using module file /usr/lib/python3/dist-packages/ansible/modules/command.py
<127.0.0.1> PUT /home/ubuntu/.ansible/tmp/ansible-local-27508expt46y/tmpa3nihfbn TO /home/ubuntu/.ansible/tmp/ansible-tmp-1735297573.0390477-2882-220125337962637/AnsiballZ_command.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /home/ubuntu/.ansible/tmp/ansible-tmp-1735297573.0390477-2882-220125337962637/ /home/ubuntu/.ansible/tmp/ansible-tmp-1735297573.0390477-2882-220125337962637/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /home/ubuntu/.ansible/tmp/ansible-tmp-1735297573.0390477-2882-220125337962637/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /home/ubuntu/.ansible/tmp/ansible-tmp-1735297573.0390477-2882-220125337962637/ > /dev/null 2>&1 && sleep 0'
changed: [127.0.0.1] => {
"changed": true,
"cmd": "touch /home/ubuntu/a /home/ubuntu/b\n",
"delta": "0:00:00.003488",
"end": "2024-12-27 11:06:13.155383",
"invocation": {
"module_args": {
"_raw_params": "touch /home/ubuntu/a /home/ubuntu/b\n",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": "['/home/ubuntu/a', '/home/ubuntu/b']",
"executable": null,
"expand_argument_vars": true,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true
}
},
"msg": "",
"rc": 0,
"start": "2024-12-27 11:06:13.151895",
"stderr": "",
"stderr_lines": [],
"stdout": "",
"stdout_lines": []
}
PLAY RECAP *********************************************************************
127.0.0.1 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Code of Conduct
- I agree to follow the Ansible Code of Conduct