简体   繁体   中英

Avoid using when condition for each task, while including an Ansible validation role?

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.

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.

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",

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM