Files
ansible-roles/roles/app_image/tasks/main.yml
T

99 lines
5.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
# tasks file for app_image
#
# Роль-инициатор сборки. Гоняет команду сборки приложения на control-хосте и
# доставляет получившийся образ на сервер через docker save/load. Тулчейн сборки
# (Go, node, …) на сервере не нужен — туда едет готовый образ.
#
# Контракт приложения (app_image_command): команда в app_image_src_dir получает
# BUILD_ID из окружения и собирает полный образ <app_image_name>:$BUILD_ID.
#
# Тег образа = случайный BUILD_ID (роль его генерит). Дедупликации по содержимому
# нет — каждый деплой везёт образ и пересоздаёт контейнер. Для ручного нечастого
# деплоя это осознанный выбор: простота важнее экономии рестарта. Старые образы
# на сервере чистит `docker image prune -af` по крону (см. playbook-system.yml).
#
# Рассчитана на один целевой хост за прогон: сборка делегируется на control-хост,
# при нескольких хостах в play повторится на каждый (мы деплоим последовательно).
#
# Выход: факт app_image_tag (= BUILD_ID) + образ <app_image_name>:<app_image_tag>
# на сервере. Тег забирает следующий кирпичик (рендер compose).
- name: "Validate role input"
ansible.builtin.assert:
that:
# Формат имени docker-образа: он же идёт в имя tar-файла (vars/main.yml),
# поэтому '/' и прочее ломало бы путь и docker-референс.
- app_image_name is string and app_image_name is match('^[a-z0-9][a-z0-9._-]*$')
- app_image_src_dir is string and app_image_src_dir | length > 0
- app_image_command is string and app_image_command | length > 0
fail_msg: >-
app_image_name — валидное имя docker-образа (^[a-z0-9][a-z0-9._-]*$);
app_image_src_dir и app_image_command — непустые строки
quiet: true
- name: "Generate build id (image tag)"
ansible.builtin.set_fact:
app_image_tag: "{{ lookup('ansible.builtin.password', '/dev/null chars=ascii_lowercase,digits length=16') }}"
- name: "Build image and deliver it to server"
# В --check command-таски пропускаются, tar не создаётся и copy упал бы «нет
# файла на контроллере». Пропускаем всю доставку — факт app_image_tag уже
# выставлен, поэтому рендер compose ниже честно покажет diff со своим тегом.
when: "not ansible_check_mode"
block:
- name: "Build image locally via app contract"
delegate_to: localhost
# Сборка идёт от локального юзера. Инвентарь включает become глобально, но
# локальная сборка под root не нужна — фиксируем инвариант явно.
become: false
ansible.builtin.command:
cmd: "{{ app_image_command }}"
chdir: "{{ app_image_src_dir }}"
environment:
BUILD_ID: "{{ app_image_tag }}"
# Локальная сборка — средство доставки; факт изменения системы (сервера)
# отражает загрузка образа ниже.
changed_when: false
- name: "Save image to tar locally"
delegate_to: localhost
become: false
ansible.builtin.command:
cmd: "docker save --output {{ app_image_local_tar }} {{ app_image_name }}:{{ app_image_tag }}"
changed_when: false
- name: "Copy image tar to server"
ansible.builtin.copy:
src: "{{ app_image_local_tar }}"
dest: "{{ app_image_remote_tar }}"
mode: "0644"
- name: "Load image on server"
ansible.builtin.command:
cmd: "docker load --input {{ app_image_remote_tar }}"
changed_when: true
always:
- name: "Remove local image tar"
delegate_to: localhost
become: false
ansible.builtin.file:
path: "{{ app_image_local_tar }}"
state: absent
- name: "Remove remote image tar"
ansible.builtin.file:
path: "{{ app_image_remote_tar }}"
state: absent
# Локальный тег — временная ручка (на сервер образ уехал через save/load).
# Снимаем, чтобы control-хост не копил <app>:<random> от каждого прогона.
- name: "Remove transient local image tag"
delegate_to: localhost
become: false
ansible.builtin.command:
cmd: "docker image rm {{ app_image_name }}:{{ app_image_tag }}"
changed_when: false
failed_when: false