Looping through a register variable

41 views
Skip to first unread message

Dimitri Yioulos

unread,
May 23, 2024, 9:07:37 AMMay 23
to Ansible Project
Good day, all. I hope I'm not wearing out my welcome with too many questions.

In the following playbook, I first find any know_host file for any user on a particular system. I then copy a file with the list of additions to add to the known_hosts files. What I want to do is use the output of my register values to make changes to those know_host files, which my last play does. My iteration is wrong, though.

The playbook:

---

- hosts: all
  gather_facts: false
  become: yes

  vars:
    script_path: <script>

  tasks:

    - name: Find known hosts
      shell: find /root /home -type f -name known_hosts
      register: known

    - name: Debug known_hosts paths
      debug:
        msg: "{{ known.stdout }}"

    - name: Set fact with known_hosts paths
      set_fact:
        known_hosts_paths: "{{ known.stdout_lines }}"

    - name: Upload entries for new known_hosts svn
      copy:
        src: append
        dest: /tmp/append
        owner: root
        group: root
        mode: u=rwx,g=rw,o=rw

    - name: Append to all known_host files
      shell: cat /tmp/append >> {{ item }}
      loop:
        - '{{ known.stdout }}'


The output of the first play:

ok: [myhost] =>
  msg: |-
    /root/.ssh/known_hosts
    /home/user1/.ssh/known_hosts
    /home/ user2/.ssh/known_hosts
    /home/ user3/.ssh/known_hosts
    /home/ user4/.ssh/known_hosts


How do I make that last play work?

Todd Lewis

unread,
May 23, 2024, 10:50:28 AMMay 23
to ansible...@googlegroups.com, uto...@gmail.com
You want stdout_lines rather than stdout. The former is a list with new-lines removed. The latter is a possibly very long string with the complete output stream intact.
    - name: Append to all known_host files
      shell: cat /tmp/append >> {{ item }}
      loop:
        - '{{ known.stdout_lines }}'
How do I make that last play work? --
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 view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/84e78306-66cf-4d86-8b45-d1c4816c598en%40googlegroups.com.

-- 
Todd

Dimitri Yioulos

unread,
May 23, 2024, 11:17:15 AMMay 23
to Ansible Project
Todd, I made the change, but, the last play failed:

TASK [Append to all known_host files] *****************************************************************************************************
Thursday 23 May 2024  11:06:33 -0400 (0:00:01.629)       0:00:06.012 **********
Thursday 23 May 2024  11:06:33 -0400 (0:00:01.629)       0:00:06.011 **********
failed: [myhost] (item=['/root/.ssh/known_hosts', '/home/user1/.ssh/known_hosts', '/home/user2/.ssh/known_hosts', '/home/user3/.ssh/known_hosts', '/home/user4/.ssh/known_hosts']) => changed=true
  ansible_loop_var: item
  cmd: cat /tmp/append >> ['/root/.ssh/known_hosts', '/home/user1/.ssh/known_hosts', '/home/user2/.ssh/known_hosts', '/home/user3/.ssh/known_hosts', '/home/user4/.ssh/known_hosts']
  delta: '0:00:00.012330'
  end: '2024-05-23 11:06:33.947617'
  item:
  - /root/.ssh/known_hosts
  - /home/user1/.ssh/known_hosts
  - /home/user2/.ssh/known_hosts
  - /home/user3/.ssh/known_hosts
  - /home/user4/.ssh/known_hosts
  msg: non-zero return code
  rc: 1
  start: '2024-05-23 11:06:33.935287'
  stderr: '/bin/sh: line 1: [/root/.ssh/known_hosts,: No such file or directory'
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>


