# Ansible set variable task?

**URL:** <https://forum.ansible.com/t/ansible-set-variable-task/12504>\
**Category:** Ansible Project\
**Created:** [March 15, 2013, 1:19am UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504 "2013-03-15T01:19:43Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![willthames](https://avatars.discourse-cdn.com/v4/letter/w/8dc957/32.png) [@willthames](https://forum.ansible.com/u/willthames)\
**Post date:** [March 15, 2013, 1:19am UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/1 "2013-03-15T01:19:43Z")

</div>

Let’s say that I want to use a variable if it’s passed to ansible-playbook (via -e) and derive it otherwise

I can use register to get the results of the derivation, but the actual information I need is then typically in the stdout property.

Is there a better way to do the following ?

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [March 15, 2013, 1:56am UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/2 "2013-03-15T01:56:16Z")

</div>

> Is there a better way to do the following ?
> 
> ---  
> ...  
> tasks:  
> - name: derive latest 2.5 release  
> &nbsp;&nbsp;local\_action: shell ls /var/releases/v2.5-\* | tail -1  
> &nbsp;&nbsp;register: release  
> &nbsp;&nbsp;when\_unset: $version
> 
> - name: register version into release  
> &nbsp;&nbsp;local\_action: command echo $version  
> &nbsp;&nbsp;register: release  
> &nbsp;&nbsp;when\_set: $version
> 
> I would prefer the second task to be something like this (rather than having  
> to store the result of echoing the property!)
> 
> - name: store release.stdout into version  
> &nbsp;&nbsp;local\_action: variable name=version value=${release.stdout}

I'm not really against some kind of action plugin called 'setvar' that  
allows you to pass in python statements, but this seems like a  
question about  
whether hostvars has higher priority than extravars, and we've  
explicitly added extra vars at maximum priority so they can override  
defaults.

[http://ansible.cc/docs/playbooks2.html#understanding-variable-precedence](http://ansible.cc/docs/playbooks2.html#understanding-variable-precedence)

What it seems to me is that instead of doing it the way you are doing  
it, you could set the default in group\_vars/all, and then let the  
computed variable  
override it there.

While, no, it is not "-e", it is somewhat equivalent.

---

<div class="post-metadata">

**Author:** ![willthames](https://avatars.discourse-cdn.com/v4/letter/w/8dc957/32.png) [@willthames](https://forum.ansible.com/u/willthames)\
**Post date:** [March 15, 2013, 2:23am UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/3 "2013-03-15T02:23:58Z")

</div>

> > Is there a better way to do the following ?
> > 
> > * * *
> > 
> > …  
> > tasks:
> > 
> > - name: derive latest 2.5 release  
> > local\_action: shell ls /var/releases/v2.5-\* | tail -1  
> > register: release  
> > when\_unset: $version
> > 
> > - name: register version into release  
> > local\_action: command echo $version  
> > register: release  
> > when\_set: $version
> > 
> > I would prefer the second task to be something like this (rather than having  
> > to store the result of echoing the property!)
> > 
> > - name: store release.stdout into version  
> > local\_action: variable name=version value=${release.stdout}
> 
> I’m not really against some kind of action plugin called ‘setvar’ that  
> allows you to pass in python statements, but this seems like a  
> question about  
> whether hostvars has higher priority than extravars, and we’ve  
> explicitly added extra vars at maximum priority so they can override  
> defaults.

I think my question is more about how I can make the results of a registered variable be equivalent to other variables.

I’m happy with the precedence order, I just want to be able to derive a variable, with the same name, if it is not set.

> [http://ansible.cc/docs/playbooks2.html#understanding-variable-precedence](http://ansible.cc/docs/playbooks2.html#understanding-variable-precedence)
> 
> What it seems to me is that instead of doing it the way you are doing  
> it, you could set the default in group\_vars/all, and then let the  
> computed variable  
> override it there.

My problem is that the variables are being passed in by external deployment tool (deploy release x.y.z or just deploy latest) and so are passed in as extra vars.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [March 15, 2013, 2:44am UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/4 "2013-03-15T02:44:14Z")

</div>

Yep, extra vars have highest precedence, because most folks wanted  
them as overrides over the defaults.

You could consider using the environment lookup $ENV(FOO) from group\_vars/all

foo: $ENV(FOO)

[https://github.com/ansible/ansible/blob/devel/lib/ansible/runner/lookup\_plugins/env.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/runner/lookup_plugins/env.py)

In which case versus -e it would just be

FOO=1 ansible-playbook ...

and that may fix things.

---

<div class="post-metadata">

**Author:** ![Grant\_BlahaErath](https://avatars.discourse-cdn.com/v4/letter/g/e47774/32.png) [@Grant\_BlahaErath](https://forum.ansible.com/u/Grant_BlahaErath)\
**Post date:** [March 21, 2014, 10:46pm UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/5 "2014-03-21T22:46:34Z")

</div>

Old thread, but it popped up in my goog when I was looking for answers. Since I worked out two different solutions, I wanted to share them.

1. 

I needed to get a user account home directory and share it with a role. Just using register meant I would have to use “variable.stdout” everywhere. Instead I used the pre\_tasks section of the playbook to retrieve the value and then pulled the key/value out on the role’s variable declaration. Here’s the code I used. I hope this helps out others.

pre\_tasks:

- name: Get ansible\_user home directory  
shell: ‘getent passwd “{{ansible\_ssh\_user}}” | cut -d: -f6’  
register: ansible\_home\_result  
roles:
- { role: boxprep\_debian, ansible\_home: ‘{{ansible\_home\_result.stdout}}’, when: ansible\_os\_family == ‘Debian’ }
- { role: boxprep\_redhat, ansible\_home: ‘{{ansible\_home\_result.stdout}}’, when: ansible\_os\_family == ‘RedHat’ }

1. 

Another approach that is far more elaborate but can solve anything is to create a python application that uses jinja2, and then process all your .yml files as if they were jinja2 templates. The python application can solve any kind of variable instantiation challenge while leaving the .yml reusable for other scenarios. Because jinja2 will only process the template variables it is told to, it will leave other {{variables}} for ansible to define. I use this approach to query an elaborate AWS cluster, and then preprocess the ansible scripts.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [March 21, 2014, 11:20pm UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/6 "2014-03-21T23:20:47Z")

</div>

If you do “ansible hostname -m setup” in recent versions, you should see that environment variables are provided, in which case you can pull $HOME from there.

This of course would only work for the active user.

[http://docs.ansible.com/faq.html#how-do-i-access-shell-environment-variables](http://docs.ansible.com/faq.html#how-do-i-access-shell-environment-variables)

---

<div class="post-metadata">

**Author:** ![Grant\_BlahaErath](https://avatars.discourse-cdn.com/v4/letter/g/e47774/32.png) [@Grant\_BlahaErath](https://forum.ansible.com/u/Grant_BlahaErath)\
**Post date:** [March 21, 2014, 11:52pm UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/7 "2014-03-21T23:52:18Z")

</div>

Okay, my example kind of sucks and I’m not surprised that you noticed. I had to implement this approach after finding that ansible\_env.HOME did what it should, but not what I needed.

The playbooks run with “sudo: yes” because it was maddening to declare sudo state for each task. That makes ansible\_env.HOME evaluate to “/root”. This is how I solved that problem, but it became difficult to reuse code that had {{ansible\_home\_result.stdout}} everywhere.

The pattern is generally applicable for converting any dictionary pair into a single value variable.

I’m not sure how durable this solution will be since it depends on the pre\_task executing and updating the global dictionary before the role is evaluated. I feel like its depending on an implied behavior instead of a contract. A “setvar” solution like you proposed would be superior because the behavior is explicit.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [March 21, 2014, 11:54pm UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/8 "2014-03-21T23:54:25Z")

</div>

“I had to implement this approach after finding that ansible\_env.HOME did what it should, but not what I needed.”

Yep!

The HOME environment variable is not always predictable in sudo scenarios.

---

<div class="post-metadata">

**Author:** ![Brian\_Coca1](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@Brian\_Coca1](https://forum.ansible.com/u/Brian_Coca1)\
**Post date:** [March 21, 2014, 11:57pm UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/9 "2014-03-21T23:57:21Z")

</div>

shell: 'getent passwd |cut -f 6 -d “:” ’

register: userhome

---

<div class="post-metadata">

**Author:** ![willthames](https://avatars.discourse-cdn.com/v4/letter/w/8dc957/32.png) [@willthames](https://forum.ansible.com/u/willthames)\
**Post date:** [March 22, 2014, 12:00am UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/10 "2014-03-22T00:00:02Z")

</div>

Surely the result is still in userhome.stdout

Since this thread was created, (and still a good while ago) set\_fact was invented

set\_fact: new\_variable=“{{result.stdout}}”

---

<div class="post-metadata">

**Author:** ![Brian\_Coca1](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@Brian\_Coca1](https://forum.ansible.com/u/Brian_Coca1)\
**Post date:** [March 23, 2014, 12:03am UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/11 "2014-03-23T00:03:10Z")

</div>

getent facts module

[https://github.com/ansible/ansible/pull/6625](https://github.com/ansible/ansible/pull/6625)

---

<div class="post-metadata">

**Author:** ![Grant\_BlahaErath](https://avatars.discourse-cdn.com/v4/letter/g/e47774/32.png) [@Grant\_BlahaErath](https://forum.ansible.com/u/Grant_BlahaErath)\
**Post date:** [March 24, 2014, 10:39pm UTC](https://forum.ansible.com/t/ansible-set-variable-task/12504/12 "2014-03-24T22:39:19Z")

</div>

Thanks Will.

I did not know about set\_facts. I am not surprised that I got the search term wrong. If we are lucky, this thread will bridge the two lexical choices in the goog.

I modified my snippet to look like this.

pre\_tasks:

- name: Get ansible\_user home directory  
shell: ‘getent passwd “{{ansible\_ssh\_user}}” | cut -d: -f6’  
register: ansible\_home\_result

- name: Set the fact for the other scripts to use  
set\_fact: ansible\_home=‘{{ansible\_home\_result.stdout}}’

I also submitted a pull for a doc change in the variable documentation since it was the first place i went looking for answers.
