Create different sets of users on different sets of hosts

Hi,
A new ansible user here… I’ve been perusing the mailing list archives and have gathered a lot of useful tidbits.

I’ve been fairly successful in figuring out how to create a set of users on a list of hosts. However, what I’m not so clear about is how to create different sets of users on different categories of hosts. We’re a software house that administrates the server farms at our customers. Let’s say we have 20 customers, and each customer can have 3-20 servers; these servers fall into different categories as well: application servers, database servers, test app. servers, test DB servers for example.

One set of users should be created on all systems always, namely our sysadmins.
Another set of users should only be created on the database servers; likewise for the application servers.

The approach I’d find logical would be to write a playbook such as:

  • hosts: all_hosts

tasks:

  • name: Add sysadmin users
    user: name={{ item.key }} password={{ item.value.password }} uid={{ item.value.uid }} group={{ item.value.group }} groups=“” comment=“{{ item.value.comment }}” state={{ item.value.state }} update_password=always
    with_dict: sysadmin_user

  • hosts: db_hosts
    tasks:

  • name: Add DBA users
    user: name={{ item.key }} password={{ item.value.password }} uid={{ item.value.uid }} group={{ item.value.group }} groups=“” comment=“{{ item.value.comment }}” state={{ item.value.state }} update_password=always
    with_dict: dba_user

  • hosts: application_hosts
    tasks:

  • name: Add application users
    user: name={{ item.key }} password={{ item.value.password }} uid={{ item.value.uid }} group={{ item.value.group }} groups=“” comment=“{{ item.value.comment }}” state={{ item.value.state }} update_password=always
    with_dict:appl_user

This would work, but would entail listing all hosts at least twice: once for the “all_hosts” list, and once for the specific type of host. I’d like to be able to compose the “all_hosts” list automatically out of the other lists. I’ve tried a couple of ways after reading things in the mailing list archive that might be applicable, but haven’t had any success.

So, in short, my question really boils down to: Is it possible to merge existing host lists so that I don’t have to repeat hosts in different lists? The same question also applies to user lists, although I suspect that if it’s possible with host lists, the same method will work for user lists as well.

(Being able to merge host lists would mean it would be possible to define hosts in lists according to customer + type, and then build different host lists such as “all DB hosts” or “all hosts at customer XYZ”.)

Thanks!

Paul,

I recently encountered what I believe the be the same scenario. I googled around and couldn’t seem to find anything to fit the scenario so I used the following approach (probably re-inventing the wheel). The key is to make use of roles, playbooks and vars separately. I’ve adapted your example and truncated it for simplicity:

  1. Create a role ‘groups_users’ consisting of least ‘roles/groups_users/tasks/main.yml’:

Made an error (why aren’t google group posts editable? who knows…). Should read:

  1. Create group_vars files for each group:

‘group_vars/myhosts’:

Thanks for your example, I’m just about understanding how it works :slight_smile: I did need to add a .yml extension to the external_vars/groups_users_* files but that was obvious from how the playbook referenced those file. Also the role needs “group:” and not “groups:” (the error message could have been a bit clearer…).

However, when I try this, the gathering facts works fine, then:

TASK: [groups_users | Add groups] *********************************************
fatal: [host1] => with_items expects a list or a set
fatal: [host2] => with_items expects a list or a set
fatal: [host3] => with_items expects a list or a set

FATAL: all hosts have already failed – aborting

This is the sort of thing that’s probably trivial to fix with some experience but I have no clue how to proceed now :frowning:

FWIW I’m running:
ansible 1.8 (devel 44afa7facc) last updated 2014/10/27 14:31:42 (GMT +200)

Following up on myself:

If I change the roles/groups_users/tasks/main.yml to this:

Hey Paul,

My apologies for the delayed reply.

I can’t see why you’re getting the result you are. But I did notice a few errors in the snippets I posted. Here’s a testing and working example:

https://github.com/mephage/ansible-groups_users_example

Also apologies, I was offline for a bit and then had other priorities at work.

I’ve downloaded your github example as a zip file, unpacked it, modified host and usernames to reflect the local situation.

I now don’t get an error, but now the tasks just show “skipping” for everything:

PLAY [Add sysadmins group and users] ******************************************

GATHERING FACTS ***************************************************************
ok: [host2]
ok: [host1]

TASK: [groups_users | Add groups] *********************************************
skipping: [host1] => (item={‘state’: ‘present’, ‘gid’: 7575, ‘name’: ‘impulsys’})
skipping: [host2] => (item={‘state’: ‘present’, ‘gid’: 7575, ‘name’: ‘impulsys’})

TASK: [groups_users | Add users] **********************************************
skipping: [host1] => (item={‘comment’: ‘Paul Slootman 2’, ‘state’: ‘present’, ‘group’: ‘groupname’, ‘name’: ‘pslootman’, ‘password’: ‘$1$.xxxxxxxxxxxxxxxxxxxxxx’, ‘pubkey’: ‘ssh-rsa AAAA…’, ‘uid’: 54343})
skipping: [host2] => (item={‘comment’: ‘Paul Slootman 2’, ‘state’: ‘present’, ‘group’: ‘groupname’, ‘name’: ‘pslootman’, ‘password’: ‘$1$.xxxxxxxxxxxxxxxxxxxxxx’, ‘pubkey’: ‘ssh-rsa AAAA…’, ‘uid’: 54343})

PLAY [Add db group and users] *************************************************

GATHERING FACTS ***************************************************************
ok: [host1]
ok: [host2]

TASK: [groups_users | Add groups] *********************************************
skipping: [host1] => (item={‘state’: ‘present’, ‘gid’: 7576, ‘name’: ‘dbagroup’})
skipping: [host2] => (item={‘state’: ‘present’, ‘gid’: 7576, ‘name’: ‘dbagroup’})

TASK: [groups_users | Add users] **********************************************
skipping: [host1] => (item={‘comment’: ‘Nelson DBA’, ‘state’: ‘present’, ‘group’: ‘dbagroup’, ‘name’: ‘ndba’, ‘password’: ‘$1$.xxxxxxxxxxxxxxxxxxxxxx’, ‘pubkey’: None, ‘uid’: 54331})
skipping: [host2] => (item={‘comment’: ‘Nelson DBA’, ‘state’: ‘present’, ‘group’: ‘dbagroup’, ‘name’: ‘ndba’, ‘password’: ‘$1$.xxxxxxxxxxxxxxxxxxxxxx’, ‘pubkey’: None, ‘uid’: 54331})

PLAY RECAP ********************************************************************
host1 : ok=6 changed=0 unreachable=0 failed=0
host2 : ok=6 changed=0 unreachable=0 failed=0

I’ve modified roles/groups_users/tasks/main.yml to this: