Рефакторинг: вынес запуск ролей в отдельный файл deploy.yml

- Создан файл roles/deploy.yml с блоком запуска роли nginx
- Обновлен molecule/default/site.yml для импорта deploy.yml
- Улучшена модульность структуры проекта
- Автор: Сергей Антропов
This commit is contained in:
2025-10-22 22:34:07 +03:00
parent 0b981ca61e
commit c99df83bad
23 changed files with 661 additions and 659 deletions

View File

@@ -0,0 +1,52 @@
---
- hosts: localhost
gather_facts: false
vars:
# перечисли файлы/глобы, которые нужно временно расшифровать
vault_targets:
- /ansible/vault/secrets.yml
# добавляй сюда свои пути (host_vars/*/vault.yml, group_vars/*/vault.yml, и т.п.)
tasks:
- name: Install collections
community.docker.docker_container_exec:
container: ansible
command: bash -lc "ansible-galaxy collection install -r /ansible/requirements.yml --force --no-deps --upgrade >/dev/null 2>&1 || true"
- name: Decrypt vault targets (best-effort)
community.docker.docker_container_exec:
container: ansible
command: >
bash -lc '
set -euo pipefail;
for p in {{ vault_targets | map('quote') | join(' ') }}; do
if [ -e "$p" ]; then
echo "[vault] decrypt $p";
ansible-vault decrypt --vault-password-file /ansible/vault-password.txt "$p" || true;
fi
done
'
- name: Run external playbook (your lab play)
community.docker.docker_container_exec:
container: ansible
command: >
bash -lc "
ANSIBLE_ROLES_PATH=/ansible/roles
ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /ansible/molecule/default/site.yml
"
- name: Re-encrypt vault targets (always)
community.docker.docker_container_exec:
container: ansible
command: >
bash -lc '
set -euo pipefail;
for p in {{ vault_targets | map('quote') | join(' ') }}; do
if [ -e "$p" ]; then
echo "[vault] encrypt $p";
ansible-vault encrypt --encrypt-vault-id default --vault-password-file /ansible/vault-password.txt "$p" || true;
fi
done
'
ignore_errors: true

107
molecule/default/create.yml Normal file
View File

@@ -0,0 +1,107 @@
---
- hosts: localhost
gather_facts: false
vars_files:
- ../presets/default.yml
tasks:
- name: Ensure network exists
community.docker.docker_network:
name: "{{ docker_network }}"
state: present
# SYSTEMD nodes
- name: Pull systemd images
community.docker.docker_image:
name: "{{ images[item.family] }}"
source: pull
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control: { label: "{{ item.name }}" }
- name: Start systemd nodes
community.docker.docker_container:
name: "{{ item.name }}"
image: "{{ images[item.family] }}"
networks: [ { name: "{{ docker_network }}" } ]
privileged: "{{ systemd_defaults.privileged }}"
command: "{{ systemd_defaults.command }}"
volumes: "{{ (systemd_defaults.volumes | default([])) + (item.volumes | default([])) }}"
tmpfs: "{{ (systemd_defaults.tmpfs | default([])) + (item.tmpfs | default([])) }}"
capabilities: "{{ (systemd_defaults.capabilities | default([])) + (item.capabilities | default([])) }}"
published_ports: "{{ item.publish | default([]) }}"
env: "{{ item.env | default({}) }}"
state: started
restart_policy: unless-stopped
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control: { label: "{{ item.name }}" }
# DinD nodes
- name: Start DinD nodes (docker:27-dind)
community.docker.docker_container:
name: "{{ item.name }}"
image: "docker:27-dind"
privileged: true
environment: { DOCKER_TLS_CERTDIR: "" }
networks: [ { name: "{{ docker_network }}" } ]
published_ports: "{{ item.publish | default([]) }}"
volumes: [ "{{ item.name }}-docker:/var/lib/docker" ]
state: started
restart_policy: unless-stopped
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}"
loop_control: { label: "{{ item.name }}" }
# DOoD nodes (mount docker.sock)
- name: Start DOoD nodes (systemd + docker.sock mount)
community.docker.docker_container:
name: "{{ item.name }}"
image: "{{ images[item.family] }}"
networks: [ { name: "{{ docker_network }}" } ]
privileged: "{{ systemd_defaults.privileged }}"
command: "{{ systemd_defaults.command }}"
volumes: "{{ (systemd_defaults.volumes | default([])) + ['/var/run/docker.sock:/var/run/docker.sock'] + (item.volumes | default([])) }}"
tmpfs: "{{ (systemd_defaults.tmpfs | default([])) + (item.tmpfs | default([])) }}"
capabilities: "{{ (systemd_defaults.capabilities | default([])) + (item.capabilities | default([])) }}"
published_ports: "{{ item.publish | default([]) }}"
env: "{{ item.env | default({}) }}"
state: started
restart_policy: unless-stopped
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list }}"
loop_control: { label: "{{ item.name }}" }
# Build groups map
- name: Build groups map
set_fact:
groups_map: "{{ groups_map | default({}) }}"
- name: Append hosts to groups
set_fact:
groups_map: "{{ groups_map | combine({ item_group: (groups_map[item_group] | default([])) + [item_name] }) }}"
loop: "{{ hosts | subelements('groups', skip_missing=True) }}"
loop_control:
label: "{{ item.0.name }}"
vars:
item_name: "{{ item.0.name }}"
item_group: "{{ item.1 }}"
# Render inventory
- name: Render inventory ini
set_fact:
inv_content: |
[all:vars]
ansible_connection=community.docker.docker
ansible_python_interpreter=/usr/bin/python3
{% for group, members in (groups_map | dictsort) %}
[{{ group }}]
{% for h in members %}{{ h }}
{% endfor %}
{% endfor %}
[all]
{% for h in hosts %}{{ h.name }}
{% endfor %}
- name: Write inventory file
copy:
dest: "{{ generated_inventory }}"
content: "{{ inv_content }}"
mode: "0644"

