How specify a list value as variable in ansible inventory file?
Asked Answered
S

7

63

I need something like (ansible inventory file):

[example]
127.0.0.1 timezone="Europe/Amsterdam" locales="en_US","nl_NL"

However, ansible does not recognize 'locales' as a list.

Seaton answered 2/9, 2013 at 11:24 Comment(0)
B
108

You can pass a list or object like this:

[example]
127.0.0.1 timezone="Europe/Amsterdam" locales='["en_US", "nl_NL"]'
Brought answered 20/3, 2015 at 20:3 Comment(8)
@ryanyuyu It not only is not the same code as in the question, it as well is the exact solution the OP was looking for. Have you tested it? Ryler did, so did I: And it works. This should be the accepted answer and not downvoted.Relent
Yep, can also confirm that this works. This is good for using with a "with_items" statement for example. You can even create dict-like objects like this. I use this for defining nginx authentication users and passwords in an inventory file: nginx_auth='[ {"user": "user1", "pass": "pass1"}, {"user": "user2", "pass": "pass2"}]'Polyunsaturated
Is this the neatest possible solution for ini files? What if you have 20+ items and 5 hosts to configure it with? Would be happy to know but this works for now.Graycegrayheaded
@WillHarris can you also put multiple items in one key? For example: {"user":["user1","user2"]}?Graycegrayheaded
@Graycegrayheaded Depends on how you want to process the value. In my example I'd use with_items: nginx_auth and then access as {{item.user}} and {{item.pass}}. With your example I don't see any natural way to iterate over your value-list within the context where with_items would be used. Perhaps you could use a Jinja2 filter to do additional "list" processing in a template.Polyunsaturated
@WillHarris I'm not sure how to achieve it with Jinja2 isn't that just for templating purposes? Here is what I want to achieve specifically.Graycegrayheaded
IMPORANT NOTE: This is correct in context, but doesn't work for other variations. I've added an answer with the results of my experiments.Fishbein
Ah, turns out it's just the template module that breaks most variations.Fishbein
G
34

With complex variables, it's best to define them in a host_vars file rather than in the inventory file, since host_vars files support YAML syntax.

Try creating a host_vars/127.0.0.1 file with the following content:

---
timezone: Europe/Amsterdam
locales:
  - en_US
  - nl_NL
Gualterio answered 2/9, 2013 at 21:34 Comment(5)
Thanks, that is my current way of working :) Does your answer implies you cannot specify a list variable in an inventory file (and --extra-vars)?Seaton
@Seaton I do not know if it's possible to specify list variables in ini files or on the command line. You'll probably get a quicker response if you ask on the ansible mailing list.Gualterio
@Seaton I'd also recommend jumping on the #ansible IRC channel, the guys there are normally quick to help :-)Trencher
I don't think it's possible in inventory. I tried xyz= with a dash-prefixed list below, and I got the error "ERROR: variables assigned to group must be in key=value form".Inhume
I also thought of using this but it's a tedious approach. Especially if you have a lot of sites to configure.Graycegrayheaded
F
20

Ryler's answer is good in this specific case but I ran into problems using other variations with the template module.

[example]
127.0.0.1 timezone="Europe/Amsterdam" locales='["en_US", "nl_NL"]'

Is his original example and works fine.

The following variations work with template. Basically if it's a string you must remember to use the internal double quotes or the entire structure is parsed as a single string. If it's only numbers or "True" or "False" (not "yes") then you're fine. In this variation I couldn't make it work with template if it had external quotes.

I haven't done an exhaustive check of which internal use cases they do and do not break other than the template module.

I am using Ansible 2.2.1.

[example:vars]
# these work
myvar1=["foo", "bar"]
myvar2=[1,2]
myvar3=[True,False]

# These fail, they get interpreted as a single string.
myvar4=[yes, no]
myvar5=[foo,bar]
myvar6='["foo", "bar"]'
Fishbein answered 26/1, 2017 at 14:18 Comment(2)
This extra bit of info helped me troubleshoot an annoyingly arbitrary variable parsing issue. Thanks!Sheffy
A bit of extra info: I think the differences occur because of the different parsing routes. In a [group:vars] everything is passed directly as INI_PARSER->YAML_PARSER, including double quotes. So the YAML parser interprets it as a string. After a hostname it goes though a similar parser to the ones used with 'equals style' arguments to a module: INI_PARSER->ANSIBLE_ARG_PARSER->YAML_PARSER. In the latter case ANSIBLE_ARG_PARSER interprets the double quoted string and passes the content (without quotes) to the YAML parser.Fishbein
T
8

you can try split

#inventory file
[example]
127.0.0.1 timezone="Europe/Amsterdam" locales="en_US","nl_NL"

#role file
---
- debug: msg="{{ item }}"
  with_items: locales.split(',')
Tola answered 6/5, 2015 at 9:52 Comment(0)
D
0

I believe the case is where you define your variable.

if it is under a

[host:vars] var=["a", "b"]

otherwise:

[hosts] host1 var='["a", "b"]'

Dustindustman answered 29/1, 2021 at 12:19 Comment(0)
M
0

INI file with variables looks like this

$ cat ./vars/vars.yml

lvol_names=['2g-1','2g-2','2g-3']

the variable represents the list type

 lvol_names:
       - 2g-1
       - 2g-2
       - 2g-3

the variable can be read from a playbook via lookup:

$ cat ./play.yml

- name: play1
  hosts: kub2_data_nodes
  become: yes


  vars:
 
     - lvol_names: "{{ lookup('ini', 'lvol_names type=properties file=./vars/vars.yml') }}"
     
Mchale answered 3/7, 2021 at 22:26 Comment(0)
B
-2

You can custom a filter, to split string to list

Github ansible example show how to create custom filter.

Biramous answered 4/4, 2014 at 12:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.