# Define var if not defined

**URL:** <https://forum.ansible.com/t/define-var-if-not-defined/11538>\
**Category:** Ansible Project\
**Created:** [May 11, 2012, 11:38pm UTC](https://forum.ansible.com/t/define-var-if-not-defined/11538 "2012-05-11T23:38:29Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Matthew\_Williams](https://avatars.discourse-cdn.com/v4/letter/m/a3d4f5/32.png) [@Matthew\_Williams](https://forum.ansible.com/u/Matthew_Williams)\
**Post date:** [May 11, 2012, 11:38pm UTC](https://forum.ansible.com/t/define-var-if-not-defined/11538/1 "2012-05-11T23:38:29Z")

</div>

Hi,

Does anyone have any suggestions on how this problem could be solved:

I have a playbook that I would like to invoke with the var ‘foo’ set to ‘bar’, using --extra-vars. So far fine. But in the playbook I want to set ‘foo’ to ‘baz’ if I don’t give it a value in --extra-vars.

Any ideas?

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [May 11, 2012, 11:42pm UTC](https://forum.ansible.com/t/define-var-if-not-defined/11538/2 "2012-05-11T23:42:07Z")

</div>

you could in Jinja2 templates but there is not otherwise a way to do it in a playbook, especially now that we execute Jinja2 only in actual templates for the template module.

--Michael

---

<div class="post-metadata">

**Author:** ![Matthew\_Williams](https://avatars.discourse-cdn.com/v4/letter/m/a3d4f5/32.png) [@Matthew\_Williams](https://forum.ansible.com/u/Matthew_Williams)\
**Post date:** [May 12, 2012, 12:20am UTC](https://forum.ansible.com/t/define-var-if-not-defined/11538/3 "2012-05-12T00:20:08Z")

</div>

Hmm… any ideas on how to do this. Would a patch be accepted?

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [May 12, 2012, 12:30am UTC](https://forum.ansible.com/t/define-var-if-not-defined/11538/4 "2012-05-12T00:30:50Z")

</div>

I’d say propose a syntax first?

---

<div class="post-metadata">

**Author:** ![Matthew\_Williams](https://avatars.discourse-cdn.com/v4/letter/m/a3d4f5/32.png) [@Matthew\_Williams](https://forum.ansible.com/u/Matthew_Williams)\
**Post date:** [May 12, 2012, 12:38am UTC](https://forum.ansible.com/t/define-var-if-not-defined/11538/5 "2012-05-12T00:38:41Z")

</div>

Perhaps similar to the vars\_prompt: let vars values be a dictionary, like so:

vars:  
foo: {value: “bar”, when: “‘${foo}’ == ‘’”}

The only thing here is that ${foo} would currently evaluate to the string “${foo}” if it’s not already defined.

Thoughts?

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [May 12, 2012, 12:45am UTC](https://forum.ansible.com/t/define-var-if-not-defined/11538/6 "2012-05-12T00:45:18Z")

</div>

I don’t particularly care for that.

While that seems logically more elegant if like this:

foo: { unless\_already\_set: 5 }

However that still bothers me in terms of syntax that is weird. It doesn’t fit well in my brain and feels like the exceptions and rules you have to remember are building up way too much.

I think this is one of those features that, because it is difficult to explain and unwieldy (and a bit of a corner case), it won’t exist in Ansible.

The current order of priorities is:

extra vars  
inventory overrides extra vars  
playbook vars override inventory

In which case my advice would be to make sure the script using extra vars sets the variable every time.

---

<div class="post-metadata">

**Author:** ![Matthew\_Williams](https://avatars.discourse-cdn.com/v4/letter/m/a3d4f5/32.png) [@Matthew\_Williams](https://forum.ansible.com/u/Matthew_Williams)\
**Post date:** [May 12, 2012, 1:06am UTC](https://forum.ansible.com/t/define-var-if-not-defined/11538/7 "2012-05-12T01:06:49Z")

</div>

Yeah, I ended up using a bash script wrapper that has the logic there.

---

<div class="post-metadata">

**Author:** ![John\_Kleint](https://avatars.discourse-cdn.com/v4/letter/j/df705f/32.png) [@John\_Kleint](https://forum.ansible.com/u/John_Kleint)\
**Post date:** [May 14, 2012, 1:20pm UTC](https://forum.ansible.com/t/define-var-if-not-defined/11538/8 "2012-05-14T13:20:02Z")

</div>

I’m not clear on how all this is supposed to work out, so there are probably some goals of this design that I’m missing. But to me, it seems like I’d want playbooks to be generic – you download one from a contrib repo on the Internet, and it has generic definitions you can use without modification. You tailor it to your site with the inventory, and you tailor to a specific run with extra vars.

For example: a playbook to install hadoop uses a group called “workers” to refer to all your cluster worker nodes. Your local cluster is probably not called “workers,” but its easy to add one to your inventory (and it would be _really_ easy with group aliases ;). Now say worker17 is acting up again, and you just want to run on one host, so you pass --extra-vars=“hosts=worker17”.

This matches the way most Unix tools work: defaults (try to) make sense for everyone, config files customize for the way you usually work, command line overrides config file for this invocation. It would also fix mgw’s problem.

So if this breakdown makes sense:

playbook → everybody on the Interwebs  
inventory → my site  
extra vars → this run

I’d think precedence would go like this:

playbook is lowest  
inventory overrides playbook  
extra vars (cmdline in general) overrides inventory

Thoughts?

-John

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [May 14, 2012, 1:50pm UTC](https://forum.ansible.com/t/define-var-if-not-defined/11538/9 "2012-05-14T13:50:39Z")

</div>

> I'm not clear on how all this is supposed to work out, so there are probably  
> some goals of this design that I'm missing. But to me, it seems like I'd  
> want playbooks to be generic -- you download one from a contrib repo on the  
> Internet, and it has generic definitions you can use without modification.  
> You tailor it to your site with the inventory, and you tailor to a specific  
> run with extra vars.

yeah, but this never works out in practice. Very true of Puppet and  
Chef "books" that they are almost  
never reusable without tweaks. That being said, we're not any worse  
in this regard.

There are at best examples you use, but everyone has different  
management requirements, and distributions, and  
application versions. It never works out as advertised.

> For example: a playbook to install hadoop uses a group called "workers" to  
> refer to all your cluster worker nodes. Your local cluster is probably not  
> called "workers," but its easy to add one to your inventory (and it would be  
> \*really\* easy with group aliases ;). Now say worker17 is acting up again,  
> and you just want to run on one host, so you pass  
> --extra-vars="hosts=worker17".

You can already pass in things to "hosts" via a variable in 0.4

hosts: $foo

--extra-vars="foo=groupname" etc

> playbook -\> everybody on the Interwebs  
> inventory -\> my site  
> extra vars -\> this run
> 
> I'd think precedence would go like this:
> 
> playbook is lowest  
> inventory overrides playbook  
> extra vars (cmdline in general) overrides inventory

> Thoughts?

We shouldn't be changing this seeing we're already well established.

Inventory is for geographic and hardware specific setup. You  
shouldn't have the same variables in both places, it's a sign things  
have gotten too complicated if so.
