Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Re: [ansible-project] Var precedence

707 views
Skip to first unread message

Michael DeHaan

unread,
May 24, 2013, 5:01:56 PM5/24/13
to ansible...@googlegroups.com
There are plenty of ways to set defaults.

You can put your systems into a group, and put the variables into group_vars/<groupname>.

This has the lowest precedence of anything in Ansible, and you can even have defaults for those in group_vars/<all>.

Yes, things included in your playbook absolutely are used.  You may say it's backwards but for other people it's quite logical and important, and we're not changing it :)  If you read a variable in a playbook, you *KNOW* it is being set.

Finally, you can just do basic stuff like so:

- hosts: blarg
  vars_files:
       - defaults.yml
       - blarg.yml

- hosts: glorp
  vars_files:
       - defaults.yml
       - glorp.yml

Which isn't using group_vars (IMHO you should use group_vars), but effectively does the same thing a bit more explicitly.




On Thu, May 23, 2013 at 3:32 PM, Phillip Gentry <phi...@cx.com> wrote:
So it looks like I've hit my first real blocker using ansible. I have eight environments currently and will be adding more in the future. I need to set defaults for certain vars, which may get overriden on a per environment basis. (using a seperate host file for each environment) 

I tried defining defaults in the /role/vars/main.yml, then overrride those via host file; unfortunately that works backwards. The role var overrides the var defined in all the host files.. which seems really strange to me, but maybe I am missing something.

I really need a way to do this in a way that doesn't require every environment/host file to have every var in it.

Is there a better way to do this?

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Michael DeHaan <mic...@ansibleworks.com>
CTO, AnsibleWorks, Inc.
http://www.ansibleworks.com/

Serge van Ginderachter

unread,
May 24, 2013, 5:20:42 PM5/24/13
to ansible...@googlegroups.com
If you want to overrule variables in roles with variables defined in the playbook (or elsewhere) you might try something like this:

$ cat rolesvar.yml
- hosts: localhost
  gather_facts: false
  vars:
   foo2: overruled_rom_role_invocation
  roles:
  - role: test
  - role: test
    foo: $foo2

$ ansible-playbook rolesvar.yml

PLAY [localhost] ************************************************************** 

TASK: [debug msg=default_from_role] ******************************************* 
ok: [localhost]

TASK: [debug msg=overruled_rom_role_invocation] ******************************* 
ok: [localhost]

PLAY RECAP ******************************************************************** 
localhost                  : ok=2    changed=0    unreachable=0    failed=0   


Serge

martin f krafft

unread,
Jun 11, 2013, 9:39:22 AM6/11/13
to ansible...@googlegroups.com
also sprach Michael DeHaan <mic...@ansibleworks.com> [2013.05.24.2301 +0200]:
> Yes, things included in your playbook absolutely are used. You
> may say it's backwards but for other people it's quite logical and
> important, and we're not changing it :)

Please show me a use-case where the existing behaviour makes sense.
I really don't think there is a way to look at it "forwards".

Roles exist to encourage code reuse. I think they should work on the
"least assumptions" principle. If I add a role to my playbook,
I expect it to just work. Then I can start tweaking parameters
exported by the role.

Look at your NTP example in the docs: the NTP server URI is a good
example of such a parameter.

The author of the NTP role does not want to expect users to have to
define an NTP server, so s/he provides a default.

The user, however, will want to change that default based on groups
and hostnames. Conveniently, a look into roles/ntp/vars/main.yml
suffices to know which parameters exist and what their defaults are.
The user hence chooses to overwrite $ntp_server like so:

1. group_vars/all sets e.g. $ntp_server to pool.ntp.org
2. group_vars/de sets $ntp_server to de.pool.ntp.org
3. host_vars/home-router sets $ntp_server to my DCF77 clock at
home.

However, ansible doesn't work that way.

Instead, the author needs to define $default_ntp_server in
vars/main.yml and always remember to use

{{ $ntp_server | default $default_ntp_server }}

in jinja2 templates, or whatever construct is necessary to give
precedence to a variable that may or may not exist, before resorting
to the default. This is extra work, and makes templates and code and
task lists more complex than they need to be.

The user now cannot copy-paste from vars/main.yml anymore, but needs
to remember to strip the "default_" prefix from variables s/he wants
to override.

