traversing directory structure

hello,

let’s look at the following structure:var/
ssh/
user1
user2
user3

hosts/
host1/
user1
user3

host2/
user2
user3

under /var/ssh there are public keys for users

files under host1,host2 catalog are empty files just pointing ansible on which host which user must be added

i did the task by reading the hosts/ one level into an array, then looping over it
like:

hosts: localhost
tasks:

  • name: get hosts from hosts directory
    command: ls -1 var/hosts
    register: ssh_hosts

  • name: set ssh_hosts_fact
    set_fact:
    ssh_hosts_fact: “{{ ssh_hosts.stdout_lines }}”

  • name: include subtasks
    include: ssh_body.yml host=“{{ item }}”
    with_items:

  • “{{ ssh_hosts_fact }}”

then
in included file:

  • name: get usernames for host
    command: ls -1 var/hosts/{{ host }}
    register: usernames_host

  • name: add users onto host
    user:
    name: “{{ user_item }}”
    shell: /bin/bash
    group: sudo
    with_items:
    “{{ usernames_host.stdout_lines }}”
    delegate_to: “{{ host }}”
    loop_control:
    loop_var: user_item
    become: true

  • name: add user keys
    authorized_key:
    user: “{{ user_item }}”
    key: “{{ lookup(‘file’, ‘var/ssh/{{ user_item }}’ ) }}”
    with_items:
    “{{ usernames_host.stdout_lines }}”
    delegate_to: “{{ host }}”
    loop_control:
    loop_var: user_item
    become: true

it works, but I think there is more effective way of doing thing, at least with no includes
any suggestions?

thank you

hello,

let's look at the following structure:
var/
  ssh/
   user1
   user2
   user3

  hosts/
   host1/
    user1
    user3
   
  host2/
   user2
   user3

under /var/ssh there are public keys for users

files under host1,host2 catalog are empty files just pointing ansible on
which host which user must be added

Short answer: Below is the playbook that you probably want.

  - hosts: localhost
    tasks:
    - name: get hosts from hosts directory
      command: ls -1 var/hosts
      register: ssh_hosts
    - name: create my_group
      add_host:
        hostname: "{{ item }}"
        groups:
          - 'my_group'
      loop: "{{ ssh_hosts.stdout_lines }}"

  - hosts: my_group
    become: true
    tasks:
      - name: get usernames
        command: "ls -1 var/hosts/{{ inventory_hostname }}"
        register: usernames_host
      - name: add users
        user:
          name: "{{ item }}"
          shell: /bin/bash
          group: sudo
        loop: "{{ usernames_host.stdout_lines }}"
      - name: add user keys
        authorized_key:
          user: "{{ item }}"
          key: "{{ lookup('file', 'var/ssh/' ~ item ) }}"
        loop: "{{ usernames_host.stdout_lines }}"

Details:

Create a group "my_group" instead of variable "ssh_hosts_fact"

    - name: create my_group
      add_host:
        hostname: "{{ item }}"
        groups:
          - 'my_group'
      loop: "{{ ssh_hosts.stdout_lines }}"

  - name: set ssh_hosts_fact
    set_fact:
      ssh_hosts_fact: "{{ ssh_hosts.stdout_lines }}"

Start another play with the group "my_group" instead of the "include". No
delegation and loop_control is needed.

  - hosts: my_group
    become: true
    tasks:

  - name: include subtasks
    include: ssh_body.yml host="{{ item }}"
    with_items:
      - "{{ ssh_hosts_fact }}"

Cheers,

  -vlado