# Роли

Роль — способ организовать набор tasks, переменных, шаблонов, файлов и обработчиков в переиспользуемый модуль. Роли используются для конфигурации конкретных приложений. По умолчанию директория /etc/ansible/roles

Настраивается в cfg файле:

```
[defaults]
roles_path = ./roles
```

Также в переменной ANSIBLE\_ROLES\_PATH

**Структура роли и добавление в playbook**

1. Создается папка roles, внутри папки с названиями ролей, внутри каждой папки - defaults files handlers meta templates tasks vars
2. в playbook добавляется   
    ```yaml
       roles:
        - имя
    ```

**Назначения папок**

<table border="1" id="bkmrk-%D0%9F%D0%B0%D0%BF%D0%BA%D0%B0-%D0%9D%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-def" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 19.5587%;"></col><col style="width: 80.4413%;"></col></colgroup><thead><tr><td class="align-center">Папка</td><td class="align-center">Назначение</td></tr></thead><tbody><tr><td>defaults</td><td>Устанавливает переменные по умолчанию для включенных ролей. Обычно defaults/main.yml ```yaml
---
# Used only for Debian/Ubuntu installation, as the -t option for apt.
nginx_default_release: ""

# Used only for Redhat installation, enables source Nginx repo.
nginx_yum_repo_enabled: true

# Use the official Nginx PPA for Ubuntu, and the version to use if so.
nginx_ppa_use: false
nginx_ppa_version: stable

```

</td></tr><tr><td>files</td><td>содержит статические файлы и файлы сценариев, которые могут быть скопированы на удалённый сервер или выполнены на нём. Пример копирования внутри роли и выполнения:

roles/myrole/  
├── files/  
│ └── install.sh  
└── tasks/  
 └── main.yml

```yaml
- name: Copy script
  ansible.builtin.copy:
    src: install.sh
    dest: /tmp/install.sh
    mode: "0755"

- name: Execute script
  ansible.builtin.command:
    cmd: /tmp/install.sh
```

</td></tr><tr><td>handlers</td><td>Обработчики, выполняемые в самом конце</td></tr><tr><td>meta</td><td>для метаданных роли, которые используются для управления зависимостями. Например, вы можете определить список ролей, которые должны быть применены до вызова текущей роли.</td></tr><tr><td>templates</td><td>Шаблоны генерации файлов на удалённых хостах. Шаблоны jinja2.

Например нужно создать файл /etc/docker/daemon.json

Создаем шаблон в roles/docker/templates/daemon.json.j2

```
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "{{ docker_log_size }}",
    "max-file": "{{ docker_log_files }}"
  }
}
```

Добавляем переменные в roles/docker/defaults/main.yml

```yaml
docker_log_size: "10m"
docker_log_files: "3"
```

Создаем задачу

```yaml
- name: Deploy daemon.json
  ansible.builtin.template:
    src: daemon.json.j2
    dest: /etc/docker/daemon.json
    owner: root
    group: root
    mode: "0644"
  notify: Restart Docker
```

Создаем handlers roles/docker/handlers/main.yml

```yaml
- name: Restart Docker
  ansible.builtin.systemd:
    name: docker
    state: restarted
```

 В результате на сервере появится json файл.

[Описание Jinja2](http://bobrobotirk.ru/books/python/page/jinja2 "Jinja2")

</td></tr><tr><td>tasks</td><td>Содержит файлы с задачами, которые определяются в разделе tasks обычного плейбука Ansible. Сначала просматривается файл tasks/main.yml В нем указывается условия импорта других файлов

```yaml
---
# Variable setup.
- name: Include OS-specific variables.
  include_vars: "{{ ansible_os_family }}.yml"

- name: Define nginx_user.
  set_fact:
    nginx_user: "{{ __nginx_user }}"
  when: nginx_user is not defined

# Setup/install tasks.
- include_tasks: setup-RedHat.yml
  when: ansible_os_family == 'RedHat'

- include_tasks: setup-Ubuntu.yml
  when: ansible_distribution == 'Ubuntu'

- include_tasks: setup-Debian.yml
  when: ansible_os_family == 'Debian'

# Vhost configuration.
- import_tasks: vhosts.yml

# Nginx setup.
- name: Copy nginx configuration in place.
  template:
    src: "{{ nginx_conf_template }}"
    dest: "{{ nginx_conf_file_path }}"
    owner: root
    group: "{{ root_group }}"
    mode: 0644
  notify:
    - reload nginx

- name: Ensure nginx service is running as configured.
  service:
    name: nginx
    state: "{{ nginx_service_state }}"
    enabled: "{{ nginx_service_enabled }}"