On the other hand, it is possible to do things like this in
a playbook:

---
- roles
- role: ntp
default_ntp_server: pool.ntp.de

which will overwrite the variables defined in the role. If you ask
me, that is inconsistent at least. Either the role variable
definitions have precedence, or the user of a role can set
variables.

But instead it is such that the user has to remember exactly which
way of defining variables takes precedence and which approach cannot
be used.

And to me, the approach that cannot be used is the one that makes
most sense.

When implementing any form of variable precedence, there is a simple
rule that needs to be followed:

Variables that apply to a smaller set take precedence over
variables that apply to a larger set.

Ansible does not follow this rule, because the set of users of
a role is larger than the set of all hosts in a given ansible
installation or infrastructure (group_vars/all).

This is my current perspective and I hope I managed to make it clear
why I (also) think that Ansible does things backwards.

Would you please be so kind as to enlighten me and help me
understand your point of view, and why you (and others) might think
that Ansible does it right?

Thanks,

--
martin | http://madduck.net/ | http://two.sentenc.es/

"gott ist tot! und wir haben ihn getötet."
- friedrich nietzsche

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

Brice Burgess

unread,
Jun 11, 2013, 11:15:07 AM6/11/13
to ansible...@googlegroups.com, mad...@madduck.net
Martin,

I haven't had time to play with ansible 1.2 yet (but soon will now that it's released!); but would something like this work:

  1. role vars / set $default_ntp_server to pool.ntp.org
  2. group_vars/all sets e.g. $ntp_server to {{ $default_ntp_server | default pool.ntp.org }}
  3. group_vars/de sets $ntp_server to de.pool.ntp.org
  4. host_vars/home-router sets $ntp_server to my DCF77 clock at
     home.

Basically is uses your example but the global group variables will look for the role's default_ntp_server and use that before falling back to its own default for $ntp_server

martin f. krafft

unread,
Jun 11, 2013, 11:41:27 AM6/11/13
to ansible...@googlegroups.com
also sprach Brice Burgess <bric...@gmail.com> [2013.06.11.1715 +0200]:
> I haven't had time to play with ansible 1.2 yet (but soon will now that
> it's released!); but would something like this work:
>
> 1. role vars / set $default_ntp_server to pool.ntp.org
> 2. group_vars/all sets e.g. $ntp_server to {{ $default_ntp_server |
> default pool.ntp.org }} <http://pool.ntp.org>
> 3. group_vars/de sets $ntp_server to de.pool.ntp.org
> 4. host_vars/home-router sets $ntp_server to my DCF77 clock at
> home.

Maybe this will work, maybe not. In my opinion, we should not be
expecting (re-)users of roles to jump through such hoops.
a Hooloovoo is a superintelligent shade of the color blue.
-- douglas adams, "the hitchhiker's guide to the galaxy"

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

GW

unread,
Jun 11, 2013, 3:44:37 PM6/11/13
to ansible...@googlegroups.com

On Tue, 11 Jun 2013 15:39:22 +0200, martin f krafft wrote:

Would you please be so kind as to enlighten me and help me
understand your point of view, and why you (and others) might think
that Ansible does it right?

I also think Ansible doesn't do it right, but that is the unintuitive way how you have to deal with variables here.

Greetings,
gw

martin f krafft

unread,
Jun 11, 2013, 5:15:38 PM6/11/13
to ansible...@googlegroups.com
also sprach GW <gw....@tnode.com> [2013.06.11.2144 +0200]:
> I also think Ansible doesn't do it right, but that is the
> unintuitive way how you have to deal with variables here.

As Michael said, it's only unintuitive to me. I would really like to
hear someone to whom the current way is intuitive, and be able to
learn.
#define emacs eighty megabytes and constantly swapping.

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

Brian Coca

unread,
Jun 11, 2013, 6:27:59 PM6/11/13
to ansible...@googlegroups.com

Works for me, but I use single inventory and use group vars to handle envs.

Brian Coca

martin f krafft

unread,
Jun 12, 2013, 2:26:49 AM6/12/13
to ansible...@googlegroups.com
also sprach Brian Coca <bria...@gmail.com> [2013.06.12.0027 +0200]:
> Works for me, but I use single inventory and use group vars to handle envs.

