0

I am new to Ansible and I am attempting to work on getting user access under control. I found this playbook from Galaxy:

https://github.com/singleplatform-eng/ansible-users

I was also reading from this source to help manage different environments:

https://www.digitalocean.com/community/tutorials/how-to-manage-multistage-environments-with-ansible

So I have the following setup:

vagrant@ansible:~/ansible$ tree
├── ansible.cfg
├── debug.yml
├── dev_site.yml
├── filter_plugins
├── group_vars
│   └── all
│       └── 000_cross_env_vars -> ../../inventories/000_cross_env_vars
├── hosts
├── inventories
│   ├── 000_cross_env_vars
│   ├── development
│   │   ├── group_vars
│   │   │   └── all
│   │   │       ├── 000_cross_env_vars -> ../../../000_cross_env_vars
│   │   │       └── env_specific.yml
│   │   ├── hosts
│   │   └── host_vars
│   │       └── hostname1
│   ├── production
│   │   ├── group_vars
│   │   │   └── all
│   │   │       ├── 000_cross_env_vars -> ../../../000_cross_env_vars
│   │   │       └── env_specific
│   │   ├── hosts
│   │   └── host_vars
│   │       └── hostname1
│   └── staging
│       ├── group_vars
│       │   └── all
│       │       ├── 000_cross_env_vars -> ../../../000_cross_env_vars
│       │       └── env_specific.yml
│       ├── hosts
│       └── host_vars
│           └── hostname1
├── library
├── mgmt-ssh-add-key.yml
├── module_utils
├── prod_site.yml
├── README.md
├── roles
│   └── users <--- FROM LINK ABOVE
│       ├── defaults
│       │   └── main.yml
│       ├── handlers
│       │   └── main.yml
│       ├── meta
│       │   └── main.yml
│       ├── tasks
│       │   ├── main.yml
│       └── tests
│           └── test.yml
├── stage_site.yml
├── user_accounts.retry
└── user_accounts.yml

Playbook

vagrant@ansible:~/ansible$ cat user_accounts.yml 
---
- hosts: all
  become: true
  remote_user: vagrant
  vars_files:
    - "{{ inventory_dir }}/group_vars/all/env_specific.yml"
  roles:
    - users

Shared Variables between environments

vagrant@ansible:~/ansible$ more inventories/000_cross_env_vars 
---
# System Users
users:
  - username: sbody
    name: Some Body
    uid: 3001
    groups: "{{ users_groups.['username'].groups }}"
    home: /home/sbody
    profile: |
      alias ll='ls -lah'
    ssh_key:
      - "ssh-rsa ... "

# Users to delete
users_deleted:
  - username: bar
    uid: 9002
    remove: yes
    force: yes

Specific Environment Variables

vagrant@ansible:~/ansible$ cat inventories/development/group_vars/all/env_specific.yml 
# here we assign variables to particular groups
env: dev
users_groups:
  - username: sbody
    groups: ['users','developers'] # feeds groups in user creation

# Groups to create
groups_to_create:
  - name: developers
    gid: 10000

I think there is a way to feed the groups memberships from env_specific.yml for each user in 000_cross_env_vars but I am not sure how to do it without the env_specific.yml trumping the 000_cross_env_vars. Any help would be most appreciated. Thank you in advance.

EDIT:

I made the following changes and it seems to be getting closer now:

vagrant@ansible:~/ansible$ cat                 
inventories/development/group_vars/all/env_specific.yml 
# here we assign variables to particular groups
stage: dev
group_membership:
  sbody_groups: ['users','developers']

And the users declaration:

vagrant@ansible:~/ansible$ more inventories/000_cross_env_vars 
---
# System Users
users:
  - username: sbody
    name: Some Body
    uid: 3001
    groups:  "{{ group_membership['sbody_groups'] }}"
    home: /home/sbody
    profile: |
      alias ll='ls -lah'
    ssh_key:
      - "ssh-rsa ... "

So now I need to figure out how to set a default in case the user_group isn't defined.

Minnow47
  • 1
  • 3

2 Answers2

0

From my experience: Instead of using inventory vars I prefer using a vars directory like:

  - name: Read all variables
    block:

      - name: Get stats on all variable files
        stat:
          path: "{{item}}"
        with_fileglob:
          - "vars/global/common.yml"
          - "vars/{{ env|default('dev') }}/default.yml"
          - "vars/{{ env|default('dev') }}/secrets.vault"
        register: _variables_stat

      - name: Include all variable files (only when found)
        include_vars : "{{item.stat.path}}"
        when         : item.stat.exists
        with_items   : "{{_variables_stat.results}}"
        no_log       : true

    delegate_to: localhost
    become: false

You can select the env whether from the inventory or from the command line.

Your global vars will be read first and replaced by your environments if they exists. If not, you will have always the default option.

imjoseangel
  • 3,543
  • 3
  • 22
  • 30
0

From personal experience, I've used inventories to separate environments and all it does it create unnecessary overhead when trying to keep certain variables in sync across the different inventories.

What we opted for instead is to separate the environments by inventory groups. That way we can load variables based on group names, pass those to our roles and utilize Ansible's inventory auto-loading mechanisms.

- name: Manage Users
  hosts: some-host
  tasks:
    - name: Include Common Users & Groups
      set_fact:
        users: "{{ common_users }}"
        usergroups: "{{ common_usergroups }}"
   - name: Include Users Based on Groups
     set_fact:
       users "{{ users + q('vars', item + '_users') }}"
       usergroups: "{{ usergroups + q('vars', item + '_usergroups') }}"
     loop: "{{ lookup('items', group_names) }}"
 roles:
   role: users

However, the query filter and the vars lookup are new features and were shipped with Ansible 2.5.

1efty
  • 825
  • 7
  • 10