Lookup plugins and complex data

Hi,

I’m quite new to Ansible, and I’ve been asking some questions on the IRC channel the past few days.

We have a lot of data in LDAP and other databases, which we would like to use in our Ansible plays (?). So I wrote a lookup plugin, but I’m stuck with how to iterate the data properly. Here’s a gist with both the plugin and a playbook I’ve used to test it: <https://gist.github.com/ptman/7599909>

Comments? Suggestions? Am I approaching this totally from the wrong angle?

Cheers,
Paul

Paul,

I've not done much LDAP in Python, but I'd like to comment on the plugin
anyway: I hope you don't mind. line numbers as per your gist:

26: I'd try/catch that import and fail cleanly if possible.
39: You seem to be getting base from naming contexts, but there can be
    several of those in a single directory server; are you sure this is
    valid for everybody? I.e.: what if my directory server has, say, 5
    naming contexts?
55: needs try/except to catch errors; same on line 68

I personally would have liked to see something like

        lookup('ldap', 'attributeType', 'value')

so
        lookup('ldap', 'paul', 'homedirectory')

maybe with several attribute types (comma/slash separated, best
something easy which doesn't clash with YAML?).

but I'm stuck > with how to iterate the data properly

Not a clue, sorry.

Regards,

        -JP

“I’m stuck with how to iterate the data properly”

Can you help me understand what this part of the question refers to?

I’ve not done much LDAP in Python, but I’d like to comment on the plugin
anyway: I hope you don’t mind. line numbers as per your gist:

Oh certainly, it isn’t meant to be finished or even for public consumption. Only for demonstrating the problems I run into.

Cheers,
Paul

Can you help me understand what this part of the question refers to?

Dealing with the ssh public keys.

I really would like to have ansible pick out the zero or more ssh public keys that a user has and deploy them without me having to specify the keys separately. Just specifying the users should be enough with powerful enough looping constructs. But I’m at a loss how to handle the looping of the data structure that I return from the lookup plugin.

Cheers,
Paul

“But I’m at a loss how to handle the looping of the data structure that I return from the lookup plugin.”

http://www.ansibleworks.com/docs/playbooks_loops.html

http://www.ansibleworks.com/docs/playbooks_loops.html

I have read the documentation. If you look at the example I posted, I’m even looping through the array returned by the lookup function. But I don’t know how to iterate the arrays it contains.

Would you please be so kind as to look at the example and give specific advice instead of general directions to the documentation?

Cheers,
Paul

Sorry for resurrecting such an old topic, but I’ve done other things with Ansible in the meantime and now returned to this. I’ve updated the gist to better reflect what I’m after (in test.yml): https://gist.github.com/ptman/7599909

Is it possible to either set the values of variables to dicts (not strings) based on lookup plugins or loop so that the nesting wouldn’t just explore an already existing complex variable but instead perform lookups (this is what I’ve tried to convey in the gist)?

Or do I need to write a vars plugin (how would I then limit the users for which the lookup is performed based on a variable in the playbook instead of providing the content of our whole directory to all hosts)? Writing vars plugins is clearly discouraged for a reason.

Maybe what’s needed is just a new looping construct, that is another layer of lookup plugins?

Hopefully the updated gist gets my original idea across better.

Cheers,
Paul

Sorry for resurrecting such an old topic, but I’ve done other things with Ansible in the meantime and now returned to this. I’ve updated the gist to better reflect what I’m after (in test.yml): https://gist.github.com/ptman/7599909

I was able to solve my problem with help and ideas from cmhamill on ansible@freenode. I’ve updated the gist to reflect my solution. Since ansible has no good way of iterating a list-of-dicts-with-list, I split the lookup plugin into two, which both return a list-of-dicts. This certainly gets the job done, but makes me feel underwhelmed. It would be nice to be able to handle more complex data structures in playbooks.

Another way to solve the problem would have been to get anything other than a stringified result when assigning from a lookup plugin to a var. I tried e.g.:

vars:
data: “{{ lookup(‘fileglob’, ‘/etc/*’) }}”

Now, I understand that templates return strings, but that’s the only way I got the result of a lookup plugin stored in a var. cmhamill suggested writing a module and registering the output of the module in order to get access to dynamically created complex data structures.

Cheers,
Paul

Sorry, I’m unclear on what you are trying to do still.

I guess i’m a bit confused because there are lookup questions, datastructure questions, and LDAP questions kind of all together.

If you’re wanting to write a lookup plugin to walk an arbitrary unique datastructure, that’s a good idea.

I would not think you would need to write a module, unless that module was to get some things from LDAP, and even then MAYBE you’d be better off just writing an inventory plugin that pulled your hosts from LDAP and set some group variables about the users and so on at the same time.

It kind of depends on what you’re trying to do, but I’ll admit I don’t have a lot of time to dig through the above and sort it out, and it confuses me somewhat.

Sorry, I’m unclear on what you are trying to do still.

Avoid duplicating data into playbook, inventory or vars files which I already have in a canonical store (LDAP in this case).

I guess i’m a bit confused because there are lookup questions, datastructure questions, and LDAP questions kind of all together.

LDAP is only coincidental, but yes, I still think there are lots of things to be done for lookups and datastructures in Ansible.

If you’re wanting to write a lookup plugin to walk an arbitrary unique datastructure, that’s a good idea.

I agree that this is something that’s missing.

I would not think you would need to write a module, unless that module was to get some things from LDAP, and even then MAYBE you’d be better off just writing an inventory plugin that pulled your hosts from LDAP and set some group variables about the users and so on at the same time.

In this case, I wanted to give our users access to hosts in ec2. They already have user accounts in our corporate LDAP server, and zero or more ssh keys per user as well. So instead of having to specify the users, including gecos field, shell and ssh keys in the playbook or vars files, I want to just give a list of usernames, and have those attributes that make sense copied from our internal directory server to the virtual host in ec2. Without having to set up an LDAP server in ec2, or a VPN from ec2 to our office or anything like that.

To me it feels natural to specify the list of users in either vars or the playbook instead of changing the inventory (script) when the list of users changes or I want to specify a set of users for a new host. And I also wouldn’t want to fetch the list of all users (basically dumping the whole directory) on every ansible run.

That said, I still think more options for handling complex data structures in playbook would be welcome. And is it possible to populate a var from a lookup without flattening the complex data structure into a string? That would also have been handy.

Sorry for being so confusing,
Paul