You are not using roles, right? I think var precedence is okay in
Ansible, but the way roles are handled is not yet.
a qui sait comprendre, peu de mots suffisent.
-- intelligenti pauca

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

Petros Moisiadis

unread,
Jun 12, 2013, 4:19:35 AM6/12/13
to ansible...@googlegroups.com
On 06/12/2013 12:15 AM, martin f krafft wrote:
> also sprach GW <gw....@tnode.com> [2013.06.11.2144 +0200]:
>> I also think Ansible doesn't do it right, but that is the
>> unintuitive way how you have to deal with variables here.
> As Michael said, it's only unintuitive to me. I would really like to
> hear someone to whom the current way is intuitive, and be able to
> learn.
>
Maybe it helps to make the following thoughts:

If you want playbooks / roles / tasks to be parametrized with variables
from the inventory then you use inside them variables that are meant to
be set in the inventory.

Reusing a role in your specific context involves including it in your
playbook as well as:
1) Adding the variables needed for that role in your inventory, in which
case your playbook becomes also reusable, since inventory vars can
always be organised as needed.
or
2) Passing variable overrides at the 'include' step in your playbook, in
which case the playbook may become less reusable, if the passed
overrides are too specific.

martin f krafft

unread,
Jun 12, 2013, 5:05:52 AM6/12/13
to ansible...@googlegroups.com
also sprach Petros Moisiadis <erne...@yahoo.gr> [2013.06.12.1019 +0200]:
> If you want playbooks / roles / tasks to be parametrized with
> variables from the inventory then you use inside them variables
> that are meant to be set in the inventory.

Right, but doesn't this mean that I have to set all variables
exported by all roles in the inventory, unless I can assume that
every role can handle the absence of a variable and provide sensible
defaults.

This requires role authors to maintain a documentation about which
variables are set, which is extra work and could easily get out of
sync. If all variables are initialised to defaults in vars/main.yml,
then this file itself serves as reference for which parameters can
be set.

But also, look at it from another angle:

If variables set within a role always override variables from the
inventory, why would the role author even care setting a variable?
Yes, of course, it's better to parametrise your source code's
tunables just like you might factor out e.g. NUM_PLAYERS to the top
of a C source code file for a game, instead of hard-coding the
number of players in the code. But if that cannot be overridden by
the user of the code, then it's not a variable but a constant.

So while I still think that role variables should have lower
precedence than inventory variables (which should have lower
precedence than variables set in playbooks and include parameters),
if Michael and others disagree, then maybe vars/main.yml should be
renamed to constants/main.yml?
"das internet wurde konzipiert, um einem atomschlag standzuhalten.
leider hatte kein militärstratege mit der deutschen telekom
gerechnet..."
-- attila radnai

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

Michael DeHaan

unread,
Jun 12, 2013, 7:01:32 AM6/12/13
to ansible...@googlegroups.com
As I posted on May 24th, "group_vars" is a great place to stick defaults, and as of 1.2, they can also live in your playbook directory.

Variables in roles/foo/main.yml do get loaded.  It's true, they will be used.

However, there's nothing to say you can't set parameters to the role in your playbook, like so, too... and is a great way to pass required parameters:

roles:
    - { role: foo, x: 42, y: asdf.example.com }

We're not going to be changing the order of inventory precedence.


martin f krafft

unread,
Jun 12, 2013, 8:57:55 AM6/12/13
to ansible...@googlegroups.com
also sprach Michael DeHaan <mic...@ansibleworks.com> [2013.06.12.1301 +0200]:
> As I posted on May 24th, "group_vars" is a great place to stick
> defaults, and as of 1.2, they can also live in your playbook
> directory.

But neither of those are under control of the author of a role, and
since roles are supposed to encourage reuse of work, they need to be
self-contained.

> However, there's nothing to say you can't set parameters to the role in
> your playbook, like so, too... and is a great way to pass required
> parameters:
>
> roles:
> - { role: foo, x: 42, y: asdf.example.com }

Yes, I am aware of this, although I wonder about the difference in
syntax between this and the way includes get parametrised.

Using this approach, it is possible to override role parameters
per-playbook, and hence for the group(s) to which the playbook
applies.

