I'm having some issues with Ansible and the way it defaults to values. What I'm trying to accomplish is to bind a Docker container to on eth1, if it exists, otherwise use lo.

My initial approach was to use the defaulting undefined variables as follows:

shell: docker run -d -p {{ ansible_eth1.ipv4.address | default( }}:27017:27017 [...] dockerfile/mongodb

Unfortunately, Ansible threw the following error.

fatal: [server] => One or more undefined variables: 'ansible_eth1' is undefined

I also tried versions of this, such as:

shell: docker run -d -p {{ ansible_eth1.ipv4.address | ansible_lo.ipv4.address }}:27017:27017 [...] dockerfile/mongodb

That gave me another error:

failed: [server] => {"changed": true, "cmd": "docker run -d -p {# ansible_eth1.ipv4.address | ansible_lo.ipv4.address #}:27017:27017 [...]", "delta": "0:00:00.021053", "end": "2014-11-01     17:22:04.457375", "rc": 127, "start": "2014-11-01 17:22:04.436322"}
stderr: /bin/sh: 1: ansible_lo.ipv4.address: not found
2014/11/01 17:22:04 Invalid containerPort: {{

Next up, I tried using the when and 'is not defined' condition instead. It's less DRY, as I need two stanzas then.

- name: Start Mongo on loopback
  shell: docker run -d -p {{ ansible_lo.ipv4.address }}:27017:27017 [...] dockerfile/mongodb
  when: ansible_eth1.ipv4.address is not defined

That gave me the following error:

error while evaluating conditional: ansible_eth1.ipv4.address is not defined

Any Ansible experts out there that can point me in the right direction?

Oh, and I'm running ton Ansible 1.7.2.


The problem with this:

ansible_eth1.ipv4.address | default(

Is that if ansible_eth1 isn't a defined variable, then ansible_eth1.ipv4.address (or even ansible_eth1.ipv4) won't work. The solution is to apply the default filter to the variable that might not be there, which is ansible_eth1:

(ansible_eth1 | default(ansible_lo)).ipv4.address

Also note it's better practice to use command instead of shell unless you need some feature of the shell like pipe or redirection:

command: docker run -d -p {{ (ansible_eth1 | default(ansible_lo)).ipv4.address }}:27017:27017 [...] dockerfile/mongodb

Finally, note that Ansible has a docker module, so you may be able to use that directly here.

docker: "ports={{ (ansible_eth1 | default(ansible_lo)).ipv4.address }}:27017:27017 ..."
  • 1
    This may well answer the question, but we all love it when you explain why it does. – Falcon Momot Nov 2 '14 at 5:54
  • That did the trick and does make a lot of sense. Thanks! – vpetersson Nov 2 '14 at 21:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.