Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Taking a csv list and iterating through it with a sequence

I have a playbook which takes a input list of comma-separated values from the user:

a,b,c,d

And turns it into a list using split (extra_hosts is the variable that stores the input from the user)

- name: Generate hosts list
  set_fact:
    hosts_list: []

- name: Build hosts list
  set_fact:
    san_list: "{{ hosts_list + [host] }}"
  loop_control:
    loop_var: host
  with_items: "{{ extra_hosts | split(',') }}"

Now this works fine so far. If I debug at this point, I get:

ok: [localhost] => {
    "msg": [
        "a",
        "b",
        "c",
        "d"
    ]
}

What I want to do now is to output into a file, the list in the format:

Host 1: a
Host 2: b
Host 3: c
Host 4: d

I can easily iterate over the list and output using this:

- name: Append hosts to file
  lineinfile:
    path: "hosts.conf"
    line: "Host: {{ host }}"
  loop_control:
    loop_var: host
  with_items: "{{ hosts_list }}"

However, this outputs (obviously) as:

Host: a
Host: b
Host: c
Host: d

But I don't think I can iterate with two variables (the second being the sequence module), so I can't do something like:

- name: Append hosts to file
  lineinfile:
    path: "hosts.conf"
    line: "Host: {{ host }}"
  loop_control:
    loop_var: host
  with_items: "{{ hosts_list }}"
  loop_control:
    loop_var: id
  with_sequence: start=1

I was thinking maybe somehow converting the list into a dict, so I'd end up with something like:

{id: 1, host: "a"},
{id: 2, host: "b"},
{id: 3, host: "c"},
{id: 4, host: "d"}

Then I can then just use something like {{ item.id }} and {{ item.host }} to write those out -- but to build the dict, I would still need to iterate with two pointers -- an incremental value, and the pointer within the list.

Is there way I can do this, and what is the best/correct way of doing it?

like image 364
Blender Fox Avatar asked Dec 19 '25 21:12

Blender Fox


2 Answers

For example, the task below will be skipped if extra_hosts is not defined

    - copy:
        dest: hosts.conf
        content: |-
          {% for i in extra_hosts.split(',') %}
          Host {{ loop.index }}: {{ i }}
          {% endfor %}
      when: extra_hosts|d('')|length > 0

If the variable extra_hosts is defined (e.g. -e extra_hosts='a,b,c,d') the task will create the file hosts.conf

shell> cat hosts.conf 
Host 1: a
Host 2: b
Host 3: c
Host 4: d
like image 106
Vladimir Botka Avatar answered Dec 22 '25 10:12

Vladimir Botka


Regarding your question

... the list in the format ...

you may take advantage from Extended loop variables.

---
- hosts: localhost
  become: no
  gather_facts: no

  vars:

   LIST: ['a', 'b', 'c', 'd']

  tasks:

  - name: Show result
    debug:
      msg: "Host {{ ansible_loop.index }}: {{ LIST[ansible_loop.index0] }}"
    loop: "{{ LIST }}"
    loop_control:
      label: "{{ item }}"
      extended: yes

results into an output of

TASK [Show result] ***********
ok: [localhost] => (item=a) =>
  msg: 'Host 1: a'
ok: [localhost] => (item=b) =>
  msg: 'Host 2: b'
ok: [localhost] => (item=c) =>
  msg: 'Host 3: c'
ok: [localhost] => (item=d) =>
  msg: 'Host 4: d'
like image 25
U880D Avatar answered Dec 22 '25 10:12

U880D



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!