However, if the playbook applies to two groups and you want to
specify different parameters for each group, or you want to be able
to use host-specific parameters, you have to resort to something
like

- { role: foo, x: 42, ntp_server: $my_url }

and define $my_url in group_vars/host_vars, rather than just
defining $ntp_server there. That's an extra level of indirection and
hence an extra source of error and confusion…

> We're not going to be changing the order of inventory precedence.

I am not asking you to do that, especially not what is documented
already. However, roles are a new concept, and they aren't even
included in the docs on variable precedence yet. Therefore, I don't
think we are looking to change existing behaviour, but rather
discussing a new feature. And I think that the way this feature
currently interacts with variable precedence is non-intuitive and
suboptimal.

Am I not succeeding in describing why, and what could be done
instead?
"vulgarity is simply the conduct of other people."
-- oscar wilde

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

Brian Coca

unread,
Jun 12, 2013, 11:54:27 AM6/12/13
to ansible...@googlegroups.com
roles can have 'requried' values and still be reusable, I don't see the need of having all needed values populated in the role when it makes more sense to pass them as input.

-- 
Brian Coca
Stultorum infinitus est numerus
0110000101110010011001010110111000100111011101000010000001111001011011110111010100100000011100110110110101100001011100100111010000100001
Pedo mellon a minno

Michael DeHaan

unread,
Jun 12, 2013, 4:32:56 PM6/12/13
to ansible...@googlegroups.com
Yep, if the parameter is required, don't have a default :)


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

martin f krafft

unread,
Jun 13, 2013, 2:37:42 AM6/13/13
to ansible...@googlegroups.com
also sprach Brian Coca <bria...@gmail.com> [2013.06.12.1754 +0200]:
> roles can have 'requried' values and still be reusable, I don't
> see the need of having all needed values populated in the role
> when it makes more sense to pass them as input.

Agreed, but then what is vars/main.yml to be used for anyway? Am
I right in assuming that it's really constants/main.yml?
"it is impossible to foresee the consequences of being clever."
-- cristopher strachey

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

Michael DeHaan

unread,
Jun 13, 2013, 7:09:27 AM6/13/13
to ansible...@googlegroups.com
It's for defining any variables you want the role to pull in to vars_files.

There is no slash "constants/", it's called "vars/" and you can put whatever you like in there.



David Golden

unread,
Jun 13, 2013, 8:43:17 AM6/13/13
to ansible...@googlegroups.com
I'm late to this thread and new-ish to roles, but let me articulate
what I would find least surprising:

(1) role main.yml variables provide defaults

(2) parameters passed to a role override the variables in main.yml

(3) to the extent that I want the role variable to be dynamic by
host/group, I have a way to pass a variable as a parameter value to
the role, e.g. something like:

{ role: foo, x: 42, ntp_server: $my_url }

