I try to generate with ansible a folder structure for a webserver with users and linked projects.
The playbook works. But with more users and projects it gets quite complex to handle.
How can I simplify my code or vars sections?
I read a hint about using blocks so that all tasks inside it could use the same loop.
Is that the way to go?
The docs on blocks don't have a lot of examples. Any hint or link to examples is most appreciated.
Of course if you have any other pointers, please let me know.
---
- hosts: localhost
become: yes
become_method: sudo
# check_mode: yes
vars:
project_base_path: /usr/src/project
www_base_path: "/var/www/{{ansible_hostname}}"
projects:
mars: "{{ project_base_path }}/mars"
venusnew: "{{ project_base_path }}/venus/new"
venusold: "{{ project_base_path }}/venus/old"
users:
goku:
present: true
pw: #vault
luffy:
present: true
pw: #vault
user_projects:
- uname: goku
uproject:
- lname: mars
spath: "{{ projects.mars }}"
- uname: luffy
uproject:
- lname: venusnew
spath: "{{ projects.venusnew }}"
- lname: project
spath: "{{ projects.venusold }}"
tasks:
- name: check www path | Check if the path is available or create it
file:
path: "{{ www_base_path }}"
owner: www-data
group: www-data
state: directory
- name: check user www directory | Check if the directory of the user is available or create it
file:
owner: www-data
group: www-data
state: directory
path: "{{ www_base_path }}/{{ item.key}}"
with_dict: "{{ users }}"
- name: check projects in usr src | Check if the directory of the user is available or create it
file:
owner: www-data
group: www-data
state: directory
path: "{{ item.value}}"
with_dict: "{{ projects }}"
- name: link projects to users | Create links for the users
file:
state: link
# force: yes
owner: www-data
group: www-data
src: "{{ item.1.spath }}"
dest: "{{ www_base_path }}/{{ item.0.uname }}/{{ item.1.lname }}"
with_subelements:
- "{{ user_projects }}"
- uproject
1 Answer 1
I can think of 3 options.
Using a role
As you work in Ansible progresses you'll find the number of tasks and variables harder to manage as a single file. You'll likely want to create an ansible role.
ansible-galaxy init <your role name>
This will create a structure of folders with defaults, vars, files, handlers, tasks, meta and templates.
You can then separate out your variables into separate files while keeping them originally defined in defaults/main.yml in order to easily override them while controlling how there initialized.
Force 'manual' loading of vars conditionally within the role by overriding defaults/main.yml with custom logic in tasks.
This can apply to stand alone task files also, but I prefer using roles. Here are two examples:
# including vars that are outside your role on inventory dir path level. - include_vars: file: "{{inventory_dir | dirname}}/group_vars/rdu.yml" when: env == 'rdu' # including vars that are within your role to a var called dataset. - include_vars: file: "{{role_path}}/defaults/datasets/{{dataset_name}}.yml" when: dataset_name is defined
You can also use the vars folder within the role but I prefer to use
defaults/main.yml
to set defaults and then write over the defaults later. If the values are static and should not be changed then you can consider usingvars/main.yml
this assumes you are using a role.Put variables which are associated with a specific group under your
group_vars
and then make the association in your inventory file.See http://docs.ansible.com/ansible/latest/intro_inventory.html#group-variables
My suggestion is to create a role, and then organize your variables into similar groups where possible and keep defaults in the role/role-name/defaults.main.yml and then override them based on the logic of your variables.
So looking at your code it seems that each project (mars, venusnew, and venusold) could like get there own yml file. Using conditional logic you can decide which vars to load.