I’m using a playbook to create users and add pubkeys on a server, it does it sequentially and the usernames, groups and keys are all in order. I’m wondering if there is a better way to do this, follow me on some pseudo playbook code:
Ok, so in Ansible, it’s more of an exercise of modeling than coding. We intentionally do not encourage things like nested Ruby lambda blocks
with_items is used for loops.
Still, I would restructure things a bit so you have a nice list instead of a hash table, so that the name of your user is easy to get at.
Right, I missed a ‘item’ there, thanks
Ok, so in Ansible, it’s more of an exercise of modeling than coding. We intentionally do not encourage things like nested Ruby lambda blocks
I thought so, but it was an example from a chef cookbook ;).
with_items is used for loops.
Still, I would restructure things a bit so you have a nice list instead of a hash table, so that the name of your user is easy to get at.
===
- name: user1
full_name: User1
groups:- a
- b
- name: user2
…
That’s a better idea indeed.
(I would also be much more apt to include the users definition in a group_vars/ file rather than keeping it inline in the playbook, but that’s not material to this)
Correct, is what I normally do, but to keep it simple for this post I did it like above.
===
Using 1.2 syntax:
- name: make some users
user: name={{ item.name }} groups={{ “,”.join(items.groups) }}
with_items: usersOr before:
- name: make some users
user: name=${item.name} groups=${item.groups}
with_items: ${users}Now for keys, I wouldn’t keep them in a list based on user, but based on a list of what keys are authorized on what system or group.
keys:
- user: bob
key: /path/to/bob.key- user: alice
key: /path/to/alice.keySo your task is just like this:
- name: authorized keys setup
authorized_key: name={{ keys.user }} key=“{{ lookup(‘file’, key.path }}”
with_items: keysYou could keep the key in the variable structure too, I just prefer them on disk so they are easier to replace.
And I’d also keep this “keys” list as part of something like “group_vars/mygroup” so I could control who had access to what system based on group, rather than keeping that list in my playbook in the vars section also.
Yet again thanks for the help
Have two related questions. When using the following syntax for groups:
users:
- name: “rve”
full_name: “RvE”
groups: - admin
- amsterdam
And the following playbook command:
- name: Create groups
group: name=${item.groups} state=present
with_items: ${users}
Results in the following error:
msg: groupadd: ‘admin,amsterdam’ is not a valid group name
Is that because I access or define the variable in a wrong way?
Second one, regarding the SSH keys:
Playbook variables:
users:
- name: “rve”
full_name: “RvE”
ssh_keys: - “ssh-rsa AAAAB3NzaC1yc2EAA[…] rve1@box”
- “ssh-rsa AAAAB3NzaC1yc2EAA[…] rve2@box”
- “ssh-rsa AAAAB3NzaC1yc2EAA[…] rve3@box”
Playbook command:
- name: add ssh keys
authorized_key: user=${item.name} key=“${item.ssh_keys}”
with_items: ${users}
Ends up in the authorized key file as a comma separated list:
ssh-rsa AAAAB3NzaC1yc2EAA[…] rve1@box, ssh-rsa AAAAB3NzaC1yc2EAA[…] rve2@box, ssh-rsa AAAAB3NzaC1yc2EAA[…] rve3@box
is the above because I’m using a with_items: users and it should for this case be a with_items: users.$USERNAME.groups/ssh_keys? if so, how can I fix it?
Groups are set on the ‘user’ module, and created with the groups module, so you’ve got that a bit inverted. See the module docs for details.
As for SSH keys the way you are modelling them, I would highly recommend constructing the authorized keys file based on a template.
This came up yesterday actually.
Groups are set on the ‘user’ module, and created with the groups module, so you’ve got that a bit inverted. See the module docs for details.
Before adding a user to a groups I need to create the group. I want to create all the groups that are defined in the variables for the users, and not define a seperate group variable with all possible groups. Therefore I want to access all the users.USERNAME.groups in a with_items, but that doesn’t seem to work.
As for SSH keys the way you are modelling them, I would highly recommend constructing the authorized keys file based on a template.
Correct, been doing that for my playbooks, but still I was wondering how to access the nested variables in a with_items.
“Before adding a user to a groups I need to create the group. I want to create all the groups that are defined in the variables for the users, and not define a seperate group variable with all possible groups. Therefore I want to access all the users.USERNAME.groups in a with_items, but that doesn’t seem to work.”
Sorry, this is presently not possible.
I’ll think about how to make a lookup plugin that allows this kind of easy iteration.
Jinja2 in playbooks is quite useful, but it doesn’t allow the kind of list comprehensions you want to do right now.
So for now, you’ll have to have two lists.
You are reading the 1.2 documentation, you should look for the 1.1 documentation at http://ansible.cc/docs/released/1.1/
I will update the 1.2 “getting started” information to make it clear also, rather than just listing it on the home page.
Maybe arbitrary Python list comprehensions with a couple of helper functions would be a nice solution for such advanced loops (just like advanced condition checking is done with with
is done with an arbitrary Python expression). Jinja2 unfortunately does not support them.
Greetings,
gw
Yep, that’s what I was proposing on IRC this AM. Perhaps something I may explore this weekend.