View File

@@ -0,0 +1,29 @@
---
- hosts: localhost
gather_facts: false
vars_files:
- ../presets/default.yml
tasks:
- name: Remove containers
community.docker.docker_container:
name: "{{ item.name }}"
state: absent
force_kill: true
loop: "{{ hosts }}"
loop_control: { label: "{{ item.name }}" }
ignore_errors: true
- name: Remove DinD volumes
community.docker.docker_volume:
name: "{{ item.name }}-docker"
state: absent
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}"
loop_control: { label: "{{ item.name }}" }
ignore_errors: true
- name: Remove network
community.docker.docker_network:
name: "{{ docker_network }}"
state: absent
ignore_errors: true

View File

@@ -0,0 +1,32 @@
---
# Универсальная конфигурация Molecule
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
driver:
name: docker
provisioner:
name: ansible
config_options:
defaults:
stdout_callback: yaml
env:
ANSIBLE_STDOUT_CALLBACK: yaml
inventory:
links:
hosts: "${MOLECULE_EPHEMERAL_DIRECTORY}/inventory/hosts.ini"
playbooks:
create: create.yml
converge: converge.yml
destroy: destroy.yml
dependency:
name: galaxy
verifier:
name: ansible
lint: |-
set -e
ansible-lint /workspace/roles/

29
molecule/default/site.yml Normal file
View File

@@ -0,0 +1,29 @@
---
# Универсальный плейбук для тестирования
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
- name: Base deps
hosts: all
become: true
tasks:
- name: Update apt cache (Debian)
apt:
update_cache: true
when: ansible_os_family == 'Debian'
changed_when: false
- name: Common tools
raw: dnf install -y curl jq ca-certificates iproute2 iputils procps-ng net-tools sudo vim || yum install -y curl jq ca-certificates iproute2 iputils procps-ng net-tools sudo vim || apt-get update && apt-get install -y curl jq ca-certificates iproute2 iputils-ping procps net-tools sudo vim || true
ignore_errors: true
- name: Update ansible-lint
raw: pip install --upgrade ansible-lint --quiet --no-warn-script-location || true
ignore_errors: true
- name: Install ansible collections
raw: ansible-galaxy collection install -r requirements.yml --force --no-deps --upgrade || true
ignore_errors: true
- import_playbook: ../../roles/deploy.yml