Include Files for Role Variables

8,994 views
Skip to first unread message

AmiableAlbion

unread,
Jan 17, 2014, 12:14:06 PM1/17/14
to ansible...@googlegroups.com
I am struggling to break out variables in the "var" directory of roles into individual files

I have tried and continue to get tracebacks. I thought this would be straight forward after seeing the documentation for include_vars, but evidently I am missing something here. 

I was trying something like this with Ansible 1.4.4

vars/main.yml
- include_vars: credentials.yml
- include_vars: imagenames.yml

vars/imagenames.yml
centos64: 52225cb3-441b-47b6-9cca-deb14d24d72f
rhel64: 364cd1c1-e958-4327-a0b4-3251da47869c

> ansible-playbook vm.yml
Traceback (most recent call last):
  File "/usr/bin/ansible-playbook", line 269, in <module>
    sys.exit(main(sys.argv[1:]))
  File "/usr/bin/ansible-playbook", line 209, in main
    pb.run()
  File "/usr/lib/python2.6/site-packages/ansible/playbook/__init__.py", line 229, in run
    play = Play(self, play_ds, play_basedir)
  File "/usr/lib/python2.6/site-packages/ansible/playbook/play.py", line 83, in __init__
    ds = self._load_roles(self.roles, ds)
  File "/usr/lib/python2.6/site-packages/ansible/playbook/play.py", line 327, in _load_roles
    roles = self._build_role_dependencies(roles, [], self.vars)
  File "/usr/lib/python2.6/site-packages/ansible/playbook/play.py", line 192, in _build_role_dependencies
    role_vars = utils.combine_vars(vars_data, role_vars)
  File "/usr/lib/python2.6/site-packages/ansible/utils/__init__.py", line 1008, in combine_vars
    return dict(a.items() + b.items())
AttributeError: 'list' object has no attribute 'items'

Perhaps I am abusing syntax here though ... 

Thanks
Albion

Matt Martz

unread,
Jan 17, 2014, 12:17:44 PM1/17/14
to ansible...@googlegroups.com, AmiableAlbion
include_vars is a module that should be executed under a 'tasks' section.

What I believe you are looking for is vars_files.

-- 
Matt Martz
ma...@sivel.net
--
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.
To post to this group, send email to ansible...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

AmiableAlbion

unread,
Jan 17, 2014, 12:34:59 PM1/17/14
to ansible...@googlegroups.com, AmiableAlbion
Thanks Matt, overlooked that obvious detail (need more coffee).

So, following the vars_files documentation I am still struggling. 

vars/main.yml
vars_files:
 - imagenames.yml

vars/imagenames.yml
centos64: 52225cb3-441b-47b6-9cca-deb14d24d72f

> ansible-playbook vm.yml

PLAY [admin-vm] ***************************************************************

TASK: [provision | Creating virtual machine instances] ************************
fatal: [10.0.0.6] => One or more undefined variables: 'centos64' is undefined

FATAL: all hosts have already failed -- aborting

PLAY RECAP ********************************************************************
           to retry, use: --limit @/root/vm.retry

10.0.0.6                   : ok=0    changed=0    unreachable=1    failed=0


I have tried using a relative and absolute paths to imagenames.yml with no luck. 

Thanks
Albion

Matt Martz

unread,
Jan 17, 2014, 12:48:44 PM1/17/14
to ansible...@googlegroups.com, AmiableAlbion, AmiableAlbion
I think I overlooked something in your initial email.

vars_files is usable from within a playbook, not from within a vars file.  In your playbook just specify all of the vars files you want to include.

Something like:

---
- name: admin-vm
  hosts: AdminVM
  vars_files:
    - vars/main.yml
    - vars/imagenames.yml
  roles:
    - role: provision

You may be able to use the jinja2 include functionality to basically include other files into your main.yml, but I have never tried it.  Probably best just to be more explicit and verbose in your playbook.
-- 
Matt Martz
ma...@sivel.net

Albion Baucom

unread,
Jan 17, 2014, 1:20:08 PM1/17/14
to Matt Martz, ansible-project
Thanks Matt, that works for me.

Best,
Albion
--
Albion Baucom
gRED IT Support
Pharma Informatics

kesten broughton

unread,
Jan 19, 2014, 11:00:10 AM1/19/14
to ansible...@googlegroups.com
Another approach that is working for me is to pass in a vars file that points to all the other vars files that you may need that change from run to run.

ansible-playbook -i hosts site.yml -e "@cluster_config.yml"

The use case is for creating clusters of hadoop based apps that have a high degree of configuration for various environments.
I find ansible's variables architecture ideal for setting up a situation that is more or less the same from run to run.
But when you have network variables that change from one datacenter to the next, or a cluster configuration that depends on staging/prod/dev
I find In need a more robust and de-coupled way of passing in re-usable but swappable configs.
Note that you could do this by putting all the vars into a group_vars/cluster_name.yml but then you have to get creative with groups or lose the re-usability of components that can be shared between groups.

Here's how i do it.

cluster_cards/deployment_name/cluster_config.yml  in my ansible playbook directory contains
network_config: "path to networking details for deployment"
hadoop_config: "path to architecture of hadoop cluster"
environment_config: "path to file with specific dev/prod config stuff"

