##Ansible Best Practises
Problem that is being addressed is to complexity of the ansible projects, soon as the project starts grow. Organization of the code in this repository shows how it is possible solve following issues:

* How to manage external roles
* Usage of variables
* Naming 
* Staging
* Complexity of plays




##Directory Layout

    production.ini            # inventory file for production stage
    development.ini           # inventory file for development stage
    test.ini                  # inventory file for test stage
    
    group_vars/
        all                   # variables under this directory belongs all the groups
            common.yml        # Common role variable file
        webservers            # here we assign variables to webservers groups
            nginx.yml         # Each file will corspond to a role i.e. nginx
        postgresql            # here we assign variables to postgresql groups
            postgresql.yml    # Each file will corspond to a role i.e. postgresql
    plays
        ansible.cfg           # Ansible.cfg file that holds all ansible config
        webservers.yml        # playbook for webserver tier
        postgresql.yml        # playbook for postgresql tier

    roles/
        requirements.yml      # All the infromation about the roles
        external              # All the roles that are in git or ansible galaxy
                              # This directory is in ignored by git and all the roles in the 
                              # requirements.yml will be downloaded into this directory
        internal              # All the roles that are not public 



##TL;DR
* Do not keep external roles in your repository, use ansible-galaxy
* Do not use pre_task, task or post_tasks in your play, use roles to reuse the code
* Keep all your variables in one place, if possible
* Do not use variables in your play
* Use variables in the roles instead of hardcoding
* Keep the names consistent between groups, plays, variables, and roles
* Different environments(development,test,production) must be close as possible, if not equal
* Use tags in your play



##1. How to Manage Roles
It is a bad habit to keep the copy of roles, that are developed by other developers, in your git repository. Therefore, you can use ansible-galaxy for installing the roles you need, at the location you need, by simply defining them in the requirements.yml:

```
---
- src: ANXS.build-essential
  version: "v1.0.1"
  path : external
```

Roles can be downloaded with this command:

```
ansible-galaxy install -r requirements.yml
```


##2. Keep your plays simple
If you want to take the advantage of the roles, you have to keep your plays simple. 
Therefore do not add any tasks in your main play. Your play should only consist of the list of roles that it depends on. Here is an example:

```
---

- name: postgresql.yml | All roles
  hosts: postgresql
  sudo: True

  roles:
    - { role: common,                   tags: ["common"] }
    - { role: ANXS.postgresql,          tags: ["postgresql"] }
```

As you can see there are also no variables in this play, you can use variables in many different ways in ansible, and to keep it simple and easier to maintain do not use variables in plays. Furthermore, use tags, they give wonderful control over role execution.


##3. Stages
Most likely you will need different stages(e.g. test, development, production) for the product you are either developing or helping to develop. A good way to manage different stages is to have multiple inventory files. As you can see in this repository, there are three inventory files. Each stage you have must be identical as possible, that also means, you should try to use few as possible host variables. It is best to not use at all.


##4. Variables
Variables are wonderful, that allows you to use all this existing code by just setting some values. Ansible offers many different ways to use variables. However, soon as your project starts to get bigger, and more you spread variables here and there, more problems you will encounter. Therefore it is good practice to keep all your variables in one place, and this place happen to be group_vars. They are not host dependent, so it will help you to have a better staging environment as well. Furthermore, if you have internal roles that you have developed, keep the variables out of them as well, so you can reuse them easily.


##5. Name consistency
If you want to maintain your code, keep the name consistency between, play and inventories, roles and group variables. Use the name of the roles to separate different variables in each group. If you have a role called nginx keep the variables under your group_vars with the same name.



#TODO
* ansible-vault

#License
MIT License.