Dynamic list of items created on remote side

And again I have a non-typical use case.

How would you approach such task? I have some servers on which there is a piece of software running that's not configured by me and thus I can't control the configuration with ansible. But I need to be able to make sure that for every entry in its configuration I make sure that something is done on the host.

For example (this is not this case; just for explanation what I mean) - someone else is responsible for creating users on the machine (or the users are created remotely and authenticated and authorized using pam_ldap and nss_ldap for example) and I can list them with gentent. I need to make sure that for each user I have a directory created on a host.

That would involve running a command on the remote host side (in our case - getent) to get an output, and then iterating over this output to make sure the directories are created.

Of course I could just do a remote command and do a script to be run on the remote side but it kinda defeats the purpose of having ansible in the first place.

Any better ideas?

Hmm... maybe doing a remote command, registering output and then looping a task over it? I'm not sure though how to split the result that I register in a variable into single lines.

Ansible (and related software) helps you to ensure a system status that is defined by the tasks you run for that host,
so ideally it works also when the installation and configuration isn't performed by Ansible.

I think it is a good idea to use Ansible modules whenever possible, and only fallback to commmand and shell (use that
only at last resort) if not.

But it would be good if you describe concrete case we can help you with.

Regards
         Racke

Sure, I understand. Sometimes the business however begs to differ :wink:
In this case it’s just that some part of the solution (the OS-level) is managed by me, and higher up on this the customer builds his own solution. I can’t force him to do his work this way or another.
Of course I can write a script that will manually connect to each server and checks something - and based on this does something else but using Ansible saves me a lot of hassle, mostly in the “connecting” part (sometimes I have to use a jumphost, sometimes I have to log in using one set of credentials, sometimes - another, and so on).
So yes, I understand that I’m trying to use Ansible here a bit not for what it is meant for but hey, if it works, then why not :wink:
And more to the point, after some digging I believe that if I do a command and register output in a variable (let’s say it’s called output_var), I can then loop another variable over output_var.stdout_lines. I still need to test it but it seems that it’s pretty much what I want.
For example (don’t get attached to what it does; it’s just what I need in terms of interaction between those two actions):

  • name: getusers
    shell: “getent passwd | grep /home/remote | cut -d : -f 1”
    register: remoteusers

  • name: touchy
    file:

path: ‘/tmp/{{item}}’
state: touch
owner: ‘{{item}}’

loop: {{remoteusers.stdout_lines}}

Sure, I understand. Sometimes the business however begs to differ :wink:
In this case it's just that some part of the solution (the OS-level) is managed by me, and higher up on this the
customer builds his own solution. I can't force him to do his work this way or another.
Of course I can write a script that will manually connect to each server and checks something - and based on this does
something else but using Ansible saves me a lot of hassle, mostly in the "connecting" part (sometimes I have to use a
jumphost, sometimes I have to log in using one set of credentials, sometimes - another, and so on).
So yes, I understand that I'm trying to use Ansible here a bit not for what it is meant for but hey, if it works, then
why not :wink:
And more to the point, after some digging I believe that if I do a command and register output in a variable (let's say
it's called output_var), I can then loop another variable over output_var.stdout_lines. I still need to test it but it
seems that it's pretty much what I want.
For example (don't get attached to what it does; it's just what I need in terms of interaction between those two actions):

 \- name: getusers
    shell: "getent passwd | grep /home/remote | cut \-d : \-f 1"
    register: remoteusers

  \- name: touchy
     file:
        path: '/tmp/\{\{item\}\}'
        state: touch
        owner: '\{\{item\}\}'
      loop: \{\{remoteusers\.stdout\_lines\}\}

Use getent module instead of the shell (remember that's the last resort):

    - name: Retrieve user information
      getent:
        database: passwd
        split: ':'

The logic used by this module for its result is a bit strange compared to others.
It stores the output in the variable "getent_passwd" (when using "passwd" database).

getent_passwd is a dictionary, sample entry looks like:

  sympa:
    - x
    - '1001'
    - '1001'
    - ''
    - /home/sympa
    - /bin/bash

The home directory at position 5, so you can retrieve it with "{{ getent_passwd['sympa'][4] }}".

In order to convert the dict "getent_passwd" to a list which only contains home directories matching /home/remote as
grep does:

  - set_fact:
      users: "{{ users | default() + [item.key] }}"
    when: item.value[4] is search('/home/remote')
    with_dict: "{{ getent_passwd }}"

Regards
          Racke

Good to know about the getent module. Thx.

Still it's not about this module as such. As I wrote, it's not about what the example does, but how one action relies on the output from another. But it seems that stdout_lines should be what I need. For some reason I somehow expected ansible to be able only to ingest an output from a command as a whole, not line by line.

For example (don't get attached to what it does; it's just what I need in terms of interaction between those two
actions):

  \- name: getusers
     shell: "getent passwd | grep /home/remote | cut \-d : \-f 1"
     register: remoteusers

   \- name: touchy
      file:
         path: '/tmp/\{\{item\}\}'
         state: touch
         owner: '\{\{item\}\}'
       loop: \{\{remoteusers\.stdout\_lines\}\}

Use getent module instead of the shell (remember that's the last resort):

 \- name: Retrieve user information
   getent:
     database: passwd
     split: ':'

Good to know about the getent module. Thx.

Still it's not about this module as such.

As I wrote, it's not about what the example does, but how one action relies on

Yes, I understood that but I think it is a nice example for using getent and transforming information
regardless :-).

the output from another. But it seems that stdout_lines should be what I need. For some reason I somehow expected
ansible to be able only to ingest an output from a command as a whole, not line by line.

It does, check out stdout instead of stdout_lines.

Regards
         Racke