Reputation: 15394
I have put together a simple ansible script to install Rails 4.2.4
if a version of rails is not already installed.
---
- name: detect rails version
command: which rails
register: rails_version
ignore_errors: yes
- name: install rails
command: gem install rails -v 4.2.4
when: rails_version.rc != 0
But when running this task it seems as if Rails will install even if it is already installed. This is the output:
TASK: [rails | detect rails version] ******************************************
failed: [192.168.33.100] => {"changed": true, "cmd": ["which", "rails"], "delta": "0:00:00.002084", "end": "2015-10-28 11:35:14.421897", "rc": 1, "start": "2015-10-28 11:35:14.419813", "warnings": []}
...ignoring
TASK: [rails | install rails] *************************************************
changed: [192.168.33.100]
PLAY RECAP ********************************************************************
192.168.33.100 : ok=3 changed=2 unreachable=0 failed=0
So does this mean the conditional has been ignored as I was expecting output more like:
TASK: [rails | install rails] **********************************
skipped: [192.168.33.100]
Upvotes: 1
Views: 808
Reputation: 5420
The output shows that the conditional is working correctly: the first task failed, with rc == 1
. This means the second task should run, and it does.
If you do already have rails installed, you need to debug why which rails
is failing. If running 'which rails' manually succeeds, try using shell: which rails
.
Upvotes: 2
Reputation: 56997
Your which rails
command is returning a non 0 return code as you can see in your output:
TASK: [rails | detect rails version] ******************************************
failed: [192.168.33.100] => {"changed": true, "cmd": ["which", "rails"], "delta": "0:00:00.002084", "end": "2015-10-28 11:35:14.421897", "rc": 1, "start": "2015-10-28 11:35:14.419813", "warnings": []}
...ignoring
So obviously Ansible is going to run your second task as your conditional explicitly says to run when the return code is not 0.
For this use case I would instead consider using the gem module to install Rails (and other gems). This will automatically handle idempotency and in general with Ansible your best bet is always to use higher level modules rather than shelling out wherever possible.
Your task would then look something like this:
---
- name: install rails
gem:
name: rails
version: 4.2.4
As an extra bonus, even if your command based tasks had worked as expected if you had a non 4.2.4 version of Rails installed then your install task would have left it as is rather than up/downgrading the version to match your specified one.
Upvotes: 2