```

Пути указываются относительно директории tasks

Эти задачи могут напрямую ссылаться на файлы и шаблоны, содержащиеся в соответствующих каталогах внутри роли, без необходимости указывать полный путь к файлу.

</td></tr><tr><td>vars</td><td>переменные для роли могут быть указаны в файлах внутри каталога, а затем ссылаться на них в другом месте роли.</td></tr></tbody></table>

**Ссылки:**

[Пример преобразования одного файла в роль](https://habr.com/ru/companies/slurm/articles/706920/)

**Хранилище ролей**

Есть сайт с ролями почти для всего. [Сайт с ролями ansible](https://galaxy.ansible.com) Можно найти нужную роль на сайте, затем установить при помощи

```
ansible-galaxy install current_role_name -p .
```

Создание роли:

```
ansible-galaxy init new_role_name
```

**Пример создания новой роли**

Пусть будет задача в установке docker. Реализуем из инструкции по [Docker: общая информация и установка](http://bobrobotirk.ru/books/docker-k8s/page/obshhaia-informaciia-i-ustanovka "Общая информация и установка")

Инициализируем новую роль

```
ansible-galaxy init just_new_role
```

Структура директорий создана. Проанализируем инструкцию.

- Написана для 3 вариаций ОС: Debian, Ubuntu, Alt.
- Последовательность установки: 
    - Создание пользователя
    - Добавление сертификатов
    - Непосредственно установка пакетов
    - Дополнительные удобства

В константы будем постепенно добавлять нужные. Итоговый defaults/main.yml :

```yaml
---
# defaults file for just_new_role
docker_user: webadmin
packages_certificates:
  - ca-certificates
  - curl
  - gnupg
  - lsb-release
packages_docker_debian:
  - docker-ce
  - docker-ce-cli
  - containerd.io
  - docker-compose-plugin
packages_docker_alt:
  - docker-engine
  - docker-compose-v2

```

Начнем с установки sudo и добавления пользователя в группы, то есть реализуем следующие команды:

```
apt-get install sudo
sudo apt-get update
usermod -aG sudo docker_user
```

Файл задач tasks/01\_create\_user.yml :

```yaml
- name: Install sudo
  ansible.builtin.apt:
    name: sudo
    state: present
    update_cache: true
- name: Ensure user exists and is in sudo group
  ansible.builtin.user:
    name: "{{ docker_user }}"
    groups: sudo
    append: true
    state: present
```

Да, если сопоставить количество строк команд и того, что необходимо написать для их исполнения, возникает ощущение перебора (в 3 раза). Но это плата за индепотентность.

Добавим в файл tasks/main.yml задачу старта 01\_create\_user.yml

```yaml
---
# tasks file for just_new_role
- include_tasks: 01_create_user.yml
```

**Запуск роли**

Когда роль написана, нужно создать следующую структуру директорий для playbook

```
project/
├── inventory.ini
├── playbook.yml
└── roles/
    └── just_new_role/
        ├── defaults/
        ├── tasks/
        ├── handlers/
        └── ...
```

Пример файла inventory.ini

```
[docker_hosts]
192.168.1.100

[docker_hosts:vars]
ansible_user=webadmin
```

Пример playbook.yml

```yaml
---
- name: Install Docker
  hosts: all
  become: true

  roles:
    - just_new_role

```

Итоговые файлы:

main.yml

```yaml
---
# tasks file for just_new_role
- include_tasks: 01_create_user.yml
- include_tasks: 02_append_certs.yml
```

01\_create\_user.yml

```yaml
- name: Install sudo
  ansible.builtin.apt:
    name: sudo
    state: present
    update_cache: true
  when: ansible_distribution == "Debian"
- name: Ensure user exists and is in sudo group
  ansible.builtin.user:
    name: "{{ docker_user }}"
    groups: sudo
    append: true
    state: present
- name: Install required packages
  ansible.builtin.apt:
    name: "{{ packages_certificates }}"
    state: present
    update_cache: true
  when: ansible_distribution == "Debian"

```

02\_append\_certs.yml

```yaml
- name: Create apt keyrings directory
  ansible.builtin.file:
    path: /etc/apt/keyrings
    state: directory
    owner: root
    group: root
    mode: "0755"

- name: Download Docker GPG key
  ansible.builtin.get_url:
    url: https://download.docker.com/linux/debian/gpg
    dest: /etc/apt/keyrings/docker.asc
    mode: "0644"

- name: Create binary keyring
  ansible.builtin.command:
    cmd: >
      gpg --dearmor
      --output /etc/apt/keyrings/docker.gpg
      /etc/apt/keyrings/docker.asc
    creates: /etc/apt/keyrings/docker.gpg

- name: Add Docker repository
  ansible.builtin.apt_repository:
    repo: >-
      deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg]
      https://download.docker.com/linux/debian
      {{ ansible_distribution_release }} stable
    filename: docker
    state: present

- name: Update apt cache
  ansible.builtin.apt:
    update_cache: true

- name: Install required packages
  ansible.builtin.apt:
    name: "{{ packages_docker_debian }}"
    state: present
    update_cache: true
  when: ansible_distribution == "Debian"

- name: Ensure user exists and is in sudo group
  ansible.builtin.user:
    name: "{{ docker_user }}"
    groups: docker
    append: true
    state: present

- name: Enable and start Docker service
  ansible.builtin.systemd:
    name: docker
    enabled: true
    state: started

```