Ansible playbook to generate webserver folder structure with users and projects 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
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 &lt;your role name&gt;


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 using vars/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.