I wonder if [ in  [/root/.ssh/known_hosts is getting in the way, since  /root/.ssh/known_host does exist.

Todd Lewis

unread,
May 23, 2024, 11:30:33 AMMay 23
to ansible...@googlegroups.com, uto...@gmail.com
Gah! Of course. known.stdout_lines is a list, so
loop:
  - '{{ known.stdout_lines }}'
passes the whole list as a single item. So you need to not put the list in a list:
loop: '{{ known.stdout_lines }}'
should do the trick.

Todd

Dimitri Yioulos

unread,
May 23, 2024, 5:00:36 PMMay 23
to Ansible Project
Yupper, that worked. And, I appreciate the explanation. As the Farber College motto states, "Learning is Good".

Dick Visser

unread,
May 23, 2024, 11:10:22 PMMay 23
to ansible...@googlegroups.com


Sent from Gmail Mobile


On Thu, May 23, 2024 at 16:50 Todd Lewis <uto...@gmail.com> wrote:
You want stdout_lines rather than stdout. The former is a list with new-lines removed. The latter is a possibly very long string with the complete output stream intact.
    - name: Append to all known_host files
      shell: cat /tmp/append >> {{ item }}
      loop:
        - '{{ known.stdout_lines }}'

That should probably just loop over the list itself? So:
    - name: Append to all known_host files
      shell: cat /tmp/append >> {{ item }}
      loop: '{{ known.stdout_lines }}'







Rowe, Walter P. (Fed)

unread,
May 28, 2024, 5:41:55 AMMay 28
to 'Rowe, Walter P. (Fed)' via Ansible Project
Here is an illustration of the difference for those interested.


- name: test loop constructs

  hosts: localhost

  gather_facts: false

  become: false

  vars:

    my_list: [ one, two, three ]

  tasks:

    - name: construct 1

      debug: var=item

      loop:

        - '{{ my_list }}'


    - name: construct 2

      debug: var=item

      loop: '{{ my_list }}'





% ansible-playbook -i localhost, loop.yml


PLAY [test loop constructs] ********************************************************************************************


TASK [construct 1] *****************************************************************************************************

ok: [localhost] => (item=['one', 'two', 'three']) => {

    "ansible_loop_var": "item",

    "item": [

        "one",

        "two",

        "three"

    ]

}


TASK [construct 2] *****************************************************************************************************

ok: [localhost] => (item=one) => {

    "ansible_loop_var": "item",

    "item": "one"

}

ok: [localhost] => (item=two) => {

    "ansible_loop_var": "item",

    "item": "two"

}

ok: [localhost] => (item=three) => {

    "ansible_loop_var": "item",

    "item": "three"

}


PLAY RECAP *************************************************************************************************************

localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   




Walter
--
Walter Rowe, Division Chief
Infrastructure Services Division
Mobile: 202.355.4123

On May 24, 2024, at 7:41 AM, Rowe, Walter P. (Fed) <walte...@nist.gov> wrote:

Very subtle but very different. Great catch Todd.

In the first instance you create a list that contains a single item – another list called known.stdout_lines.

loop:
  - '{{ known.stdout_lines
 }}'

In the second instance you provide a list called known.stdout_lines as the list for the loop:

loop: '{{ known.stdout_lines }}'

The second instance is the desired behavior. The difference is subtle at first glance but makes a world of difference in execution.

Walter
--
Walter Rowe, Division Chief
Infrastructure Services Division
Mobile: 202.355.4123

Rowe, Walter P. (Fed)

unread,
May 28, 2024, 5:41:58 AMMay 28
to 'Rowe, Walter P. (Fed)' via Ansible Project
Very subtle but very different. Great catch Todd.

In the first instance you create a list that contains a single item – another list called known.stdout_lines.

loop:
  - '{{ known.stdout_lines
 }}'

In the second instance you provide a list called known.stdout_lines as the list for the loop:

loop: '{{ known.stdout_lines }}'

The second instance is the desired behavior. The difference is subtle at first glance but makes a world of difference in execution.

Walter
--
Walter Rowe, Division Chief
Infrastructure Services Division
Mobile: 202.355.4123
On May 23, 2024, at 11:30 AM, Todd Lewis <uto...@gmail.com> wrote:

Reply all
Reply to author
Forward
0 new messages