Richlewis
Richlewis

Reputation: 15394

Ansible conditional

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

Answers (2)

jazmit
jazmit

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

ydaetskcoR
ydaetskcoR

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

Related Questions