skip to Main Content

I have the following roles structure:

$ tree roles
roles
├── user
│   └── tasks
│       └── main.yaml
└── validation
    └── tasks
        └── main.yaml

My goal is to include the validation role into multiple roles and avoid using a when condition, into every task.

validation/tasks/main.yaml:

---
- name: Test model
  ansible.builtin.command: grep 'Debian' /proc/device-tree/model
  changed_when: false
  register: model

- name: Set fact
  ansible.builtin.set_fact:
    debian: true
  when: model.rc == 0

user/tasks/main.yaml:

---
- name: Perform validation
  ansible.builtin.include_role:
    name: validation

- name: Get user info
  ansible.builtin.user:
    name: user
    state: present
  register: user_info
  when: debian | default(false)

playbook.yaml:

---
- name: Deployment
  hosts: cluster
  become: true
  gather_facts: true
  roles:
    - role: user

When I run the playbook, everything works as expected. My goal is to avoid adding inside each task that when condition.

Is there a way to create a handler which will perform automatically a validation for each role task? The above example is very limited, the actual playbook contains many roles, with each task being required to be validated.

My end-result should be:

  roles:
    - role: user
    - role: os
    - role: reset
    ...

Where each role task would automatically perform a validation during execution. Thank you for your help.

3

Answers


  1. Chosen as BEST ANSWER

    I resolved the issue, by including the validation role into meta.

    user/meta/main.yaml:

    ---
    dependencies:
      - role: validation
    

  2. You may try using when condition in role modifying playbook.yaml like this using any variable you may need in when condition:

    ---
    - name: Deployment
      hosts: cluster
      become: true
      gather_facts: true
      roles:
        - role: user
          when: ansible_os_family == "Debian"
    

    For more information check ansible documentation here:
    https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_conditionals.html#conditionals-with-roles

    Also if you need this, in playbook.yaml you may set any variables needed for a role to run.

    Login or Signup to reply.
  3. The validation is not needed. Use Ansible variable ansible_os_family instead. See gather_facts. For example,

    - hosts: localhost
      gather_facts: true
      tasks:
        - debug:
            var: ansible_os_family
    

    gives

      ansible_os_family: Debian
    

    You want to perform a role for multiple operating systems (or families of OS). In this case, you have to decide where to place the conditions.

    a) If you want to use the role keyword you have to place the conditions inside the roles because the facts will be gathered after the roles are loaded. In other words, the variable ansible_os_family won’t be available before a role is loaded.

      roles:
        - role: user
        - role: os
        - role: reset
    

    For example, create role user

    shell> tree roles/
    roles/
    └── user
        └── tasks
            ├── Debian.yml
            ├── FreeBSD.yml
            └── main.yml
    
    shell> cat roles/user/tasks/main.yml 
    - include_tasks: "{{ ansible_os_family }}.yml"
    shell> cat roles/user/tasks/Debian.yml 
    - debug:
        msg: Manage users for Debian
    shell> cat roles/user/tasks/FreeBSD.yml 
    - debug:
        msg: Manage users for FreeBSD
    

    Then, the playbook

    - hosts: localhost,test_11
      gather_facts: true
      roles:
        - user
    

    gives

    PLAY [localhost,test_11] *************************************************************************************************************
    
    TASK [Gathering Facts] ***************************************************************************************************************
    ok: [localhost]
    ok: [test_11]
    
    TASK [user : include_tasks] **********************************************************************************************************
    included: /export/scratch/tmp7/test-178/roles/user/tasks/Debian.yml for localhost
    included: /export/scratch/tmp7/test-178/roles/user/tasks/FreeBSD.yml for test_11
    
    TASK [user : debug] ******************************************************************************************************************
    ok: [localhost] => 
      msg: Manage users for Debian
    
    TASK [user : debug] ******************************************************************************************************************
    ok: [test_11] => 
      msg: Manage users for FreeBSD
    
    PLAY RECAP ***************************************************************************************************************************
    localhost: ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    test_11: ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    


    b) If you want to use the module include_role the situation is more flexible. For example, you can create roles for particular OS families

    shell> tree roles/
    roles/
    ├── user_Debian
    │   └── tasks
    │       └── main.yml
    ├── user_default
    │   └── tasks
    │       └── main.yml
    ├── user_FreeBSD
    │   └── tasks
    │       └── main.yml
    └── user_RedHat
        └── tasks
            └── main.yml
    
    shell> cat roles/user_Debian/tasks/main.yml 
    - debug:
        msg: "Manage users for {{ ansible_os_family }}"
    

    Declare the variables, for example in group_vars/all

    shell> cat group_vars/all/role_user_family.yml
    roles_user_family:
      Debian: user_Debian
      FreeBSD: user_FreeBSD
      RedHat: user_RedHat
      default: user_default
    
    role_user_family: "{{ roles_user_family[ansible_os_family]|
                          default(roles_user_family.default) }}"
    

    Then, the playbook

    - hosts: localhost,test_11
      gather_facts: true
      tasks:
        - include_role:
            name: "{{ role_user_family }}"
    

    gives

    PLAY [localhost,test_11] *********************************************************************
    
    TASK [Gathering Facts] ***********************************************************************
    ok: [localhost]
    ok: [test_11]
    
    TASK [include_role : {{ role_user_family }}] *************************************************
    
    TASK [user_Debian : debug] *******************************************************************
    ok: [localhost] => 
      msg: Manage users for Debian
    
    TASK [user_FreeBSD : debug] ******************************************************************
    ok: [test_11] => 
      msg: Manage users for FreeBSD
    
    PLAY RECAP ***********************************************************************************
    localhost: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    test_11: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    


    Notes:

    • See available platforms

    • See other distribution facts, for example

    shell> ansible test_host -m setup | grep ansible_distr
            "ansible_distribution": "Ubuntu",
            "ansible_distribution_file_parsed": true,
            "ansible_distribution_file_path": "/etc/os-release",
            "ansible_distribution_file_variety": "Debian",
            "ansible_distribution_major_version": "20",
            "ansible_distribution_release": "focal",
            "ansible_distribution_version": "20.04",
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search