I have an Ansible role to install/activate Trendmicro. In the task, there's one action did that activation by calling a bash command
- name: Execute /opt/imal/bin/dsupdstat.sh
ansible.builtin.command: /opt/imal/bin/dsupdstat.sh
changed_when: true
failed_when: false
But since this dsupdstat.sh always needs to create a lock file at beginning and delete it at the end. So the Ansible Molecule test keeps failing on it with a "idempotence" error... But that lock file creation/deletion is inevitable. So it looks that no hope to pass this Molecule test even if I marked that action with changed_when: true
.
Now I have to use this to ignore running that action in molecule test --
- name: Execute /opt/imal/bin/dsupdstat.sh
ansible.builtin.command: /opt/imal/bin/dsupdstat.sh
when: not lookup('env', 'MOLECULE_SCENARIO') is defined
changed_when: true
failed_when: false
Is there any better method to let molecule understand this action must do system changes and let it pass?
The problem is not your command creating/deleting a lock file but the presence of changed_when: true
in you task options. This will always report changed
and will never pass an idempotency check (whatever the command you play).
Note that command
/shell
reports changed
by default since ansible can't guess what you are doing exactly. Ideally, you should implement a test based on the registered command execution to tell whether something has changed or not (using e.g. the output, the return code ....). A proto example would look like:
- name: A command which changes or not
command: some_command
register: run_cmd
failed_when: run_cmd.rc not in [0,2] or run_cmd.stdout is search('error')
changed_when: run_cmd.stdout is search('Configuration updated')
Meanwhile if you are 100% sure your task can't pass idempotency in any way, there is a workaround to fool molecule test. You can read this PR thread for more information (I did not find any clear reference in the documentation with my quick search).
The solution takes advantage of molecule setting the ansible_skip_tags
variable before it runs ansible (you are welcome to debug it in your playbooks to see its full content).
- name: Execute /opt/imal/bin/dsupdstat.sh
ansible.builtin.command: /opt/imal/bin/dsupdstat.sh
changed_when: "'molecule-idempotence-notest' not in ansible_skip_tags"
failed_when: some_condition # Using false as in your question is really a bad idea...
This will report changed: false
when run in a molecule idempotency check and changed: true
otherwise. Note that you can also add the tag to your task to totally skip it during idempotence phase (but your command will not play)