Then in site.yml (or a tasks file with include_vars: )
 - hosts: hadoop_cluster
   vars_files:
     - ["{{network_config}}]
     - ["{{environment_config}}]
     - ["{{hadoop_config}}]

deployment1/network_config_1.yml
                   /environment_config.yml
deployment2/network_config_2.yml

                   /
shared/small_hadoop_cluster.yml
          /medium_hadoop_cluster.yml

I still use the ansible hierarchy of vars for less variable/configurable constants, but this has worked well for me

kesten

Michael DeHaan

unread,
Jan 19, 2014, 3:29:17 PM1/19/14
to ansible...@googlegroups.com
I'd find that above a bit of an anti-pattern. 

If you want to include multiple files and have that role associated versus play associated, the best way to do this is to use the "include_vars" module inside a task file.

There's an open RFE to include every file in "vars/" automatically with "main" coming first, but I'm thinking we're likely to close that idea entirely -- as conditional includes are useful things.





--
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.
To post to this group, send email to ansible...@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/

kesten broughton

unread,
Jan 20, 2014, 6:33:43 PM1/20/14
to ansible...@googlegroups.com


On Sunday, January 19, 2014 2:29:17 PM UTC-6, Michael DeHaan wrote:
I'd find that above a bit of an anti-pattern. 

If you want to include multiple files and have that role associated versus play associated, the best way to do this is to use the "include_vars" module inside a task file.

There's an open RFE to include every file in "vars/" automatically with "main" coming first, but I'm thinking we're likely to close that idea entirely -- as conditional includes are useful things.


 
I had most of the items using include_vars to begin with, but I make heavy use of --start-at-task while developing scripts / debugging.
   It would be nice if include_vars at the top of the file would get loaded even when starting at a task below that.
   It's hard to imagine a case where that would be bad.

Michael DeHaan

unread,
Jan 20, 2014, 7:01:49 PM1/20/14
to ansible...@googlegroups.com
"   It would be nice if include_vars at the top of the file would get loaded even when starting at a task below that."

If include vars is below a task they are definitely injected into the namespace by the time a task below it is executed.

If you mean you want to write include vars after a task apply to a task before, this can't happen, because the path may be derived from a registered variable or a call to a custom fact module, etc.


Albion Baucom

unread,
Jan 21, 2014, 1:38:21 PM1/21/14
to ansible-project
I wanted to jump back into this conversation. It has been interesting.

I did like Kesten's use of command line variables, but it looks like it is a better practice to have conditional inclusion of variables that are specific to a particular use of a role if I read this right. 

We certainly have use cases like Kesten's where I want to reuse a role but change variables. For instance, using the Nova compute module in a role to provision, it is ideal to have flexible variables to define the users OpenStack environment and project details like image IDs, security groups and other user specific configurations.

The ability to include variable files via the main in the "vars/" directory of a role seems it would be an improvement, and would be more consistent with the behavior of "tasks/", but perhaps there is a specific reason this was not implemented from the get-go.


--
You received this message because you are subscribed to a topic in the Google Groups "Ansible Project" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ansible-project/LgiQ6CRHRCY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ansible-proje...@googlegroups.com.

To post to this group, send email to ansible...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--

Michael DeHaan

unread,
Jan 21, 2014, 1:43:21 PM1/21/14
to ansible...@googlegroups.com
"The ability to include variable files via the main in the "vars/" directory of a role seems it would be an improvement, "

It wouldn't, and it provides a bit too much of a "more than seven ways to do this" kind of thing.

If something in variables is defining a block of variables, having an "include" in the middle of the data means you're now defining a way that a datastructure can reference other data structures by naming specific files that they are in, and how do you distinguish a valid datastructure with a key named "include:" versus the desire to include?

It muddles semantics.

include_vars is going to be the way we are going to do this for multiple files.



Brian Coca

unread,
Jan 21, 2014, 1:43:43 PM1/21/14
to ansible...@googlegroups.com
 vars files are pure YAML, there is no inclusion mechanism in YAML which is what parses these files.

playbooks or tasks/main.yml are YAML files in 'ansible format' and are parsed by ansible, which has include directives.

Albion Baucom

unread,
Jan 21, 2014, 1:53:15 PM1/21/14
to ansible-project
Then help me understand how this is any different than includes in a main task file?

There could be a block of tasks, with an include in the middle. Also that means the behavior is inconsistent across the role sub-systems. What did I do when I wanted to break out variables and organize them logically in my vars/main.yml? I followed the logic in tasks/main.yml to break out tasks.

Its fine. As this thread is demonstrating, there are already a number of ways to do this. From a user perspective what I suggested makes sense to me, but perhaps I should fall in-line with semantics.

Albion Baucom

unread,
Jan 21, 2014, 1:56:35 PM1/21/14
to ansible-project
OK, well this makes more sense from an implementation perspective. 

I was under the impression that Ansible was using pure YAML throughout, but shows how well I understand the language currently :)


On Tue, Jan 21, 2014 at 10:43 AM, Brian Coca <bria...@gmail.com> wrote:
 vars files are pure YAML, there is no inclusion mechanism in YAML which is what parses these files.

playbooks or tasks/main.yml are YAML files in 'ansible format' and are parsed by ansible, which has include directives.

--
You received this message because you are subscribed to a topic in the Google Groups "Ansible Project" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ansible-project/LgiQ6CRHRCY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Brian Coca

unread,
Jan 21, 2014, 3:26:49 PM1/21/14
to ansible...@googlegroups.com
ansible playbook/task files ARE YAML, but they get processed a 2nd time with the ansible engine, vars/files do not, they only get processed by YAML, they were just meant to be static data files.
Reply all
Reply to author
Forward
0 new messages