Separation of config data and logic

63 views
Skip to first unread message

Giovanni Tirloni

unread,
Feb 1, 2015, 4:03:41 PM2/1/15
to ansible...@googlegroups.com
Hi,

As I build more complex playbooks that will be used by other teams that
have zero knowledge of Ansible (read: big corporation), I started to
migrate much of the configuration data to variable files. The idea was
to enforce certain things in the playbooks (thing that won't ever
change and are standards -- famous last words) and let these users
change the moving parts through variables.

Initially it was nice because I was asking them to fill in a variable
named "oracle_sid" and I would use it throughout the plays in all sorts
of ways. The "users" didn't have to mess with Jinja filters, get the
chance to break the logic, etc.

Then it got weird when I was creating lists of dictionaries for users
that should exist for a given role, like this:

oracle_users:
- name: userX
group: groupX
groups: groupY,groupZ
home: /home/userX
- name: userY
group: ....

The YAML file with these variables is _almost_ like the playbook file
itself and I'm just looping over the list creating users with _almost_
all parameters defined by the end-user through that vars file.

So I got stuck thinking if I should be radical and not allow any
configuration data in the playbooks, only get it from variables. Or if I
should let these other operation teams mess directly with the playbooks.

I'm really divided about this and really appreciate any feedback.

Giovanni

mic...@mcrilly.me

unread,
Feb 1, 2015, 7:54:39 PM2/1/15
to ansible...@googlegroups.com
Hey Giovanni,

It's good that you want to separate your data from your logic. It's a design pattern you won't regret, now and going forward. Here's how I see your problem resolved.

A simple Playbook for looping over the data, adding groups (first) and users:

---
# oracle_users.yaml
- hosts: oracledb
  sudo
: yes
  tasks
:
   
- name: Create our (active) groups
     
group: name={{item.name}} state={{item.state}}
      with_items
: oracle_groups

   
- name: Create our (active) users
      user
: name={{item.name}} state={{item.state}}
      with_items
: oracle_users

And our actual data, which defines our groups and users. Keep in mind this file is being utilised in an important way: it's going into 'group_vars/'. As you're likely grouping up your hosts in your inventory file, this means you can easily apply a default, "global" configuration to all systems in that group, using group_vars. If you have just one Oracle server you want the users to exist on, however, then you can just move the data to host_vars/, and call the file the same name as the host's hostname in the inventory. Don't include any extensions, such as .yaml, to the file.

# oracledb
oracle_groups
:
 
- name: oracle_users
    state
: present
 
- name: oracle_admins
    state
: present
oracle_users
:
 
- name: oracle_user_1
    state
: present
    groups
:
     
- oracle_users
     
- oracle_admins
 
- name: oracle_user_2
    state
: present
    groups
:
     
- oracle_user

And our inventory file, for a complete example. Note I'm using Vagrant locally, so this is how it looks for me. These files are a complete working example with a simple, practically default, Vagrantfile.

[oracledb]
localdev ansible_ssh_host
=127.0.0.1 ansible_ssh_port=2222 ansible_ssh_user=vagrant ansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key

Overall you should be using 'group_vars/all' to define truly global data state that applies to everything in your estate. This is a great place to define the default users that can SSH into your systems, like sysads, as well as other handy features such as a base set of packages that must be installed, etc. If you need to override these settings, then you can use 'group_vars/$group_name' and 'host_vars/$host_name'.

You can also change the 'hash_behaviour' from the default of 'replace' to 'merge', which means as you work your way close to a specific host's configuration, hashes and arrays can have their values overridden OR new values introduced, those allowing you to merge global configuration with more host or group specific configuration. An example of this might be merging the global users from 'group_vars/all' with your Oracle users (from above) in 'group_vars/oracledb'.

I hope this makes helps. If you have any questions, let me know.

- M

Giovanni Tirloni

unread,
Feb 2, 2015, 5:03:28 AM2/2/15
to ansible...@googlegroups.com
On Sun, 01 Feb 2015 16:54 -0800, mic...@mcrilly.me wrote:
> It's good that you want to separate your data from your logic. It's a design pattern you won't regret, now and going forward. Here's how I see your problem resolved.

Hi Michael,

Thanks for the insights, certainly helpful! I will review my playbooks
and incorporate more of these ideas.

Giovanni
Reply all
Reply to author
Forward
0 new messages