dahiya_boy
dahiya_boy

Reputation: 9503

How to use ansible loop

Variable file

I have a variable file

fruits:
  - apple
  - banana
  - orange
  - strawberry
  - grapes
  - papaya

users:
  - user_name: 'john'
    user_age: 45
  - user_name: 'yash'
    user_age: 95
  - user_name: 'srk'
    user_age: 52
  - user_name: 'alia'
    user_age: 26

Playbook Tasks

and my ansible tasks, just trying to make a text file and adding variables in file in vertical order.

- hosts: localhost
  gather_facts: true
  vars_files:
    - variables.var # this is my variable file in the same dir that playbook have.
  tasks:
    - name: add fruits to the list
      lineinfile:
        create: yes
        line: "{{ item }}"
        path: /home/ansible/ansible-demo2/fruits.txt
      loop:
        - "{{ fruits|flatten }}"

    - name: add uses to the list
      lineinfile:
        create: yes
        line: "{{ item.user_name }} ==> {{ item.user_age }}"
        path: /home/ansible/ansible-demo2/users.txt
      loop:
        - "{{ users|flatten(levels=1) }}"

Errors

But I am getting weird behavior. Below is the output of fruits task and error of the users task.

TASK [add fruits to the list] ***************************************************************************************************************************
ok: [localhost] => (item=[u'apple', u'banana', u'orange', u'strawberry', u'grapes', u'papaya'])
[WARNING]: The value ['apple', 'banana', 'orange', 'strawberry', 'grapes', 'papaya'] (type list) in a string field was converted to u"['apple',
'banana', 'orange', 'strawberry', 'grapes', 'papaya']" (type string). If this does not look like what you expect, quote the entire value to ensure it
does not change.

TASK [add uses to the list] *****************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'user_name'
\n\nThe error appears to be in '/home/ansible/ansible-demo2/myansible.yml': line 18, column 7, but may\nbe elsewhere in the file depending on the exact s
yntax problem.\n\nThe offending line appears to be:\n\n\n    - name: add uses to the list\n      ^ here\n"}

Expected Output

List in vertical order in text file.

Comment on question:

I am amazed every thing works fine with with_items and not with loop, even user_name variable is defined but still it is saying undefined. Now I unable to find out what's wrong going on.

Reference:

Here is the doc that I am referencing : Migrating from with_X to loop

Edit: Variables debug output

I debug the variables. output is below

TASK [debug] ********************************************************************************************************************************************
ok: [localhost] => {
    "fruits": [
        "apple",
        "banana",
        "orange",
        "strawberry",        "grapes",        "papaya"
    ]
}

TASK [debug] ********************************************************************************************************************************************
ok: [localhost] => {
    "users": [
        {
            "user_age": 45,
            "user_name": "john"
        },
        {
            "user_age": 95,
            "user_name": "yash"
        },
        {
            "user_age": 52,
            "user_name": "srk"
        },
        {
            "user_age": 26,
            "user_name": "alia"
        }
    ]
}

Upvotes: 3

Views: 491

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68034

Q: *"[WARNING]: The value ['apple', ... ] (type list) in a string field was converted to u"['apple', ... ]" (type string).

A: From the code, it's not clear what is the reason for this conversion. The data and the playbook below work as expected.

shell> cat data.yml
fruits:
  - apple
  - banana
  - orange
  - strawberry
  - grapes
  - papaya

users:
  - user_name: 'john'
    user_age: 45
  - user_name: 'yash'
    user_age: 95
  - user_name: 'srk'
    user_age: 52
  - user_name: 'alia'
    user_age: 26
shell> cat playbook.yml
- hosts: localhost
  vars_files:
    - data.yml
  tasks:
    - name: add fruits to the list
      lineinfile:
        create: yes
        line: "{{ item }}"
        path: fruits.txt
      loop: "{{ fruits }}"

    - name: add uses to the list
      lineinfile:
        create: yes
        line: "{{ item.user_name }} ==> {{ item.user_age }}"
        path: users.txt
      loop: "{{ users }}"

Give

shell> cat fruits.txt 
apple
banana
orange
strawberry
grapes
papaya
shell> cat users.txt 
john ==> 45
yash ==> 95
srk ==> 52
alia ==> 26

Q: "2 variables fruits1 and fruits2 ... append their data into single file ... in single task with 2 vars"

A: With the modified data

shell> cat data.yml
fruits1:
  - apple
  - banana
  - orange

fruits2:
  - strawberry
  - grapes
  - papaya

this task gives the same result

    - name: add fruits to the list
      lineinfile:
        create: yes
        line: "{{ item }}"
        path: fruits.txt
      loop: "{{ fruits1 + fruits2 }}"

See Append list variable to another list in Ansible.


Comment on the question: "I am amazed everything works fine with with_items and not with loop"

A: See Comparing loop and with_*.

Upvotes: 3

Related Questions