(I'm not actually sure if Ansible works this way or if #3 actually works or not)

In other words, I want to be able to reason about roles like a
subroutine call. "Execute yourself with these parameters". Global
variables are bad.

I'm actually not entirely sure how ansible scopes variables. What if
two roles use the same parameter name? What if a role uses a
parameter and a host or group var of the same name is used elsewhere?
If everything is globally scoped, then re-usability is harder because
anything might stomp on the variable name of something else.

How do I write ordinary (not Ansible) programs with external config?
I load external config into variables (or a single data structure,
whatever). I then pass those to functions as needed.

Ansible is pretty much a procedural language and it should encourage
good variable scoping practices, just as we would for "real" programs.

David
> --
> You received this message because you are subscribed to the Google Groups
> "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to ansible-proje...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>



--
David Golden <x...@xdg.me>
Take back your inbox! → http://www.bunchmail.com/
Twitter/IRC: @xdg

martin f krafft

unread,
Jun 13, 2013, 10:04:53 AM6/13/13
to ansible...@googlegroups.com
also sprach Michael DeHaan <mic...@ansibleworks.com> [2013.06.13.1309 +0200]:
> It's for defining any variables you want the role to pull in to
> vars_files.

There's a bit of light at the end of the tunnel. Are you suggesting
that just like roles can be used to factor out tasks and handlers
from playbooks, vars/main.yml in the role will essentially be
appended to the vars_files list of the playbook?

How does this interact with an existing vars_files list in the
playbook? Are the role var_files prepended or appended to the
existing list?

What happens when multiple roles are used?

Thanks,
for years, we have thought that a million monkeys typing at a million
typewriters would eventually produce the complete works of shakespeare.
today, thanks to the internet, we know this is not true.

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

martin f krafft

unread,
Jun 13, 2013, 10:17:10 AM6/13/13
to ansible...@googlegroups.com
also sprach David Golden <x...@xdg.me> [2013.06.13.1443 +0200]:
> (1) role main.yml variables provide defaults
> (2) parameters passed to a role override the variables in main.yml
> (3) to the extent that I want the role variable to be dynamic by
> host/group, I have a way to pass a variable as a parameter value to
> the role, e.g. something like:
>
> { role: foo, x: 42, ntp_server: $my_url }

I think this is precisely how things currently work.

> In other words, I want to be able to reason about roles like
> a subroutine call. "Execute yourself with these parameters".
> Global variables are bad.

This is a good point! However, it would require proper scoping, but…

> I'm actually not entirely sure how ansible scopes variables.

It does not. If, in the example above, *any* role defines $my_url,
it will override the value if that was set earlier by a group_vars
or host_vars file or statement.

> What if two roles use the same parameter name?

In that case, one will overwrite the other. I assume that the one
that's loaded later will overwrite the former.

Maybe the real solution is to scope all variables within Ansible.

- Role variables should be available only within a role;
- Playbook variables should only be available to that playbook.
I wouldn't even make them available to included playbooks then.
- Group and Host variables are available all the time, but maybe
they can be scoped to group_vars:: and host_vars:: respectively.
- Ansible facts should probably also be scoped, although they
already are in some ways through the $ansible_ convention. There
ought to be a transitional period with DeprecationWarnings,
IMHO.
"alles sollte so einfach, wie möglich gemacht sein,
aber nicht einfacher."
-- albert einstein

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

Michael DeHaan

unread,
Jun 13, 2013, 11:19:09 AM6/13/13
to ansible...@googlegroups.com
Ansible intentionally lacks vars_scoping.

It's all part of the simplicity of things to not have to have conversations about scoping.

If you want something named foo_port, don't name the variable port, etc.

I recognize that this is different from what some people want, but at the same time being *exactly* what some people want.

--Michael

martin f krafft

unread,
Jun 13, 2013, 11:53:08 AM6/13/13
to ansible...@googlegroups.com
also sprach Michael DeHaan <mic...@ansibleworks.com> [2013.06.13.1719 +0200]:
> Ansible intentionally lacks vars_scoping.
>
> It's all part of the simplicity of things to not have to have
> conversations about scoping.

I am really failing to see your "simplicity of things" argument, and
I also doubt that there are really people who *want* *exactly* the
current behaviour, namely:

- roles (i.e. reusable, sharable code) can overwrite variables in
playbooks, and even the ones that are very specific to the
inventory (host_vars, group_vars). This means that using a role
may well break other, completely unrelated parts of my setup;

- role variables themselves can all be overwritten by other roles
and vars_files, not only through parametrised role includes. You
are advocating a soft, "by-convention" remediation that is
functionally equivalent to scoping, but optional and
error-prone;

- roles basically do not have an interface and do not obey any
form of imperative paradigms or closure. It feels a bit like
the re-use you are trying to achieve with roles is equivalent to
giving root access to the developers of tools I want to use;

- there is no way to find out what may be tempering/overwriting my
variables after all variables from all over the place have been
munged in the global namespace according to precedence rules
that do not obey the "most-specific-wins" principle. In fact,
I'd argue that the way variable resolution takes place is
actually almost non-determinstic in the event of multiple,
conflicting defintions;

- role include parametrisation syntax is different from playbook
include parametrisation syntax. The former, requiring me to
enter ascii-representations of data structures feels like a hack
at best;

Who could possibly want all of that?

> I recognize that this is different from what some people want, but
> at the same time being *exactly* what some people want.

Good software, especially "simple" software, hard-codes no
assumptions; it provides flexible interfaces and leaves all the rest
up to the user.
i stopped fighting my inner demons.. we're all on the same side now.

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

David Golden

unread,
Jun 13, 2013, 1:12:20 PM6/13/13
to ansible...@googlegroups.com
On Thu, Jun 13, 2013 at 11:19 AM, Michael DeHaan
<mic...@ansibleworks.com> wrote:
> Ansible intentionally lacks vars_scoping.
>
> It's all part of the simplicity of things to not have to have conversations
> about scoping.

I think you're having them. :-)

> If you want something named foo_port, don't name the variable port, etc.

Assuming no scoping, then having conventions like "prefix role
variables with the role name" seems like the best.

But even that doesn't help me understand what to expect if I use a
parameterized role more than once.

E.g. I set "myrole_foo" variable with a default of "bar" in the
role/myrole/vars/main.yml file. Then I have playbook that call the
role once overriding "myrole_foo" and once without:

- { role: myrole, myrole_foo: baz }
- { role: myrole }

In the second role invocation, is "myrole_foo" the default "bar" or is
it "baz" because it's a global overwritten by the first role
invocation? From what you said about scope, I think it's going to be
"baz".

If so, then the global scope *severely* restrict the ability to have
reusable roles with defaults. Roles have to be fully parameterized to
ensure the globals are set correctly for each invocation. That's not
DRY.

I realize getting scoping right is hard, but I think it's worth it to
figure out the right way to make it work for ansible.

David

Michael DeHaan

unread,
Jun 13, 2013, 3:20:21 PM6/13/13
to ansible...@googlegroups.com
Yeah guys, I understand you don't like things.

Ultimately, if you feel this way, it might not be for you.

There is precedence as defined in the docs.


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Michael DeHaan

unread,
Jun 13, 2013, 3:28:48 PM6/13/13
to ansible...@googlegroups.com
BTW, if you pass a variable to the role on the role line, that's not used later.

I guess I shouldn't say there's no scope, I should say that vars_files do not apply only to their specific role.

This is not true of parameters *passed* to roles, those only apply there.





On Thu, Jun 13, 2013 at 1:12 PM, David Golden <x...@xdg.me> wrote:
--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


David Golden

unread,
Jun 13, 2013, 4:25:50 PM6/13/13
to ansible...@googlegroups.com
On Thu, Jun 13, 2013 at 3:28 PM, Michael DeHaan
<mic...@ansibleworks.com> wrote:
> BTW, if you pass a variable to the role on the role line, that's not used
> later.

That's good to know!

> I guess I shouldn't say there's no scope, I should say that vars_files do
> not apply only to their specific role.

So now I'm confused. You said Ansible intentionally lacks vars
scoping, but you do appear to have vars scoping for roles.

It would be really helpful to get some more clarity around all the
different ways that variables can be set and the precedence between
them now that roles are in the picture.

What I get from the docs is this:

* inventory variables -- host vars and group vars

* playbook variables -- vars_file, extra vars on command line, vars in playbook

* "set during the play" -- register option, set_fact module, custom
facts returned from modules

If I understand you correctly, a role vars file is equivalent to a
playbook vars_file (but what precedence between them?).

And you said that parameters provided to a role invocation survive the
role invocation only. But do they have more precedence than anything
else? Or only more precedence than other things at the playbook
level? Or something else?

Unrelated to roles, do register variables survive the play? set_fact
is defined as surviving the play and collected facts clearly do.

Part of what I'm struggling to grok is the interaction between
"precedence" and "survives X part of process".

Michael DeHaan

unread,
Jun 13, 2013, 4:35:37 PM6/13/13
to ansible...@googlegroups.com
It's been a busy day, roles and tasks can be passed variables, inventory scope is also different than things defined in variable files.

So I was wrong to say there was not scoping.

I initially understood this thread to be about something like having arbitrary levels of scope and nesting, which we intentionally do *not* have.   

It is very important for me to persue a modelling/infrastructure-as-data approach as to being a system that needs to discuss "clojures" and other things, which I believe is a major problem in the automation tools space that excludes users.

What we do is it make it easy to describe what you want to do, and we don't dwell on the terminology quite so much :)

registered variables are available for the rest of the playbook run, and are accessible for other hosts via "hostvars", which is covered in the docs.



--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


martin f krafft

unread,
Jun 13, 2013, 5:08:40 PM6/13/13
to ansible...@googlegroups.com
also sprach Michael DeHaan <mic...@ansibleworks.com> [2013.06.13.2235 +0200]:
> It's been a busy day, roles and tasks can be passed variables,
> inventory scope is also different than things defined in variable
> files.
>
> So I was wrong to say there was not scoping.
>
> I initially understood this thread to be about something like
> having arbitrary levels of scope and nesting, which we
> intentionally do *not* have.

There are two issues at hand:

1. some of us believe that a role's vars/main.yml file should
define defaults at a very low level of precedence, i.e. *below*
the inventory variables;

2. some of us believe that there ought to be no global scope at
all (thereby eradicating (1.)), but that each role should have
its own scope and variables set within a role cannot ever leak
outside the role. Only through role parametrisation can those
variables be overridden, although I feel it would be better if
the role author could specify a subset of variables that are
changeable;

I initially came at things from the point of view of (1.), asking
for counter-arguments, and the recent comment on the badness of
the global scope and the goodness of thinking about roles as an
imperative paradigm helped me move on to (2.).

As I attempted to illustrate in
msgid:<2013061315...@fishbowl.rw.madduck.net>, I think the
lack of scoping of role variables is a serioues problem. I hope that
you are not going to shut the doors on this one and say that "while
some might not like it, others do, and I won't change it", because
that would be a shame.

> It is very important for me to persue
> a modelling/infrastructure-as-data approach as to being a system
> that needs to discuss "clojures" and other things, which I believe
> is a major problem in the automation tools space that excludes
> users.

Closure is not that hard of a concept and it's always a question of
whom you target. I think it's reasonable to assume that anyone who
seeks to control large numbers of systems with an automating tool
such as Ansible can be expected to know basic imperative paradigms,
including common closure/scoping, and precedence rules.

I'd even go as far as to say that if anyone approached a set of
machines with an automation tool without that knowledge, they would
do really well long-term investing time now to learn these basic
principles.

Excluding users is never good. But for the same reason as I don't
think that tools like webmin or PHPMyAdmin ("web-based root over
PHP") should ever be touched, I don't think that automation tools
should be written with sympathy for dummies.
"we should have a volleyballocracy.
we elect a six-pack of presidents.
each one serves until they screw up,
at which point they rotate."
-- dennis miller

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

David Golden

unread,
Jun 13, 2013, 7:33:42 PM6/13/13
to ansible...@googlegroups.com
On Thu, Jun 13, 2013 at 5:08 PM, martin f krafft <mad...@madduck.net> wrote:
> 1. some of us believe that a role's vars/main.yml file should
> define defaults at a very low level of precedence, i.e. *below*
> the inventory variables;

I can easily see how different people might reach different
conclusions on that point, simply on what they see as the most
specific element of their orchestration. Inventories and playbooks
are a many-many mapping, so depending on whether you have more of one
or the other, it's pretty arbitrary which seems more specific to any
person.

That doesn't bother me as long as it's clearly documented.

Personally, I think such variables should be orthogonal in practice.
Inventory vars should be about the inventory. Putting playbook (or
role) defaults there leads to global variable spaghetti. I don't mind
taking an inventory variable and passing it explicitly to a role
parameter because that makes the code very clear.

> 2. some of us believe that there ought to be no global scope at
> all (thereby eradicating (1.)), but that each role should have
> its own scope and variables set within a role cannot ever leak
> outside the role. Only through role parametrisation can those
> variables be overridden, although I feel it would be better if
> the role author could specify a subset of variables that are
> changeable;

I don't think there has to be no global scope. On reflection my
concern is mostly about whether re-usable constructs (roles and
includes) that take parameter get dynamic scope for their parameters
or not. (For anyone not clear on "dynamic scope", see
https://en.wikipedia.org/wiki/Dynamic_scope#Lexical_scoping_and_dynamic_scoping.)

The use of global scope for most variables -- particularly collected
facts -- does makes it easy to sidestep explicit parameter passing and
returns. I get why that is "simpler" for most common tasks.

As I said in some other thread, it does mean having to be more careful
about variable names. For instance, I've taken to always using the
role name as a prefix for role variables. That's fine. It's a bit
verbose, but it works.

Sébastien Simard

unread,
Jun 13, 2013, 2:28:50 PM6/13/13
to ansible...@googlegroups.com
Just wondering: have you guys considered making variables immutable once set? 
This approach is used by the ant build tool (see [1]), and it seems to me that it *might* make reasoning about playbooks easier and fit quite naturally with the sequential execution model that ansible follows.

Just a thought,
- Seb



2013/6/13 David Golden <x...@xdg.me>

Michael DeHaan

unread,
Jun 14, 2013, 11:57:26 AM6/14/13
to ansible...@googlegroups.com
There's really not a need for variable immutability actually.

What happens is the global things, like vars_files, apply globally, and setting inventory variables and facts does not stomp into the global scope, but are stored on a per host basis.  See "hostvars" and the like in the docs.

Yeah, I mispoke when I said there was no scope :)  Consequence of posting during AnsibleFest when I had limited time.

I meant to say we don't have anything like block scoping on purpose, because that's confusing :)


GW

unread,
Jun 20, 2013, 4:54:52 AM6/20/13
to ansible...@googlegroups.com

Hi,

On Thu, 13 Jun 2013 23:08:40 +0200, martin f krafft wrote:

  1. some of us believe that a role's vars/main.yml file should
     define defaults at a very low level of precedence, i.e. *below*
     the inventory variables;

Sorry for bringing up the old thread, but what do you all think of introducing "vars_defaults"
in plays that would be similar to "vars_files", but would have either the lowest possible priority
(lower than "group_vars/all") or at least lower than "vars" (above all inventory variables)?

If roles would than (maybe configurable behavior), instead of "vars_files: .../vars/main.yml"
implicitly use "vars_defaults: .../vars/main.yml" this would solve all precedence issues. Or maybe
roles could implicitly use "vars_defaults: .../vars/defaults.yml" and "vars_files: .../vars/main.yml".

Use case for a couple of re-usable roles each with its own "vars/main.yml" that all define the same
variables and you want to override most of them would result in unnecessary large play, because
you need to specify role parameters over and over again. Eg.:

- hosts: xxx
  roles:
    - role: net_basic
      net_name: thishostname
      net_domain: thisdomain
      net_fqdn: thishostname.thisdomain
net_primary_ip: 1.2.3.4
      net_primary_netmask: 255.255.255.0
    - role: net_iface
      net_name: thishostname
      net_domain: thisdomain
      net_fqdn: thishostname.thisdomain
net_primary_ip: 1.2.3.4
      net_primary_netmask: 255.255.255.0
    - role: net_iptables
      net_name: thishostname
      net_domain: thisdomain
      net_fqdn: thishostname.thisdomain
net_primary_ip: 1.2.3.4
      net_primary_netmask: 255.255.255.0
Wouldn't it be much cleaner to have the ability to use it as (or even putting the vars into inventory?):

- hosts: xxx
vars:
      net_name: thishostname
      net_domain: thisdomain
      net_fqdn: thishostname.thisdomain
net_primary_ip: 1.2.3.4
      net_primary_netmask: 255.255.255.0
  roles:
    - net_basic
    - net_iface
    - net_iptables

Where in case you forget to specify anything the default from "vars/defaults.yml" kicks-in?

Greetings,
gw 

martin f krafft

unread,
Jun 20, 2013, 8:56:31 AM6/20/13
to ansible...@googlegroups.com
also sprach GW <gw....@tnode.com> [2013.06.20.1054 +0200]:
> Sorry for bringing up the old thread, but what do
> you all think of introducing "vars_defaults"

I think this is a cool idea:

- vars_defaults in addition to vars and vars_files in playbooks;
- vars/defaults.yml, or defaults/main.yml to populate that from
a role;
- vars_defaults would have the lowest precedence, i.e. below
group_vars.

However, I could still imagine newcomers being confused by the link
between vars/main.yml and vars_files. Once that is understood, the
nomenclature makes sense, i.e. vars/*.yml are all vars_files. But
then we don't want to have a special case for defaults.yml…

So maybe defaults, defaults_files, and defaults/main.yml?
chaos reigns within.
reflect, repent, reboot.
order shall return.

spamtraps: madduc...@madduck.net
digital_signature_gpg.asc

Michael DeHaan

unread,
Jun 20, 2013, 12:13:25 PM6/20/13