Mickster
Mickster

Reputation: 683

Building a list with ansible

I have a group with a large list of systems and need to grab the first 3 systems from the group. Is there a way to take a group such as this:

[webservers]
web01
web02
web03
web04
web05

And produce a quoted list similar to the following?:

- name: Pick the initial masters
  lineinfile:
    dest: "/bits/etc/web.conf"
    state: present
    regexp: 'node.masters'
    line: 'node.masters: [ "web01", "web02", "web03" ]'

I may need to change the number of masters in the future so I'm hoping to use a slice if at all possible. Thanks for any insight.

Upvotes: 2

Views: 1000

Answers (2)

LHSnow
LHSnow

Reputation: 1266

You can use the python array slice syntax and pipe it to the json filter. This will avoid looping in Jinja2 and produce nice quoted output.

- name: Pick the initial masters
  lineinfile:
    dest: /bits/etc/web.conf
    state: present
    regexp: 'node.masters'
    line: 'node.masters: {{groups['webservers'][:3] | to_json}}'

Be careful with slices of groups, as the order is not necessarily consistent if the inventory is dynamically generated, as stated in the Ansible FAQ. To avoid this, I would advice on creating a second group, "masters" in the inventory, specifying which nodes to use rather than relying on order. This has other benefits, such as being able to target the masters or non-masters instead of having to know and change the number of masters in every playbook.

[webservers]
web[01:05]

[masters]
web[01:03]

Upvotes: 2

kfreezy
kfreezy

Reputation: 1579

You can reference the built-in groups variable.

- name: Pick the initial masters
  lineinfile:
    dest: "/bits/etc/web.conf"
    state: present
    regexp: 'node.masters'
    line: "node.masters: [ \"{{ groups['webservers'][0] }}\", \"{{ groups['webservers'][1] }}\", \"{{ groups['webservers'][2] }}\" ]"

Updated answer from comments:

You could also use jinja in your variable declarations to loop over an arbitrary number of hosts in webservers.

vars: 
  master_nodes: 3
  master_nodes_line: "{% for item in groups['webservers'][:master_nodes] %}\"{{ item }}\"{% if not loop.last %},{% endif %}{% endfor %}"
tasks:
- name: Print list
  lineinfile:
    dest: foo
    regexp: "node.masters"
    line: "node.masters: [ {{ master_nodes_line }} ]"

Upvotes: 2

Related Questions