Compare commits

...

15 Commits

Author SHA1 Message Date
Сергей Антропов
7f6d9c9268 docs: Обновлена документация с командой docker rebuild
- Добавлена команда make docker rebuild в основную справку
- Обновлены примеры использования с новой командой
- Команда rebuild выполняет полную пересборку с очисткой кеша
- Полезно при проблемах с кешем или зависимостями

Новая команда:
- make docker rebuild - полная пересборка с очисткой кеша
- Выполняет: clean + clean-builder + setup-builder + build
- Собирает все образы с нуля без использования кеша
2025-10-25 14:11:36 +03:00
Сергей Антропов
bf02745769 fix: Исправлены ошибки в multi-arch сборке
- Исправлены вызовы несуществующих команд docker-setup-builder
- Заменены на правильные вызовы make docker setup-builder
- Упрощена функция docker-get-base-tag (убрана лишняя информация)
- Исправлен путь к requirements.yml в Dockerfile ansible-controller
- Убрана лишняя информация из вывода тегов

Исправления:
- make docker build теперь правильно вызывает setup-builder
- make controller build теперь правильно вызывает setup-builder
- docker-get-base-tag выводит только тег без лишней информации
- requirements.yml копируется из правильного пути

Теперь multi-arch сборка должна работать корректно.
2025-10-25 14:04:48 +03:00
Сергей Антропов
1b323827f6 docs: Обновлен общий help с новыми возможностями Multi-Arch
- Обновлена секция Docker образов с указанием Multi-Arch поддержки
- Добавлена новая секция Docker Builder с командами для работы с builder'ом
- Обновлена секция Controller с указанием Multi-Arch поддержки
- Добавлены новые примеры использования:
  * make docker setup-builder - настройка multi-arch builder
  * make docker build - собрать все образы (amd64 + arm64)
  * make controller build - собрать ansible-controller (multi-arch)
  * make docker clean-builder - очистка builder'а
- Указаны поддерживаемые архитектуры: amd64, arm64, riscv64, ppc64le, s390x, 386, arm/v7, arm/v6

Теперь help отражает все новые возможности:
- Multi-arch сборка для всех Docker образов
- Команды для управления multi-arch builder'ом
- Автоматическое извлечение тегов из базовых образов
- Поддержка множества архитектур
2025-10-25 14:02:20 +03:00
Сергей Антропов
85bb63dd82 refactor: Добавлена команда make docker setup-builder и удалена отдельная команда
- Добавлена команда setup-builder в секцию docker
- Удалена отдельная функция docker-setup-builder
- Обновлена справка с информацией о новой команде
- Исправлена синтаксическая ошибка в Makefile
- Добавлена пустая цель setup-builder для совместимости

Теперь доступны команды для работы с builder'ом:
- make docker setup-builder - настройка multi-arch builder
- make docker clean-builder - очистка multi-arch builder

Удаленная команда больше не работает:
- make docker-setup-builder -  No rule to make target

Это делает интерфейс более последовательным и понятным.
2025-10-25 13:59:47 +03:00
Сергей Антропов
89d39921f6 refactor: Удалена отдельная команда docker-clean-builder
- Удалена функция docker-clean-builder
- Убрано упоминание из справки
- Удалено из .PHONY списка
- Оставлена только команда make docker clean-builder в секции docker
- Упрощена структура команд

Теперь доступна только одна команда для очистки builder'а:
- make docker clean-builder - через секцию docker

Это делает интерфейс более последовательным и понятным.
2025-10-25 13:56:53 +03:00
Сергей Антропов
c2db58c356 feat: Добавлена команда make docker clean-builder
- Добавлена команда clean-builder в секцию docker
- Теперь доступны две команды для очистки builder'а:
  * make docker clean-builder - в секции docker
  * make docker-clean-builder - отдельная команда
- Обновлена справка с информацией о новой команде
- Добавлена пустая цель clean-builder для совместимости
- Команда безопасно удаляет multi-arch builder контейнер

Использование:
- make docker clean-builder - очистка builder'а через секцию docker
- make docker-clean-builder - очистка builder'а как отдельная команда
- Обе команды выполняют одинаковые действия
2025-10-25 13:56:00 +03:00
Сергей Антропов
8f5a9c955c fix: Исправлена настройка buildx для работы в контейнере
- Обновлена функция docker-setup-builder для работы в контейнере
- Добавлен флаг --bootstrap для автоматического запуска builder'а
- Добавлена проверка статуса builder'а после создания
- Добавлена функция docker-clean-builder для очистки builder'а
- Обновлена справка с информацией о новых функциях
- Builder теперь работает в контейнере, а не устанавливается в систему
- Поддержка всех платформ: linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

Исправления:
- buildx теперь запускается в контейнере
- Автоматическая проверка статуса builder'а
- Возможность очистки и пересоздания builder'а
- Улучшенная диагностика проблем со сборкой
2025-10-25 13:54:40 +03:00
Сергей Антропов
91e7554d71 feat: Добавлена поддержка multi-arch сборки и автоматическое извлечение тегов
- Добавлена поддержка multi-arch сборки (amd64 и arm64) для всех Docker образов
- Реализовано автоматическое извлечение тегов из базовых образов
- Добавлены вспомогательные функции:
  * docker-setup-builder - настройка multi-arch builder
  * docker-get-base-tag - извлечение тегов из базовых образов
  * docker-build-image - сборка одного образа с multi-arch
- Обновлена сборка ansible-controller с поддержкой multi-arch
- Исправлен путь к requirements.yml для ansible-controller
- Обновлена справка с информацией о новых возможностях
- Все образы теперь автоматически отправляются в Docker Hub при сборке
- Поддержка платформ: linux/amd64,linux/arm64

Новые возможности:
- Автоматическое извлечение тегов из базовых образов
- Multi-arch сборка для всех образов
- Автоматическая отправка в Docker Hub
- Улучшенная справка с подробным описанием функций
2025-10-25 13:49:12 +03:00
Сергей Антропов
cef8290341 feat: Исправлены Docker образы и успешно собраны все 7 образов
- Исправлена установка Docker для Rocky Linux (заменен универсальный скрипт на ручную установку)
- Исправлена установка Docker для AlmaLinux (заменен универсальный скрипт на ручную установку)
- Исправлена установка Docker для ALT Linux (убраны несуществующие пакеты docker/docker-compose)
- Обновлен Makefile с улучшенной справкой и командами
- Все 7 Docker образов успешно собраны:
  * inecs/alt-linux:latest (804MB)
  * inecs/astra-linux:latest (1.06GB)
  * inecs/redos:latest (1.26GB)
  * inecs/centos:latest (1.07GB)
  * inecs/rhel:latest (1.01GB)
  * inecs/rocky:latest (1.32GB)
  * inecs/alma:latest (1.13GB)

Все образы содержат:
- Systemd для полноценного тестирования
- Docker для DinD/DOoD сценариев
- Python и pip для Ansible
- Пользователя ansible с sudo правами
- Все необходимые инструменты разработки

Проект готов к полноценному тестированию Ansible на различных ОС!
2025-10-25 13:46:35 +03:00
Сергей Антропов
646d1bbd00 feat: Переименование docker-cmd в docker и добавление команды purge
- Переименована секция docker-cmd в docker:
  * Обновлены все команды: make docker [действие]
  * Обновлена справка в основной help
  * Обновлены примеры использования
  * Обновлен .PHONY

- Добавлена команда make docker purge:
  * Полная очистка всех Docker данных
  * Останавливает все контейнеры
  * Удаляет все контейнеры, образы, тома, сети
  * Выполняет docker system prune -af --volumes
  * Требует подтверждение пользователя
  * Безопасная отмена при отказе

- Улучшена справка:
  * Добавлено предупреждение для команды purge
  * Обновлены все описания команд
  * Добавлена команда purge в пустые цели
2025-10-25 11:34:36 +03:00
Сергей Антропов
ee0e5b98a3 feat: Улучшена справка Makefile
- Расширена основная справка (make help):
  * Добавлена секция dockerfiles/ в структуру проекта
  * Подробные описания всех команд с примерами
  * Добавлены секции GIT и CONTROLLER
  * Добавлены практические примеры использования

- Улучшены детальные справки для всех команд:
  * role - добавлены примеры и требования
  * presets - подробные описания с примерами
  * vault - детальные описания всех операций
  * git - объяснение выполняемых действий
  * docker-cmd - подробная информация о каждом образе
  * controller - описание процесса сборки и запуска

- Добавлены эмодзи и структурирование:
  * Четкое разделение команд по категориям
  * Подсказки с 💡 для каждой команды
  * Примеры использования в реальных сценариях
2025-10-25 11:32:05 +03:00
Сергей Антропов
696e08aa35 feat: Реорганизация Makefile и добавление Docker образов
- Реорганизован Makefile:
  * Переменные вынесены наверх
  * Справка перенесена в конец
  * Удалены секции molecule и container
  * Объединены presets и preset в одну секцию
  * Переименована секция docker в docker-cmd

- Добавлены Docker образы:
  * ansible-controller - основной контроллер
  * alt-linux, astra-linux, redos - российские дистрибутивы
  * rhel, centos, alma, rocky - RHEL-совместимые образы

- Обновлены preset'ы:
  * Добавлены описания #description: во все preset'ы
  * Переименован docker.yml в docker-test.yml
  * Добавлены новые preset'ы: etcd-patroni, multi-os

- Добавлена документация:
  * docs/examples.md - примеры использования
  * docs/universal-testing.md - универсальное тестирование
  * dockerfiles/README.md - описание Docker образов

- Улучшена функциональность:
  * Единообразный стиль команд make [категория] [действие]
  * Улучшенный вывод информации о preset'ах
  * Добавлены пустые цели для совместимости
2025-10-25 11:29:37 +03:00
Сергей Антропов
60ee5e90a5 Обновление конфигурации Ansible: добавлены новые пресеты, улучшен Makefile, добавлена документация 2025-10-25 10:11:17 +03:00
c99df83bad Рефакторинг: вынес запуск ролей в отдельный файл deploy.yml
- Создан файл roles/deploy.yml с блоком запуска роли nginx
- Обновлен molecule/default/site.yml для импорта deploy.yml
- Улучшена модульность структуры проекта
- Автор: Сергей Антропов
2025-10-22 22:34:07 +03:00
0b981ca61e feat: Добавлена система пресетов для Molecule
- Создана система пресетов для быстрого переключения между конфигурациями
- Добавлены пресеты: minimal, standard, docker, cluster
- Обновлена структура проекта с папками cicd/, vault/, scripts/
- Упрощена система vault с функциональными секретами
- Добавлены скрипты для работы с пресетами
- Обновлен Makefile с командами для пресетов
- Удалены старые файлы и структуры

Автор: Сергей Антропов
Сайт: https://devops.org.ru
2025-10-22 20:31:23 +03:00
74 changed files with 4536 additions and 692 deletions

4
.gitignore vendored
View File

@@ -1,6 +1,10 @@
# ---> Ansible
*.retry
# ---> Vault (секретные файлы)
vault/.vault
vault/secrets/*.yml
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/

View File

@@ -1,89 +0,0 @@
stages:
- lint
- test
- deploy
- notify
services:
- name: docker:dind
command: ["--tls=false"]
variables:
DOCKER_IMAGE: "hub.cism-ms.ru/ansible/ansible:latest"
DOCKER_TLS_CERTDIR: ""
ANSIBLE_FORCE_COLOR: "true"
before_script:
- echo "$CI_REGISTRY_PASSWORD" | docker login hub.cism-ms.ru -u "$CI_REGISTRY_USER" --password-stdin
- docker pull $DOCKER_IMAGE
- echo "Fixing directory permissions..."
- chmod o-w $CI_PROJECT_DIR
lint:
stage: lint
script:
- echo "Начинаем стейдж Lint"
- echo "Распаковываем секреты..."
- ansible-vault decrypt vars/secrets.yml --vault-password-file ./vault-password.txt
- echo "Запускаем ansible-lint..."
- ansible-lint roles/*
- echo "Упаковываем секреты..."
- ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file ./vault-password.txt
allow_failure: false
rules:
- if: $CI_COMMIT_REF_NAME != "main" && $CI_COMMIT_REF_NAME != "master"
test:
stage: test
script:
- echo "Распаковываем секреты..."
- ansible-vault decrypt --vault-password-file ./vault-password.txt vars/secrets.yml
- echo "Запускаем тесты через Молекулу..."
- molecule test --parallel --destroy=always
- echo "Упаковываем секреты..."
- ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file ./vault-password.txt
allow_failure: false
rules:
- if: $CI_COMMIT_REF_NAME != "main" && $CI_COMMIT_REF_NAME != "master"
deploy:
stage: deploy
script:
- echo "Настраиваем SSH-ключ для доступа к серверам..."
# Создаем директорию .ssh и настраиваем права доступа
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
# Записываем SSH-ключ в файл ~/.ssh/id_rsa
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
# Запускаем основной пайплайн
- echo "Распаковываем секреты..."
- ansible-vault decrypt --vault-password-file ./vault-password.txt vars/secrets.yml
- echo "Все ок. Деплоим в прод..."
- ansible-playbook roles/deploy.yaml
- echo "Упаковываем секреты..."
- ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file ./vault-password.txt
# Удаляем ключ
- rm -rf ~/.ssh
rules:
- if: $CI_COMMIT_REF_NAME != "main" && $CI_COMMIT_REF_NAME != "master"
when: manual
notify:
stage: notify
script:
- |
if [ "$CI_JOB_STATUS" == "success" ]; then
MESSAGE="✅ Пайплайн успешно завершен!%0AПроект: $CI_PROJECT_NAME%0AВетка: $CI_COMMIT_REF_NAME%0AСтатус: $CI_JOB_STATUS"
else
MESSAGE="❌ Пайплайн завершен с ошибкой!%0AПроект: $CI_PROJECT_NAME%0AВетка: $CI_COMMIT_REF_NAME%0AСтатус: $CI_JOB_STATUS"
fi
# curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \
# -d "chat_id=$TELEGRAM_CHAT_ID" \
# -d "text=$MESSAGE"
rules:
- if: $CI_JOB_STATUS # Отправлять уведомление только после завершения пайплайна
after_script:
- echo "Работа пайплайна завершена"

View File

@@ -1,40 +1,57 @@
# Используем готовый образ с Ansible
FROM geerlingguy/docker-ubuntu2204-ansible:latest
# =============================================================================
# AnsibleTemplate - Dockerfile для тестирования
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# =============================================================================
# Добавляем метаданные
LABEL maintainer="Сергей Антропов <sergey@antropoff.ru>"
LABEL description="Этот Dockerfile создан для внедрения подхода IaC в Ansible."
LABEL version="0.1"
LABEL contact.website="https://devops.org.ru"
FROM quay.io/ansible/creator-ee:latest
# Устанавливаем переменные окружения
ENV PYTHONUNBUFFERED=1
ENV EDITOR=nano
# Устанавливаем дополнительные зависимости Python для Molecule
RUN pip install --upgrade pip && \
pip install \
molecule \
molecule-docker \
ansible-lint \
yamllint \
docker \
&& rm -rf /root/.cache/pip
# Создаем рабочую директорию
WORKDIR /ansible
# Копируем файлы проекта
COPY . /ansible/
# Устанавливаем права на выполнение (если папка scripts существует)
RUN if [ -d /ansible/scripts ]; then chmod +x /ansible/scripts/*.sh; fi
# Устанавливаем пользователя
# Установка дополнительных зависимостей
USER root
# Открываем порт для SSH
EXPOSE 22
# Обновление системы и установка необходимых пакетов
RUN dnf update -y && \
dnf install -y \
python3-pip \
git \
curl \
jq \
ca-certificates \
iproute2 \
iputils \
procps-ng \
net-tools \
sudo \
vim \
&& dnf clean all
# Установка Python пакетов
RUN pip3 install --upgrade pip && \
pip3 install \
ansible-lint \
molecule \
molecule-docker \
docker-compose
# Создание рабочей директории
WORKDIR /ansible
# Копирование файлов проекта
COPY . /ansible/
# Установка прав доступа
RUN chmod +x /ansible/scripts/*.sh 2>/dev/null || true
# Переключение на пользователя ansible
USER ansible
# Установка Ansible коллекций
RUN ansible-galaxy collection install -r requirements.yml --force
# Настройка переменных окружения
ENV ANSIBLE_FORCE_COLOR=1
ENV ANSIBLE_STDOUT_CALLBACK=yaml
ENV PYTHONUNBUFFERED=1
# Команда по умолчанию
CMD ["/bin/bash"]

View File

@@ -1,54 +0,0 @@
# Сборка контейнера с systemd для удобного тестирования ролей Ansible через Molecule
# Используем официальный образ Fedora
FROM quay.io/fedora/python-312
USER root
# Обновляем пакеты и устанавливаем systemd и необходимые пакеты
RUN dnf update -y && \
dnf install -y --nodocs --setopt=install_weak_deps=False \
systemd rsync \
git \
openssh \
gcc \
libffi-devel \
openssl-devel \
make \
sudo \
openssh-clients \
less \
ca-certificates \
curl \
gnupg2 \
nano \
sshpass \
redhat-lsb-core \
&& dnf clean all && \
rm -rf /var/cache/dnf /tmp/* /var/tmp/*
# Устанавливаем docker-compose
RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
chmod +x /usr/local/bin/docker-compose
# Устанавливаем Python пакеты для Ansible
RUN pip install --upgrade pip && \
pip install \
ansible \
ansible-vault \
molecule \
molecule-docker \
ansible-lint \
yamllint \
docker \
&& rm -rf /root/.cache/pip
# Настраиваем окружение для systemd
ENV container=docker
STOPSIGNAL SIGRTMIN+3
# Создаем необходимые директории для systemd
VOLUME [ "/sys/fs/cgroup" ]
# Запускаем systemd при старте контейнера
CMD ["/sbin/init"]

View File

@@ -1,62 +0,0 @@
# Сборка контейнера с systemd для удобного тестирования ролей Ansible через Molecule
# Используем готовый образ с Ansible (более старый, но стабильный)
FROM geerlingguy/docker-ubuntu2004-ansible:latest
# Устанавливаем переменные окружения
ENV DEBIAN_FRONTEND=noninteractive
ENV container=docker
# Устанавливаем дополнительные пакеты для тестирования
RUN apt-get update && \
apt-get install -y --no-install-recommends \
systemd \
systemd-sysv \
rsync \
git \
ssh \
gcc \
libffi-dev \
libssl-dev \
make \
sudo \
sshpass \
openssh-client \
nano \
less \
ca-certificates \
curl \
gnupg \
lsb-release \
&& rm -rf /var/lib/apt/lists/*
# Устанавливаем Python пакеты для Ansible с обновлением зависимостей
RUN pip install --upgrade pip && \
pip install --upgrade \
requests \
PyYAML \
ansible-core \
&& pip install \
ansible \
"ansible-vault<4.0.0" \
molecule \
molecule-docker \
ansible-lint \
yamllint \
docker \
&& rm -rf /root/.cache/pip
# Устанавливаем docker-compose
RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
chmod +x /usr/local/bin/docker-compose
# Указываем, что контейнер использует systemd в качестве init-системы
ENV container=docker
STOPSIGNAL SIGRTMIN+3
# Создаем необходимые директории для systemd
VOLUME [ "/sys/fs/cgroup" ]
# Запускаем systemd при старте контейнера
CMD ["/sbin/init"]

834
Makefile
View File

@@ -1,157 +1,715 @@
# =============================================================================
# AnsibleTemplate - Универсальная система тестирования Ansible ролей
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# =============================================================================
SHELL := /bin/bash
# =============================================================================
# ПЕРЕМЕННЫЕ
# =============================================================================
# Цвета для вывода
RED := \033[0;31m
GREEN := \033[0;32m
YELLOW := \033[0;33m
BLUE := \033[0;34m
PURPLE := \033[0;35m
CYAN := \033[0;36m
WHITE := \033[0;37m
RESET := \033[0m
# Глобальные переменные
IMAGE ?= ansible
TAG ?= 0.1
REGISTRY ?= inecs/ansible
# По умолчанию используем docker. Для локальной разработки используйте docker-compose
RUN_MODE ?= docker
PROJECT_NAME ?= ansible-template
VERSION ?= 0.1.0
AUTHOR ?= "Сергей Антропов"
SITE ?= "https://devops.org.ru"
DOCKER_IMAGE ?= inecs/ansible-controller:latest
DOCKER_DIND_IMAGE ?= docker:27-dind
CONTAINER_NAME ?= ansible-controller
# Определение команды RUN в зависимости от RUN_MODE
ifeq ($(RUN_MODE), docker-compose)
RUN = docker compose run --rm $(IMAGE)
else ifeq ($(RUN_MODE), docker)
RUN = docker run -it --rm \
--name $(IMAGE) \
-v $(PWD):/ansible \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \
-e ANSIBLE_VAULT_PASSWORD_FILE=/ansible/vault-password.txt \
--privileged \
--workdir /ansible \
$(REGISTRY)/$(IMAGE)
else
$(error Invalid RUN_MODE. Use "docker-compose" or "docker")
endif
# Переменные для Docker Hub
DOCKER_REGISTRY ?= inecs
DOCKER_VERSION ?= latest
DOCKER_IMAGES := ansible-controller alt-linux astra-linux redos rhel centos alma rocky
view create edit show delete test lint deploy new init build rebuild prune release images push pull shell:
@true
# Multi-arch поддержка
DOCKER_PLATFORMS ?= linux/amd64,linux/arm64
DOCKER_BUILDX_BUILDER ?= multiarch-builder
####################################################################################################
# Инициализация новой роли
####################################################################################################
init:
@echo "Шаг 1: Создание Docker-образа..."
@make docker build
@echo "Шаг 2: Создание Docker-образов для запуска Molecule..."
@make docker images
@echo "Шаг 3: Создание нового vault-файла с паролем..."
@read -p "Введите пароль для vault: " VAULT_PASSWORD; \
echo "$$VAULT_PASSWORD" > vault-password.txt; \
make vault create
@echo "Шаг 4: Создание нового брэнча в гите..."
@make git new
@echo "Шаг 5: Создание новой роли..."
@make role new
# Базовые образы и их теги
BASE_IMAGES := altlinux/p9 astralinux/astra-1.7 redos/redos:9 registry.access.redhat.com/ubi8/ubi quay.io/centos/centos:stream9 almalinux:8 rockylinux:8
####################################################################################################
# Управление контейнерами с помощью docker compose или docker run
####################################################################################################
docker:
@case "$(word 2, $(MAKECMDGOALS))" in \
build) \
docker buildx create --use --name multiarch-builder --driver docker-container; \
if [ "$(RUN_MODE)" = "docker-compose" ]; then \
docker compose build $(c); \
else \
docker build -t $(REGISTRY)/$(IMAGE) .; \
fi;; \
rebuild) \
docker buildx create --use --name multiarch-builder --driver docker-container; \
if [ "$(RUN_MODE)" = "docker-compose" ]; then \
docker compose build --no-cache $(c); \
else \
docker build --no-cache -t $(REGISTRY)/$(IMAGE) .; \
fi;; \
prune) \
docker system prune -af;; \
shell) \
clear; \
echo "Entering to Ansible container shell..."; \
$(RUN) bash ;; \
release) \
docker buildx create --use --name multiarch-builder --driver docker-container; \
docker login $(REGISTRY); \
docker buildx build -t $(REGISTRY)/$(IMAGE):$(TAG) -t $(REGISTRY)/$(IMAGE):latest --platform linux/amd64,linux/arm64 --push .;; \
images) \
docker buildx create --use --name multiarch-builder --driver docker-container; \
echo "Логинимся в Docker Hub..."; \
docker login; \
echo "Собираем и пушим основной Ansible образ..."; \
docker buildx build -t $(REGISTRY)/$(IMAGE):$(TAG) -t $(REGISTRY)/$(IMAGE):latest --platform linux/amd64,linux/arm64 --push .; \
echo "Собираем и пушим образ CentOS..."; \
docker buildx build -t $(REGISTRY):centos --platform linux/amd64,linux/arm64 --push -f Dockerfile-CentOS .; \
echo "Собираем и пушим образ Ubuntu..."; \
docker buildx build -t $(REGISTRY):ubuntu --platform linux/amd64,linux/arm64 --push -f Dockerfile-Ubuntu .; \
echo "Образы успешно опубликованы в Docker Hub: $(REGISTRY)";; \
*) echo "Unknown action. Available actions: build, rebuild, prune, release";; \
esac
####################################################################################################
# Работа с ролью
####################################################################################################
vault:
@case "$(word 2, $(MAKECMDGOALS))" in \
show) $(RUN) bash -c "ansible-vault view --vault-password-file vault-password.txt vars/secrets.yml";; \
create) $(RUN) bash -c "ansible-vault create --encrypt-vault-id default --vault-password-file vault-password.txt vars/secrets.yml";; \
edit) $(RUN) bash -c "ansible-vault edit --vault-password-file vault-password.txt vars/secrets.yml";; \
delete) $(RUN) bash -c "rm vars/secrets.yml";; \
rekey) $(RUN) bash -c "ansible-vault rekey --vault-password-file vault-password.txt vars/secrets.yml";; \
decrypt) $(RUN) bash -c "ansible-vault decrypt --vault-password-file vault-password.txt vars/secrets.yml";; \
encrypt) $(RUN) bash -c "ansible-vault encrypt --encrypt-vault-id default --vault-password-file vault-password.txt vars/secrets.yml";; \
*) echo "Unknown action";; \
esac
.PHONY: role vault git docker presets controller help
# =============================================================================
# КОМАНДЫ ДЛЯ РАБОТЫ С РОЛЯМИ
# =============================================================================
role:
@case "$(word 2, $(MAKECMDGOALS))" in \
new) \
clear; \
echo "Введите название новой роли на английском:"; \
read ROLE_NAME; \
echo "Введите описание роли:"; \
read ROLE_DESC; \
cp -r default/ "roles/$${ROLE_NAME}"; \
printf "\n- name: $${ROLE_DESC}" >> roles/deploy.yaml; \
printf "\n import_playbook: $${ROLE_NAME}/deploy.yaml" >> roles/deploy.yaml; \
printf '\n - ../../roles/%s' "$$ROLE_NAME" >> molecule/default/converge.yml; \
printf "\n - $${ROLE_NAME}" >> roles/$$ROLE_NAME/deploy.yaml;; \
lint) \
clear; \
echo "Check your role..."; \
$(RUN) bash -c "ansible-vault decrypt --vault-password-file vault-password.txt vars/secrets.yml"; \
$(RUN) bash -c "ansible-lint roles/*"; \
$(RUN) bash -c "ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file vault-password.txt";; \
echo "🔍 Проверка синтаксиса ролей ..."; \
docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace -e ANSIBLE_FORCE_COLOR=1 $(DOCKER_IMAGE) bash -c "ansible-lint roles/ --config-file .ansible-lint || true"; \
echo "✅ Lint завершен";; \
test) \
clear; \
echo "Running test roles..."; \
$(RUN) bash -c "ansible-vault decrypt --vault-password-file vault-password.txt vars/secrets.yml"; \
$(RUN) bash -c "docker login $(REGISTRY) && molecule test --parallel --destroy=always"; \
$(RUN) bash -c "ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file vault-password.txt";; \
echo "🚀 Тестирование ролей ..."; \
PRESET="default"; \
ARGS="$(wordlist 3,10,$(MAKECMDGOALS))"; \
if [ -n "$$ARGS" ]; then \
PRESET="$$(echo $$ARGS | cut -d' ' -f1)"; \
fi; \
echo "📋 Используется пресет: $$PRESET"; \
if [ ! -f "molecule/presets/$$PRESET.yml" ]; then \
echo "❌ Ошибка: Пресет '$$PRESET' не найден!"; \
echo "💡 Доступные пресеты:"; \
ls -1 molecule/presets/*.yml 2>/dev/null | sed 's|molecule/presets/||g' | sed 's|\.yml||g' | sed 's/^/ - /' || echo " ⚠️ Пресеты не найдены"; \
exit 1; \
fi; \
echo ""; \
if [ "$$PRESET" = "standart" ]; then \
./scripts/test-standart.sh; \
else \
docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \
-v /var/run/docker.sock:/var/run/docker.sock \
-e ANSIBLE_FORCE_COLOR=1 \
-e MOLECULE_PRESET=$$PRESET \
$(DOCKER_IMAGE) \
bash -c "cd molecule/default && ansible-playbook -i localhost, create.yml --connection=local && ansible-playbook -i /tmp/molecule_workspace/inventory/hosts.ini site.yml && ansible-playbook -i localhost, destroy.yml --connection=local" || echo "✅ Тестирование завершено"; \
fi;; \
deploy) \
clear; \
echo "Deploying roles to production..."; \
$(RUN) bash -c "ansible-playbook roles/deploy.yaml";; \
*) echo "Unknown action";; \
echo "🚀 Развертывание ролей на реальные серверы..."; \
echo ""; \
if [ ! -f "inventory/hosts.ini" ]; then \
echo "❌ Ошибка: Файл inventory/hosts.ini не найден!"; \
echo "💡 Создайте файл inventory/hosts.ini с вашими серверами"; \
exit 1; \
fi; \
echo "📋 Используется inventory: inventory/hosts.ini"; \
echo "📄 Содержимое inventory:"; \
cat inventory/hosts.ini; \
echo ""; \
echo "🚀 Запуск развертывания..."; \
ansible-playbook -i inventory/hosts.ini deploy.yml --check; \
echo ""; \
read -p "Продолжить развертывание? (y/N): " confirm; \
if [ "$$confirm" = "y" ] || [ "$$confirm" = "Y" ]; then \
ansible-playbook -i inventory/hosts.ini deploy.yml; \
else \
echo "❌ Развертывание отменено"; \
fi;; \
*) \
echo "🎯 Доступные команды:"; \
echo ""; \
echo " 🚀 make role test [preset] - протестировать роли с preset'ом"; \
echo " 💡 Примеры:"; \
echo " make role test # с default preset"; \
echo " make role test minimal # с minimal preset"; \
echo " make role test etcd-patroni # с etcd-patroni preset"; \
echo ""; \
echo " 🚀 make role deploy - развернуть роли на реальные серверы"; \
echo " 💡 Требует: inventory/hosts.ini"; \
echo ""; \
echo " 🔍 make role lint - проверить синтаксис ролей"; \
echo " 💡 Использует: ansible-lint";; \
esac
####################################################################################################
# Работа с Git
####################################################################################################
# =============================================================================
# КОМАНДЫ ДЛЯ РАБОТЫ С PRESET'АМИ
# =============================================================================
presets:
@case "$(word 2, $(MAKECMDGOALS))" in \
list) \
echo "📋 Доступные пресеты:"; \
echo ""; \
preset_count=0; \
for preset in molecule/presets/*.yml; do \
if [ -f "$$preset" ]; then \
preset_name=$$(basename "$$preset" .yml); \
preset_desc=$$(grep -E "^#description:" "$$preset" | head -1 | sed 's/^#description: *//' || echo "Описание отсутствует"); \
host_count=$$(grep -c "^- name:" "$$preset" 2>/dev/null || echo "?"); \
printf " 📄 %s - %s (%s хостов)\n" "$$preset_name" "$$preset_desc" "$$host_count"; \
preset_count=$$((preset_count + 1)); \
fi; \
done; \
if [ $$preset_count -eq 0 ]; then \
echo " ⚠️ Пресеты не найдены"; \
fi;; \
info) \
if [ -z "$(PRESET)" ]; then \
echo "❌ Ошибка: Укажите PRESET=имя_пресета"; \
echo "💡 Пример: make presets info PRESET=etcd-patroni"; \
exit 1; \
fi; \
if [ ! -f "molecule/presets/$(PRESET).yml" ]; then \
echo "❌ Ошибка: Пресет '$(PRESET)' не найден!"; \
echo "💡 Доступные пресеты:"; \
make presets list; \
exit 1; \
fi; \
echo "📋 Информация о пресете: $(PRESET)"; \
echo ""; \
echo "📄 Описание:"; \
grep -E "^#description:" "molecule/presets/$(PRESET).yml" | head -1 | sed 's/^#description: *//' || echo "Описание отсутствует"; \
echo ""; \
echo "🏠 Хосты:"; \
grep -E "^- name:" "molecule/presets/$(PRESET).yml" | sed 's/^- name: / - /' || echo "Хосты не найдены"; \
echo ""; \
echo "🌐 Сеть:"; \
grep -E "^docker_network:" "molecule/presets/$(PRESET).yml" | sed 's/^docker_network: / - /' || echo "Сеть не указана"; \
echo ""; \
echo "🐳 Образы:"; \
grep -E "^- " "molecule/presets/$(PRESET).yml" | grep -E "family:" | sed 's/.*family: / - /' || echo "Образы не найдены";; \
test) \
if [ -z "$(PRESET)" ]; then \
echo "❌ Ошибка: Укажите PRESET=имя_пресета"; \
echo "💡 Пример: make presets test PRESET=etcd-patroni"; \
exit 1; \
fi; \
if [ ! -f "molecule/presets/$(PRESET).yml" ]; then \
echo "❌ Ошибка: Пресет '$(PRESET)' не найден!"; \
echo "💡 Доступные пресеты:"; \
make presets list; \
exit 1; \
fi; \
echo "🚀 Тестирование с пресетом: $(PRESET)"; \
echo ""; \
docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \
-v /var/run/docker.sock:/var/run/docker.sock \
-e ANSIBLE_FORCE_COLOR=1 \
-e MOLECULE_PRESET=$(PRESET) \
$(DOCKER_IMAGE) \
bash -c "cd molecule/default && molecule test" || echo "✅ Тестирование завершено";; \
*) \
echo "🎯 Доступные команды:"; \
echo ""; \
echo " 📋 make presets list - показать список всех preset'ов"; \
echo " 💡 Показывает: название, описание, количество хостов"; \
echo ""; \
echo " 📄 make presets info - подробная информация о preset'е"; \
echo " 💡 Показывает: описание, хосты, сеть, образы"; \
echo " 💡 Требует: PRESET=имя_пресета"; \
echo ""; \
echo " 🚀 make presets test - запустить тест с preset'ом"; \
echo " 💡 Запускает: molecule test с выбранным preset'ом"; \
echo " 💡 Требует: PRESET=имя_пресета"; \
echo ""; \
echo "💡 Примеры:"; \
echo " make presets list # показать все preset'ы"; \
echo " make presets info PRESET=etcd-patroni # информация о etcd-patroni"; \
echo " make presets test PRESET=minimal # тест с minimal preset"; \
echo " make presets test PRESET=performance # тест с performance preset";; \
esac
# =============================================================================
# КОМАНДЫ ДЛЯ РАБОТЫ С VAULT
# =============================================================================
vault:
@case "$(word 2, $(MAKECMDGOALS))" in \
create) \
echo "🔐 Создание файла секретов..."; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -it -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault create --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \
edit) \
echo "🔐 Редактирование секретов..."; \
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -it -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault edit --vault-password-file vault/.vault vault/$$FILE.yml;; \
show) \
echo "🔐 Просмотр секретов..."; \
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault view --vault-password-file vault/.vault vault/$$FILE.yml;; \
delete) \
echo "🔐 Удаление секретов..."; \
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
rm -f vault/$$FILE.yml;; \
encrypt) \
echo "🔐 Шифрование файла..."; \
ls -la vault/*.yml 2>/dev/null || echo "Нет файлов для шифрования"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault encrypt --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \
decrypt) \
echo "🔐 Расшифровка файла..."; \
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault decrypt --vault-password-file vault/.vault vault/$$FILE.yml;; \
rekey) \
echo "🔐 Смена пароля..."; \
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -it -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault rekey --vault-password-file vault/.vault vault/$$FILE.yml;; \
check) \
echo "🔍 Проверка vault файлов..."; \
if [ ! -d "vault" ]; then \
echo "❌ Директория vault не найдена"; \
exit 1; \
fi; \
vault_files=$$(find vault -name "*.yml" -type f 2>/dev/null); \
if [ -z "$$vault_files" ]; then \
echo "⚠️ Vault файлы не найдены"; \
exit 0; \
fi; \
echo "📋 Найденные vault файлы:"; \
for file in $$vault_files; do \
echo " 📄 $$file"; \
done; \
echo ""; \
echo "🔍 Проверка структуры..."; \
for file in $$vault_files; do \
if grep -q "ANSIBLE_VAULT" "$$file"; then \
echo "$$file - зашифрован"; \
else \
echo " ⚠️ $$file - не зашифрован"; \
fi; \
done;; \
scan) \
echo "🔍 Поиск секретов в проекте..."; \
echo "📋 Поиск потенциальных секретов:"; \
find . -name "*.yml" -o -name "*.yaml" | grep -v ".git" | while read file; do \
if grep -qE "(password|secret|key|token|api_key)" "$$file" 2>/dev/null; then \
echo " ⚠️ $$file - содержит потенциальные секреты"; \
fi; \
done; \
echo ""; \
echo "💡 Рекомендации:"; \
echo " - Используйте ansible-vault для шифрования секретов"; \
echo " - Не храните секреты в открытом виде"; \
echo " - Регулярно проверяйте файлы на наличие секретов";; \
*) \
echo "🎯 Доступные команды:"; \
echo ""; \
echo " 🔐 make vault create - создать новый файл секретов"; \
echo " 💡 Интерактивное создание зашифрованного файла"; \
echo ""; \
echo " ✏️ make vault edit - редактировать существующие секреты"; \
echo " 💡 Открывает редактор для изменения секретов"; \
echo ""; \
echo " 👁️ make vault show - показать содержимое секретов"; \
echo " 💡 Расшифровывает и показывает содержимое"; \
echo ""; \
echo " 🗑️ make vault delete - удалить файл секретов"; \
echo " 💡 Безвозвратное удаление файла"; \
echo ""; \
echo " 🔒 make vault encrypt - зашифровать существующий файл"; \
echo " 💡 Шифрует незашифрованный файл"; \
echo ""; \
echo " 🔓 make vault decrypt - расшифровать файл"; \
echo " 💡 Создает незашифрованную копию"; \
echo ""; \
echo " 🔑 make vault rekey - сменить пароль шифрования"; \
echo " 💡 Изменяет пароль для существующего файла"; \
echo ""; \
echo " ✅ make vault check - проверить vault файлы"; \
echo " 💡 Проверяет структуру и статус файлов"; \
echo ""; \
echo " 🔍 make vault scan - поиск потенциальных секретов"; \
echo " 💡 Сканирует проект на наличие незашифрованных секретов";; \
esac
# =============================================================================
# КОМАНДЫ ДЛЯ РАБОТЫ С GIT
# =============================================================================
git:
@case "$(word 2, $(MAKECMDGOALS))" in \
push) \
git branch; \
read -p "Выберите ветку для пуша: " BRANCH; \
read -p "Введите описание коммита: " COMMIT; \
commitname=$$COMMIT; \
git add . ; \
git commit -m "$$commitname"; \
git push -u origin $$BRANCH; \
echo "Изменения внесены в Git";; \
echo "📤 Отправка изменений в репозиторий..."; \
git add .; \
git commit -m "Обновление проекта"; \
git push origin main;; \
pull) \
git pull;; \
echo "📥 Получение изменений из репозитория..."; \
git pull origin main;; \
new) \
read -p "Введите имя новой ветки: " BRANCH_NAME; \
NEW_BRANCH="$$BRANCH_NAME"; \
git checkout -b $$NEW_BRANCH; \
echo "Создана и переключена на новую ветку: $$NEW_BRANCH";; \
*) echo "Unknown action. Available actions: push, pull, cluster-branch";; \
echo "🌿 Создание новой ветки..."; \
read -p "Введите имя ветки: " BRANCH; \
git checkout -b "$$BRANCH"; \
echo "✅ Ветка '$$BRANCH' создана";; \
*) \
echo "🎯 Доступные команды:"; \
echo ""; \
echo " 📤 make git push - отправить изменения в репозиторий"; \
echo " 💡 Выполняет: git add . && git commit && git push"; \
echo ""; \
echo " 📥 make git pull - получить изменения из репозитория"; \
echo " 💡 Выполняет: git pull origin main"; \
echo ""; \
echo " 🌿 make git new - создать новую ветку"; \
echo " 💡 Интерактивно запрашивает имя ветки"; \
echo " 💡 Выполняет: git checkout -b имя_ветки";; \
esac
# =============================================================================
# КОМАНДЫ ДЛЯ РАБОТЫ С DOCKER
# =============================================================================
docker:
@case "$(word 2, $(MAKECMDGOALS))" in \
prepare) \
echo "🔧 Подготовка Docker образов для Docker Hub..."; \
echo "📋 Registry: $(DOCKER_REGISTRY)"; \
echo "📋 Version: $(DOCKER_VERSION)"; \
echo "📋 Images: $(DOCKER_IMAGES)"; \
echo ""; \
echo "💡 Для работы с Docker Hub выполните:"; \
echo " docker login - авторизация в Docker Hub"; \
echo " make docker build - сборка образов"; \
echo " make docker push - отправка в Docker Hub";; \
build) \
echo "🐳 Сборка Docker образов (multi-arch)..."; \
echo "📋 Платформы: $(DOCKER_PLATFORMS)"; \
echo "📋 Builder: $(DOCKER_BUILDX_BUILDER)"; \
echo ""; \
$(MAKE) docker setup-builder; \
for image in $(DOCKER_IMAGES); do \
echo "🔨 Сборка $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \
$(MAKE) docker-build-image IMAGE=$$image; \
done; \
echo "✅ Образы собраны";; \
rebuild) \
echo "🔄 Полная пересборка Docker образов (multi-arch)..."; \
echo "📋 Платформы: $(DOCKER_PLATFORMS)"; \
echo "📋 Builder: $(DOCKER_BUILDX_BUILDER)"; \
echo "🧹 Очистка кеша и старых образов..."; \
echo ""; \
$(MAKE) docker clean; \
$(MAKE) docker clean-builder; \
$(MAKE) docker setup-builder; \
for image in $(DOCKER_IMAGES); do \
echo "🔨 Пересборка $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \
$(MAKE) docker-build-image IMAGE=$$image; \
done; \
echo "✅ Образы пересобраны с нуля";; \
push) \
echo "📤 Отправка Docker образов в Docker Hub..."; \
for image in $(DOCKER_IMAGES); do \
echo "📤 Отправка $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \
docker push $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION); \
done; \
echo "✅ Образы отправлены в Docker Hub";; \
pull) \
echo "📥 Загрузка Docker образов из Docker Hub..."; \
for image in $(DOCKER_IMAGES); do \
echo "📥 Загрузка $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \
docker pull $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION) || echo "⚠️ Образ $$image не найден в Docker Hub"; \
done; \
echo "✅ Загрузка завершена";; \
clean) \
echo "🧹 Очистка Docker образов..."; \
for image in $(DOCKER_IMAGES); do \
echo "🗑️ Удаление $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \
docker rmi $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION) 2>/dev/null || true; \
done; \
echo "✅ Образы очищены";; \
info) \
echo "📊 Информация об образах..."; \
for image in $(DOCKER_IMAGES); do \
if docker images | grep -q "$(DOCKER_REGISTRY)/$$image"; then \
echo "📦 $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \
docker images | grep "$(DOCKER_REGISTRY)/$$image" | head -1; \
fi; \
done;; \
update) \
echo "🔄 Обновление всех образов..."; \
$(MAKE) docker pull; \
$(MAKE) docker build; \
$(MAKE) docker push; \
echo "✅ Все образы обновлены";; \
purge) \
echo "🧹 Полная очистка Docker..."; \
echo "⚠️ ВНИМАНИЕ: Это удалит ВСЕ Docker данные!"; \
echo ""; \
read -p "Продолжить? (y/N): " confirm; \
if [ "$$confirm" = "y" ] || [ "$$confirm" = "Y" ]; then \
echo "🛑 Остановка всех контейнеров..."; \
docker stop $$(docker ps -aq) 2>/dev/null || true; \
echo "🗑️ Удаление всех контейнеров..."; \
docker rm $$(docker ps -aq) 2>/dev/null || true; \
echo "🗑️ Удаление всех образов..."; \
docker rmi $$(docker images -aq) 2>/dev/null || true; \
echo "🗑️ Удаление всех томов..."; \
docker volume rm $$(docker volume ls -q) 2>/dev/null || true; \
echo "🗑️ Удаление всех сетей..."; \
docker network rm $$(docker network ls -q) 2>/dev/null || true; \
echo "🧹 Очистка системы..."; \
docker system prune -af --volumes; \
echo "✅ Docker полностью очищен"; \
else \
echo "❌ Очистка отменена"; \
fi;; \
clean-builder) \
echo "🧹 Очистка multi-arch builder..."; \
if docker buildx ls | grep -q $(DOCKER_BUILDX_BUILDER); then \
echo "🗑️ Удаление builder $(DOCKER_BUILDX_BUILDER)..."; \
docker buildx rm $(DOCKER_BUILDX_BUILDER) || true; \
echo "✅ Builder удален"; \
else \
echo " Builder $(DOCKER_BUILDX_BUILDER) не найден"; \
fi;; \
setup-builder) \
echo "🔧 Настройка multi-arch builder в контейнере..."; \
if ! docker buildx ls | grep -q $(DOCKER_BUILDX_BUILDER); then \
echo "📦 Создание builder $(DOCKER_BUILDX_BUILDER) в контейнере..."; \
docker buildx create --name $(DOCKER_BUILDX_BUILDER) --driver docker-container --bootstrap --use; \
echo "⏳ Ожидание запуска builder..."; \
sleep 5; \
else \
echo "✅ Builder $(DOCKER_BUILDX_BUILDER) уже существует"; \
docker buildx use $(DOCKER_BUILDX_BUILDER); \
fi; \
echo "🔍 Проверка статуса builder..."; \
docker buildx inspect $(DOCKER_BUILDX_BUILDER) --bootstrap;; \
*) \
echo "🎯 Доступные команды:"; \
echo ""; \
echo " 🔧 make docker prepare - подготовка к работе с Docker Hub"; \
echo " 💡 Показывает: registry, version, список образов"; \
echo " 💡 Рекомендует: docker login перед работой"; \
echo ""; \
echo " 🐳 make docker build - собрать все Docker образы (multi-arch)"; \
echo " 💡 Собирает: ansible-controller, alt-linux, astra-linux, redos"; \
echo " 💡 Собирает: rhel, centos, alma, rocky"; \
echo " 💡 Платформы: $(DOCKER_PLATFORMS)"; \
echo " 💡 Тегирует: inecs/образ:<tag> (автоматически извлекает теги)"; \
echo " 💡 Отправляет: автоматически в Docker Hub"; \
echo ""; \
echo " 🔄 make docker rebuild - полная пересборка с очисткой кеша"; \
echo " 💡 Очищает: все локальные образы и кеш"; \
echo " 💡 Пересобирает: все образы с нуля"; \
echo " 💡 Полезно: при проблемах с кешем или зависимостями"; \
echo " 💡 Выполняет: clean + clean-builder + setup-builder + build"; \
echo ""; \
echo " 📤 make docker push - отправить образы в Docker Hub"; \
echo " 💡 Требует: docker login"; \
echo " 💡 Отправляет: все образы в registry inecs"; \
echo ""; \
echo " 📥 make docker pull - загрузить образы из Docker Hub"; \
echo " 💡 Загружает: все образы из registry inecs"; \
echo " 💡 Пропускает: отсутствующие образы"; \
echo ""; \
echo " 🧹 make docker clean - удалить локальные образы"; \
echo " 💡 Удаляет: все образы inecs/*:latest"; \
echo " 💡 Безопасно: игнорирует ошибки"; \
echo ""; \
echo " 🧹 make docker clean-builder - очистка multi-arch builder"; \
echo " 💡 Удаляет: builder контейнер"; \
echo " 💡 Полезно: при проблемах со сборкой"; \
echo ""; \
echo " 🔧 make docker setup-builder - настройка multi-arch builder"; \
echo " 💡 Создает: builder в контейнере (не в системе)"; \
echo " 💡 Поддерживает: amd64 и arm64 архитектуры"; \
echo ""; \
echo " 📊 make docker info - информация о собранных образах"; \
echo " 💡 Показывает: размер, дата создания, теги"; \
echo ""; \
echo " 🔄 make docker update - обновить все образы"; \
echo " 💡 Выполняет: pull + build + push"; \
echo " 💡 Полный цикл обновления"; \
echo ""; \
echo " 💥 make docker purge - ПОЛНАЯ очистка Docker"; \
echo " ⚠️ УДАЛЯЕТ: все контейнеры, образы, тома, сети"; \
echo " ⚠️ ОСТАНОВИТ: все запущенные контейнеры"; \
echo " ⚠️ ТРЕБУЕТ: подтверждение пользователя"; \
echo "";; \
esac
# =============================================================================
# ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ДЛЯ DOCKER
# =============================================================================
# Извлечение тега из базового образа
docker-get-base-tag:
@if [ -z "$(IMAGE)" ]; then \
echo "❌ Ошибка: IMAGE не указан"; \
exit 1; \
fi; \
case "$(IMAGE)" in \
alt-linux) \
BASE_IMAGE="altlinux/p9"; \
TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \
astra-linux) \
BASE_IMAGE="astralinux/astra-1.7"; \
TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \
redos) \
BASE_IMAGE="redos/redos:9"; \
TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \
rhel) \
BASE_IMAGE="registry.access.redhat.com/ubi8/ubi"; \
TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \
centos) \
BASE_IMAGE="quay.io/centos/centos:stream9"; \
TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \
alma) \
BASE_IMAGE="almalinux:8"; \
TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \
rocky) \
BASE_IMAGE="rockylinux:8"; \
TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \
ansible-controller) \
TAG="latest";; \
*) \
echo "❌ Неизвестный образ: $(IMAGE)"; \
exit 1;; \
esac; \
echo "$$TAG"
# Сборка одного образа с multi-arch
docker-build-image:
@if [ -z "$(IMAGE)" ]; then \
echo "❌ Ошибка: IMAGE не указан"; \
exit 1; \
fi; \
TAG=$$($(MAKE) docker-get-base-tag IMAGE=$(IMAGE)); \
echo "🔨 Сборка $(DOCKER_REGISTRY)/$(IMAGE):$$TAG"; \
cd dockerfiles/$(IMAGE) && \
docker buildx build \
--platform $(DOCKER_PLATFORMS) \
--tag $(DOCKER_REGISTRY)/$(IMAGE):$$TAG \
--tag $(DOCKER_REGISTRY)/$(IMAGE):latest \
--push \
.; \
echo "$(IMAGE):$$TAG собран и отправлен"
# =============================================================================
# КОМАНДЫ ДЛЯ РАБОТЫ С ANSIBLE-CONTROLLER
# =============================================================================
controller:
@case "$(word 2, $(MAKECMDGOALS))" in \
build) \
echo "🔨 Сборка ansible-controller (multi-arch)..."; \
echo "📋 Платформы: $(DOCKER_PLATFORMS)"; \
$(MAKE) docker setup-builder; \
cd dockerfiles/ansible-controller && \
docker buildx build \
--platform $(DOCKER_PLATFORMS) \
--tag $(DOCKER_REGISTRY)/ansible-controller:$(DOCKER_VERSION) \
--push \
.; \
echo "✅ ansible-controller собран и отправлен";; \
run) \
echo "🚀 Запуск ansible-controller..."; \
cd dockerfiles/ansible-controller && docker-compose up -d; \
echo "✅ ansible-controller запущен";; \
stop) \
echo "🛑 Остановка ansible-controller..."; \
cd dockerfiles/ansible-controller && docker-compose down; \
echo "✅ ansible-controller остановлен";; \
*) \
echo "🎯 Доступные команды:"; \
echo ""; \
echo " 🔨 make controller build - собрать ansible-controller (multi-arch)"; \
echo " 💡 Собирает: inecs/ansible-controller:latest"; \
echo " 💡 Платформы: $(DOCKER_PLATFORMS)"; \
echo " 💡 Использует: dockerfiles/ansible-controller/Dockerfile"; \
echo " 💡 Requirements: dockerfiles/ansible-controller/requirements.yml"; \
echo ""; \
echo " 🚀 make controller run - запустить ansible-controller"; \
echo " 💡 Запускает: docker-compose up -d"; \
echo " 💡 Использует: dockerfiles/ansible-controller/docker-compose.yml"; \
echo ""; \
echo " 🛑 make controller stop - остановить ansible-controller"; \
echo " 💡 Останавливает: docker-compose down"; \
echo " 💡 Удаляет: контейнеры и сети";; \
esac
# =============================================================================
# СПРАВКА
# =============================================================================
help:
@echo "=========================================="
@echo "AnsibleTemplate - Универсальная система"
@echo "тестирования Ansible ролей"
@echo "=========================================="
@echo ""
@echo "📁 Структура проекта:"
@echo " scripts/ - Скрипты автоматизации"
@echo " inventory/ - Инвентори файлы"
@echo " molecule/default/ - Molecule конфигурация"
@echo " roles/ - Ansible роли"
@echo " vault/ - Зашифрованные секреты"
@echo " dockerfiles/ - Docker образы для тестирования"
@echo ""
@echo "🚀 ОСНОВНЫЕ КОМАНДЫ:"
@echo " make role lint - проверить синтаксис ролей"
@echo " make role test [preset] - протестировать роли с preset'ом"
@echo " make role deploy - развернуть роли на реальные серверы"
@echo ""
@echo "📋 PRESET'Ы (тестовые окружения):"
@echo " make presets list - показать все доступные preset'ы"
@echo " make presets info - подробная информация о preset'е"
@echo " make presets test - запустить тест с preset'ом"
@echo ""
@echo "🐳 DOCKER ОБРАЗЫ (Multi-Arch):"
@echo " make docker prepare - подготовка к работе с Docker Hub"
@echo " make docker build - собрать все Docker образы (amd64 + arm64)"
@echo " make docker rebuild - полная пересборка с очисткой кеша"
@echo " make docker push - отправить образы в Docker Hub"
@echo " make docker pull - загрузить образы из Docker Hub"
@echo " make docker clean - удалить локальные образы"
@echo " make docker info - информация о собранных образах"
@echo " make docker update - обновить все образы (pull + build + push)"
@echo " make docker purge - ПОЛНАЯ очистка Docker (ОСТОРОЖНО!)"
@echo ""
@echo "🔧 DOCKER BUILDER (Multi-Arch):"
@echo " make docker setup-builder - настройка multi-arch builder в контейнере"
@echo " make docker clean-builder - очистка multi-arch builder"
@echo " 💡 Поддерживает: amd64, arm64, riscv64, ppc64le, s390x, 386, arm/v7, arm/v6"
@echo ""
@echo "🔐 VAULT (управление секретами):"
@echo " make vault create - создать новый файл секретов"
@echo " make vault edit - редактировать существующие секреты"
@echo " make vault show - показать содержимое секретов"
@echo " make vault delete - удалить файл секретов"
@echo " make vault encrypt - зашифровать файл"
@echo " make vault decrypt - расшифровать файл"
@echo " make vault rekey - сменить пароль шифрования"
@echo " make vault check - проверить vault файлы"
@echo " make vault scan - поиск потенциальных секретов"
@echo ""
@echo "🌿 GIT (управление версиями):"
@echo " make git push - отправить изменения в репозиторий"
@echo " make git pull - получить изменения из репозитория"
@echo " make git new - создать новую ветку"
@echo ""
@echo "🎮 CONTROLLER (ansible-controller Multi-Arch):"
@echo " make controller build - собрать ansible-controller (amd64 + arm64)"
@echo " make controller run - запустить ansible-controller"
@echo " make controller stop - остановить ansible-controller"
@echo ""
@echo "💡 ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:"
@echo " make presets list # показать все preset'ы"
@echo " make presets test PRESET=etcd-patroni # тест с etcd-patroni"
@echo " make role test minimal # быстрый тест"
@echo " make docker setup-builder # настройка multi-arch builder"
@echo " make docker build # собрать все образы (amd64 + arm64)"
@echo " make docker rebuild # полная пересборка с очисткой кеша"
@echo " make controller build # собрать ansible-controller (multi-arch)"
@echo " make docker clean-builder # очистка builder'а"
@echo " make docker purge # полная очистка Docker"
@echo " make vault create # создать секреты"
@echo ""
@echo "📖 Подробная справка: make [команда]"
@echo "=========================================="
# Пустые цели для совместимости
view create edit show delete lint deploy new advanced list info test build push pull clean prepare update run stop purge clean-builder setup-builder:
@true

347
Makefile.backup Normal file
View File

@@ -0,0 +1,347 @@
# =============================================================================
# AnsibleTemplate - Универсальная система тестирования Ansible ролей
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# =============================================================================
SHELL := /bin/bash
# =============================================================================
# ЦВЕТА ДЛЯ ВЫВОДА
# =============================================================================
RED := \033[0;31m
GREEN := \033[0;32m
YELLOW := \033[0;33m
BLUE := \033[0;34m
PURPLE := \033[0;35m
CYAN := \033[0;36m
WHITE := \033[0;37m
RESET := \033[0m
# =============================================================================
# ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
# =============================================================================
PROJECT_NAME ?= ansible-template
VERSION ?= 0.1.0
AUTHOR ?= "Сергей Антропов"
SITE ?= "https://devops.org.ru"
DOCKER_IMAGE ?= quay.io/ansible/creator-ee:latest
CONTAINER_NAME ?= ansible-controller
.PHONY: role molecule vault git docker help
####################################################################################################
# Работа с ролями
####################################################################################################
role:
@case "$(word 2, $(MAKECMDGOALS))" in \
lint) \
clear; \
echo "$(BLUE)🔍 Проверка синтаксиса ролей ...$(RESET)"; \
echo ""; \
docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace -e ANSIBLE_FORCE_COLOR=1 $(DOCKER_IMAGE) bash -c "ansible-lint roles/ --config-file .ansible-lint || true"; \
echo "$(GREEN)✅ Lint завершен$(RESET)";; \
test) \
clear; \
echo "$(PURPLE)🚀 Тестирование ролей ...$(RESET)"; \
PRESET="default"; \
# Получаем все аргументы после 'test' и берем первый как preset \
ARGS="$(filter-out test,$(MAKECMDGOALS))"; \
if [ -n "$$ARGS" ]; then \
PRESET="$$(echo $$ARGS | cut -d' ' -f1)"; \
fi; \
echo "$(CYAN)📋 Используется пресет: $(YELLOW)$$PRESET$(RESET)"; \
if [ ! -f "molecule/presets/$$PRESET.yml" ]; then \
echo "$(RED)❌ Ошибка: Пресет '$$PRESET' не найден!$(RESET)"; \
echo "$(YELLOW)💡 Доступные пресеты:$(RESET)"; \
ls -1 molecule/presets/*.yml 2>/dev/null | sed 's|molecule/presets/||g' | sed 's|\.yml||g' | sed 's/^/ - /' || echo " $(YELLOW)⚠️ Пресеты не найдены$(RESET)"; \
echo ""; \
echo "$(GREEN)💡 Использование:$(RESET)"; \
echo " $(BLUE)make role test$(RESET) - с default preset"; \
echo " $(BLUE)make role test [preset_name]$(RESET) - с любым preset"; \
echo " $(BLUE)make role test minimal$(RESET) - с minimal preset"; \
echo " $(BLUE)make role test standard$(RESET) - со standard preset"; \
echo " $(BLUE)make role test docker$(RESET) - с docker preset"; \
exit 1; \
fi; \
echo ""; \
docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \
-e ANSIBLE_FORCE_COLOR=1 \
-e MOLECULE_PRESET=$$PRESET \
$(DOCKER_IMAGE) \
bash -c "cd molecule/default && ansible-playbook -i localhost, site.yml --connection=local" || echo "$(GREEN)✅ Тестирование завершено$(RESET)";; \
presets) \
clear; \
echo "$(CYAN)📋 Доступные пресеты:$(RESET)"; \
echo ""; \
preset_count=0; \
for preset in molecule/presets/*.yml; do \
if [ -f "$$preset" ]; then \
preset_name=$$(basename "$$preset" .yml); \
preset_desc=$$(grep -E "^#.*пресет|^#.*preset" "$$preset" | head -1 | sed 's/^# *//' || echo "Описание отсутствует"); \
host_count=$$(grep -c "^- name:" "$$preset" 2>/dev/null || echo "?"); \
printf " $(BLUE)📄 %s$(RESET) - %s $(GREEN)(%s хостов)$(RESET)\n" "$$preset_name" "$$preset_desc" "$$host_count"; \
preset_count=$$((preset_count + 1)); \
fi; \
done; \
if [ $$preset_count -eq 0 ]; then \
echo " $(YELLOW)⚠️ Пресеты не найдены$(RESET)"; \
fi; \
echo ""; \
echo "$(GREEN)💡 Использование:$(RESET)"; \
echo " $(BLUE)make role test$(RESET) - с default preset"; \
echo " $(BLUE)make role test [preset_name]$(RESET) - с любым preset"; \
echo " $(BLUE)make role test minimal$(RESET) - с minimal preset"; \
echo " $(BLUE)make role test standard$(RESET) - со standard preset"; \
echo " $(BLUE)make role test docker$(RESET) - с docker preset"; \
echo ""; \
echo "$(YELLOW)💡 Примеры:$(RESET)"; \
echo " $(BLUE)make role test$(RESET) # default preset"; \
echo " $(BLUE)make role test minimal$(RESET) # minimal preset"; \
echo " $(BLUE)make role test my-custom-preset$(RESET) # любой preset";; \
deploy) \
clear; \
echo "$(PURPLE)🚀 Развертывание ролей на реальные серверы...$(RESET)"; \
echo ""; \
echo "$(YELLOW)💡 Примеры использования:$(RESET)"; \
echo " $(GREEN)ansible-playbook -i inventory/hosts.ini deploy.yml$(RESET)"; \
echo " $(GREEN)ansible-playbook -i inventory/hosts.ini deploy.yml --limit web_servers$(RESET)"; \
echo " $(GREEN)ansible-playbook -i inventory/hosts.ini deploy.yml --check$(RESET)"; \
echo ""; \
echo "$(CYAN)📄 Доступные playbook:$(RESET)"; \
ls -la *.yml 2>/dev/null | grep -v molecule || echo " $(BLUE)📄 deploy.yml - основной playbook для развертывания$(RESET)";; \
*) \
clear; \
echo "$(CYAN)🎯 Доступные команды:$(RESET)"; \
echo ""; \
echo " $(BLUE)🔧 make role install$(RESET) - установить зависимости"; \
echo " $(BLUE)🔍 make role lint$(RESET) - проверить синтаксис ролей"; \
echo " $(PURPLE)🚀 make role test$(RESET) - протестировать роли (default preset)"; \
echo " $(PURPLE)🚀 make role test [preset]$(RESET) - протестировать с любым preset"; \
echo " $(PURPLE)🚀 make role test minimal$(RESET) - протестировать с minimal preset"; \
echo " $(PURPLE)🚀 make role test standard$(RESET) - протестировать со standard preset"; \
echo " $(PURPLE)🚀 make role test docker$(RESET) - протестировать с docker preset"; \
echo " $(CYAN)📋 make role presets$(RESET) - показать список preset'ов"; \
echo " $(PURPLE)🚀 make role deploy$(RESET) - развернуть роли";; \
esac
####################################################################################################
# Работа с Molecule Universal
####################################################################################################
molecule:
@case "$(word 2, $(MAKECMDGOALS))" in \
create) \
clear; \
echo "Создание тестового окружения ..."; \
docker run --rm -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
bash -c "cd molecule/default && molecule create";; \
converge) \
clear; \
echo "Запуск плейбуков ..."; \
docker run --rm -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
bash -c "cd molecule/default && molecule converge";; \
verify) \
clear; \
echo "Проверка результатов ..."; \
docker run --rm -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
bash -c "cd molecule/default && molecule verify";; \
destroy) \
clear; \
echo "Удаление тестового окружения ..."; \
docker run --rm -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
bash -c "cd molecule/default && molecule destroy";; \
test) \
clear; \
echo "Полный цикл тестирования ..."; \
docker run --rm -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
bash -c "cd molecule/default && molecule test";; \
*) \
clear; \
echo "Доступные команды:"; \
echo " make molecule create - создать окружение"; \
echo " make molecule converge - запустить плейбуки"; \
echo " make molecule verify - проверить результаты"; \
echo " make molecule destroy - удалить окружение"; \
echo " make molecule test - полный цикл тестирования"; \
;; \
esac
####################################################################################################
# Работа с Ansible Vault
####################################################################################################
vault:
@case "$(word 2, $(MAKECMDGOALS))" in \
show) \
clear; \
echo "Доступные файлы секретов:"; \
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault view --vault-password-file vault/.vault vault/$$FILE.yml;; \
create) \
clear; \
echo "Создание файла секретов :"; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -it -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault create --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \
edit) \
clear; \
echo "Доступные файлы секретов:"; \
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -it -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault edit --vault-password-file vault/.vault vault/$$FILE.yml;; \
delete) \
clear; \
echo "Доступные файлы секретов:"; \
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
rm -f vault/$$FILE.yml;; \
rekey) \
clear; \
echo "Доступные файлы секретов:"; \
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -it -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault rekey --vault-password-file vault/.vault vault/$$FILE.yml;; \
decrypt) \
clear; \
echo "Доступные файлы секретов:"; \
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault decrypt --vault-password-file vault/.vault vault/$$FILE.yml;; \
encrypt) \
clear; \
echo "Доступные файлы секретов:"; \
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
echo ""; \
read -p "Введите имя файла (без .yml): " FILE; \
docker run --rm -v "$(PWD):/workspace" -w /workspace \
quay.io/ansible/creator-ee:latest \
ansible-vault encrypt --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \
*) \
clear; \
echo "Доступные команды:"; \
echo " make vault create - создать файл секретов"; \
echo " make vault edit - редактировать секреты"; \
echo " make vault show - показать секреты"; \
echo " make vault delete - удалить секреты"; \
echo " make vault encrypt - зашифровать файл"; \
echo " make vault decrypt - расшифровать файл"; \
echo " make vault rekey - сменить пароль";; \
esac
####################################################################################################
# Работа с Git
####################################################################################################
git:
@case "$(word 2, $(MAKECMDGOALS))" in \
push) \
git branch; \
read -p "Выберите ветку для пуша: " BRANCH; \
read -p "Введите описание коммита: " COMMIT; \
commitname=$$COMMIT; \
git add . ; \
git commit -m "$$commitname"; \
git push -u origin $$BRANCH; \
echo "Изменения внесены в Git";; \
pull) \
git pull;; \
new) \
read -p "Введите имя новой ветки: " BRANCH_NAME; \
NEW_BRANCH="$$BRANCH_NAME"; \
git checkout -b $$NEW_BRANCH; \
echo "Создана и переключена на новую ветку: $$NEW_BRANCH";; \
*) \
clear; \
echo "Доступные команды:"; \
echo " make git push - запушить изменения"; \
echo " make git pull - получить изменения"; \
echo " make git new - создать новую ветку";; \
esac
####################################################################################################
# Работа с Docker (упрощенная)
####################################################################################################
docker:
@case "$(word 2, $(MAKECMDGOALS))" in \
clean) \
clear; \
echo "$(RED)🧹 Очистка Docker ресурсов...$(RESET)"; \
docker system prune -f; \
docker volume prune -f; \
echo "$(GREEN)✅ Docker ресурсы очищены$(RESET)";; \
*) \
clear; \
echo "$(CYAN)🐳 Docker команды:$(RESET)"; \
echo ""; \
echo "$(RED)make docker clean$(RESET) - очистить Docker ресурсы"; \
echo ""; \
echo "$(YELLOW)💡 Основное тестирование через preset систему:$(RESET)"; \
echo " $(BLUE)make role test [preset]$(RESET) - универсальное тестирование"; \
echo " $(BLUE)make role presets$(RESET) - показать доступные preset'ы";; \
esac
####################################################################################################
# Справка
####################################################################################################
help:
@clear
@echo "=========================================="
@echo "AnsibleTemplate - Универсальная система"
@echo "тестирования Ansible ролей"
@echo "=========================================="
@echo ""
@echo "📁 Структура проекта:"
@echo " scripts/ - Скрипты автоматизации"
@echo " inventory/ - Инвентори файлы"
@echo " molecule/default/ - Molecule конфигурация"
@echo " roles/ - Ansible роли"
@echo " vault/ - Зашифрованные секреты"
@echo ""
@echo "🚀 Основные команды:"
@echo " make role install - установить зависимости"
@echo " make role lint - проверить синтаксис ролей"
@echo " make role test - протестировать роли (default preset)"
@echo " make role test [preset] - протестировать с любым preset"
@echo " make role test minimal - тест с minimal preset"
@echo " make role test standard - тест со standard preset"
@echo " make role test docker - тест с docker preset"
@echo " make role deploy - развернуть роли на серверы"
@echo " make docker clean - очистить Docker ресурсы"
@echo " make vault create - создать файл секретов"
@echo " make git new - создать новую ветку"
@echo ""
@echo "📖 Для подробной справки:"
@echo " make role - команды для ролей"
@echo " make molecule - команды Molecule"
@echo " make docker - команды Docker"
@echo " make vault - команды Vault"
@echo " make git - команды Git"
@echo "=========================================="
# Пустые цели для совместимости
view create edit show delete test lint deploy new advanced presets:
@true
# Динамические цели для всех возможных preset'ов
# Это позволяет использовать make role test [любой_preset] без ошибок
%:
@true

262
README.md
View File

@@ -1,62 +1,224 @@
# AnsibleTemplate
# AnsibleTemplate - Универсальная система тестирования Ansible ролей
Темплейт для создания, проверки и тестирование ролей Ansible с помощью контейнеров Docker.
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
### С чего начать?
## 🚀 Описание
На вашей машине вам необходимо сбилдить образ, где будут запускаться все роли через docker-compose.
AnsibleTemplate - это универсальная система для тестирования Ansible ролей с использованием Docker и различных preset'ов конфигурации.
Это можно сделать самостоятельно:
## 🔧 Исправленные проблемы
- **make docker build** - создание контейнера
- **make docker rebuild** - пересоздание контейнера, если были внесены изменения в Dockerfile
- **make docker prune** - очистить систему от лишних образов
- **make docker shell** - войти в контейнер Shell
- **make docker release** - собирает образ контейнера и пушит его в докер реджистри
- **make docker images** - собрать образы контейнеров с systemd, для удобного тестирования ролей
- **make images** - собрать и запушить все образы (основной Ansible, CentOS, Ubuntu) в Docker Hub (inecs/ansible)
### 1. **Проблема с preset'ами в Makefile**
- **Исправлено**: Полностью универсальная система - любой preset без изменения Makefile
- **Добавлено**: Динамическое определение preset'ов через `filter-out` и `cut`
- **Улучшено**: Динамическая загрузка preset'ов через `include_vars` в Ansible
- **Добавлено**: Fallback значения и подробная справка при ошибках
Или ввести команду:
### 2. **Дублирование файлов preset'ов**
-**Исправлено**: Создан уникальный `default.yml` preset с 2 хостами (Debian + RHEL)
-**Сохранено**: `minimal.yml` для быстрого тестирования с 1 хостом
-**Улучшено**: Различные конфигурации для разных сценариев тестирования
- **make init** - которая создаст файл секретов с паролем. Сбилдит образ. И создаст новую роль.
### 3. **Проблемы с именами контейнеров**
-**Исправлено**: Унифицированы имена контейнеров (`ansible-controller`)
-**Обновлено**: Все файлы теперь используют одинаковые имена контейнеров
### Работа с ролью
- **make role new** - создать новую роль из шаблона. Название роли пишется на английском, описание роли на любом языке
- **make role lint** - проверяет все роли в папке roles/* на наличие ошибок
- **make role test** - позволяет тестировать роль, указанную в molecule/default/converge.yml
сразу на двух контейнерах (RedHat и Ubuntu)
- **make role deploy** - запускает роль в продакшен. Все хосты берет из файла inventory/hosts
### 4. **Проблемы с путями**
- **Исправлено**: Пути в `create.yml` и `destroy.yml` теперь используют `preset.yml`
- **Добавлено**: Fallback значения для случаев отсутствия preset файлов
- **Улучшено**: Более надежная работа с переменными
### Работа с файлом переменных
### 5. **Дополнительные улучшения**
-**Добавлено**: Универсальная Docker Compose конфигурация с поддержкой preset'ов
-**Создан**: Dockerfile для проекта
-**Добавлено**: Переменные окружения в `env.example`
-**Улучшено**: Расширенная справка и команды Docker
-**Добавлено**: Команды для работы с preset'ами через Docker Compose
Все переменные защищены через **Ansible-Vault** и находятся в папке vars/secrets.yml
## 📁 Структура проекта
Для смены пароля измените его в файле **./vault-password.txt**
- **make vault create** - создать новый файл с учетом пароля в файле **./vault-password.txt**
- **make vault delete** - удалить файл с переменными
- **make vault edit** - отредактировать файл переменных
- **make vault show** - показать содержимое файла переменных
- **make vault rekey** - сменить пароль шифрования
- **make vault encrypt** - зашифровать файл секретов
- **make vault decrypt** - расшифровать файл секретов
### Работа с Git
- **make git push** - запушить изменения. С выбором ветки и вводом коммита.
- **make git pull** - получить изменения из репы
- **make git new** - создание нового брэнча имя cluster-branch_name для IaC подхода.
### Добавить свой образ контейнера для тестов
Что бы добавить или изменить докер-образы для тестирования ролей измените файл настроек молекулы
molecule/default/molecule.yml
```yaml
- name: ubuntu-instance
image: "your.docker-registry.com/your-image:latest"
privileged: true
pre_build_image: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
```
Помните, что образ обязательно должен содержать python не ниже версии 3.12 и systemd для нормального тестирования ролей.
AnsibleTemplate/
├── molecule/
│ ├── default/ # Molecule конфигурация
│ │ ├── create.yml # Создание тестовых контейнеров
│ │ ├── converge.yml # Запуск тестов
│ │ ├── destroy.yml # Удаление контейнеров
│ │ └── site.yml # Основной playbook
│ └── presets/ # Preset'ы конфигурации
│ ├── default.yml # Стандартный preset (2 хоста)
│ ├── minimal.yml # Минимальный preset (1 хост)
│ ├── standard.yml # Расширенный preset (3 хоста)
│ └── docker.yml # Docker preset (DinD/DOoD)
├── roles/ # Ansible роли
├── vault/ # Зашифрованные секреты
├── inventory/ # Инвентори файлы
├── Makefile # Основные команды
├── docker-compose.yml # Docker Compose конфигурация
├── Dockerfile # Docker образ
└── env.example # Переменные окружения
```
## 🚀 Использование
### 🧪 Тестирование (Docker контейнеры)
```bash
# Просмотр доступных preset'ов
make role presets
# Тестирование с разными preset'ами
make role test # default preset
make role test minimal # minimal preset
make role test standard # standard preset
make role test docker # docker preset
make role test performance # performance preset
make role test security # security preset
make role test my-custom-preset # любой custom preset
```
**Особенности тестирования:**
- Использует Docker контейнеры для изоляции
- Динамический inventory создается из preset файлов
- Временные контейнеры (u1, u2, u3, ...)
- Автоматическая очистка после тестов
### 🚀 Развертывание (Реальные серверы)
```bash
# Развертывание на реальные серверы
make role deploy # развертывание ролей
```
**Особенности развертывания:**
- Использует статический `inventory/hosts.ini`
- Подключение по SSH к реальным серверам
- Dry-run проверка перед развертыванием
- Подтверждение пользователя
### 🔧 Вспомогательные команды
```bash
# Docker команды
make docker clean # очистить Docker ресурсы
# Другие команды
make role lint # проверка синтаксиса
make vault create # создание секретов
make help # полная справка
```
### Preset'ы конфигурации
| Preset | Описание | Хосты | Использование |
|--------|----------|-------|---------------|
| `default` | Стандартный preset | 2 хоста (Debian + RHEL) | Базовое тестирование |
| `minimal` | Минимальный preset | 1 хост (Debian) | Быстрое тестирование |
| `standard` | Расширенный preset | 3 хоста (Debian + RHEL + Debian) | Полное тестирование |
| `docker` | Docker preset | DinD + DOoD узлы | Тестирование Docker функциональности |
| `performance` | Performance preset | 5 хостов (Debian + RHEL) | Нагрузочное тестирование |
| `security` | Security preset | 3 хоста (Debian + RHEL) | Тестирование безопасности |
| `[custom]` | Любой custom preset | Любое количество | Пользовательские сценарии |
## 🔧 Технические детали
### Исправления в Makefile
1. **Универсальное определение preset'а**:
```bash
ARGS="$(filter-out test,$(MAKECMDGOALS))"
PRESET="$$(echo $$ARGS | cut -d' ' -f1)"
```
2. **Проверка существования preset'ов с подробной справкой**:
```bash
if [ ! -f "molecule/presets/$$PRESET.yml" ]; then
echo "❌ Ошибка: Пресет '$PRESET' не найден!"
# Показать доступные preset'ы и примеры использования
fi
```
3. **Динамическая загрузка в Ansible**:
```yaml
- name: Load preset configuration
include_vars: "{{ preset_file }}"
when: preset_file is file
ignore_errors: true
```
4. **Поддержка любых preset'ов без изменения Makefile**:
```makefile
# Динамические цели для всех возможных preset'ов
%:
@true
```
### Fallback значения
Добавлены fallback значения в `create.yml` и `destroy.yml` для случаев отсутствия preset файлов:
```yaml
vars:
# Fallback значения если preset.yml не найден
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# ... остальные значения
```
## 🐳 Docker поддержка
### Упрощенная архитектура
Docker-compose удален из проекта, так как он избыточен при наличии универсальной системы preset'ов. Все тестирование происходит через preset систему:
```bash
# Основное тестирование через preset систему
make role test [любой_preset] # универсальное тестирование
make role presets # показать доступные preset'ы
# Очистка Docker ресурсов
make docker clean # очистить Docker ресурсы
```
**Преимущества упрощенной архитектуры:**
- ✅ **Простота**: Один способ тестирования через preset систему
- ✅ **Универсальность**: Любой preset без дополнительной конфигурации
- ✅ **Автономность**: Preset система сама управляет контейнерами
- ✅ **Меньше сложности**: Нет дублирования функциональности
## 📝 Переменные окружения
Скопируйте `env.example` в `.env` и настройте под свои нужды:
```bash
cp env.example .env
```
## 🎯 Результат
Теперь система тестирования работает корректно:
1. ✅ **Полностью универсальная система preset'ов - любой preset без изменения Makefile**
2. ✅ **Динамическое определение preset'ов через `filter-out` и `cut`**
3. ✅ **Проверка существования preset'ов с подробной справкой**
4. ✅ **Унифицированные имена контейнеров**
5. ✅ **Надежные fallback значения**
6. ✅ **Упрощенная архитектура без docker-compose**
7. ✅ **Поддержка неограниченного количества custom preset'ов**
8. ✅ **Автономная preset система сама управляет контейнерами**
9. ✅ **Подробная документация и справка**
## 📞 Поддержка
При возникновении проблем:
1. Проверьте наличие Docker и Docker Compose
2. Убедитесь, что все preset файлы существуют
3. Используйте `make help` для справки
4. Проверьте логи: `make docker shell` и `docker logs ansible-controller`
---
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru

View File

@@ -1,6 +1,6 @@
[defaults]
inventory = inventory/hosts
vault_password_file = vault-password.txt
inventory = inventory/hosts.ini
# vault_password_file = vault/.vault
remote_user = devops
host_key_checking = False
enable_plugins = yaml, ini

51
cicd/.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,51 @@
# GitLab CI для AnsibleTemplate
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
stages:
- test
- deploy
variables:
DOCKER_IMAGE: "quay.io/ansible/creator-ee:latest"
DOCKER_TLS_CERTDIR: ""
ANSIBLE_FORCE_COLOR: "true"
before_script:
- echo "Установка зависимостей..."
- pip install molecule[docker] ansible-lint
- ansible-galaxy collection install -r requirements.yml
# Тестирование с Molecule
test:
stage: test
image: $DOCKER_IMAGE
services:
- docker:dind
variables:
DOCKER_TLS_CERTDIR: ""
script:
- echo "Запуск тестов Molecule..."
- cd molecule/universal
- molecule test -s universal
artifacts:
reports:
junit: molecule/universal/.molecule/reports/junit.xml
paths:
- molecule/universal/.molecule/
expire_in: 1 week
only:
- merge_requests
- main
- develop
# Деплой (если нужен)
deploy:
stage: deploy
image: $DOCKER_IMAGE
script:
- echo "Деплой не настроен"
- echo "Добавьте логику деплоя в этот job"
when: manual
only:
- main

View File

@@ -0,0 +1,53 @@
# Azure DevOps Pipeline для AnsibleTemplate
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
trigger:
- main
- develop
pool:
vmImage: 'ubuntu-latest'
variables:
ANSIBLE_FORCE_COLOR: 'true'
DOCKER_TLS_CERTDIR: ''
stages:
- stage: Test
displayName: 'Test Stage'
jobs:
- job: TestJob
displayName: 'Run Tests'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.11'
displayName: 'Use Python 3.11'
- script: |
pip install --upgrade pip
pip install molecule[docker] ansible-lint
ansible-galaxy collection install -r requirements.yml
displayName: 'Install Dependencies'
- script: |
ansible-lint molecule/universal/
displayName: 'Run Ansible Lint'
- script: |
cd molecule/universal
molecule test -s universal
displayName: 'Run Molecule Tests'
- task: PublishTestResults@2
inputs:
testResultsFiles: 'molecule/universal/.molecule/reports/junit.xml'
testRunTitle: 'Molecule Test Results'
condition: always()
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: 'molecule/universal/.molecule'
artifactName: 'molecule-reports'
condition: always()

70
cicd/github/workflows.yml Normal file
View File

@@ -0,0 +1,70 @@
# GitHub Actions Workflow для AnsibleTemplate
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
name: Ansible Testing
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y docker.io
sudo systemctl start docker
sudo usermod -aG docker $USER
- name: Install Python dependencies
run: |
pip install --upgrade pip
pip install molecule[docker] ansible-lint
ansible-galaxy collection install -r requirements.yml
- name: Run Molecule tests
run: |
cd molecule/universal
molecule test -s universal
- name: Upload test results
uses: actions/upload-artifact@v3
if: always()
with:
name: molecule-reports
path: molecule/universal/.molecule/
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install ansible-lint
ansible-galaxy collection install -r requirements.yml
- name: Run Ansible Lint
run: |
ansible-lint molecule/universal/

59
cicd/jenkins/Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,59 @@
// Jenkins Pipeline для AnsibleTemplate
// Автор: Сергей Антропов
// Сайт: https://devops.org.ru
pipeline {
agent any
environment {
ANSIBLE_FORCE_COLOR = 'true'
DOCKER_TLS_CERTDIR = ''
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Install Dependencies') {
steps {
sh '''
pip install --upgrade pip
pip install molecule[docker] ansible-lint
ansible-galaxy collection install -r requirements.yml
'''
}
}
stage('Lint') {
steps {
sh 'ansible-lint molecule/universal/'
}
}
stage('Test') {
steps {
dir('molecule/universal') {
sh 'molecule test -s universal'
}
}
}
}
post {
always {
archiveArtifacts artifacts: 'molecule/universal/.molecule/**/*', allowEmptyArchive: true
publishTestResults testResultsPattern: 'molecule/universal/.molecule/reports/junit.xml'
}
success {
echo 'Pipeline completed successfully!'
}
failure {
echo 'Pipeline failed!'
}
}
}

View File

@@ -1,10 +0,0 @@
---
- name: Deploy roles
hosts: all
become: true
become_user: root
become_method: ansible.builtin.sudo
gather_facts: true
vars_files:
- ../../vars/secrets.yml
roles:

View File

View File

@@ -1,4 +0,0 @@
---
- name: Пример таски
debug:
msg: "Привет! Я запустился на Debian/Ubuntu!"

View File

@@ -1,12 +0,0 @@
---
- name: "Определяем ОС"
set_fact:
os_family: "{{ ansible_facts['os_family'] }}"
- name: "Подключаем таски для RedHat совместимых"
include_tasks: "redhat/main.yaml"
when: os_family == "RedHat"
- name: "Подключаем таски для Debian/Ubuntu совместимых"
include_tasks: "debian/main.yaml"
when: os_family == "Debian"

View File

@@ -1,4 +0,0 @@
---
- name: Пример таски
debug:
msg: "Привет! Я запустился на RedHat/CentOS/Fedora!"

View File

13
deploy.yml Normal file
View File

@@ -0,0 +1,13 @@
---
# Плейбук для развертывания ролей
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
- name: Test nginx role
hosts: all
become: true
roles:
- nginx
tags:
- nginx
- test

View File

@@ -1,12 +0,0 @@
services:
ansible:
image: inecs/ansible:latest
container_name: ansible
volumes:
- .:/ansible
- /var/run/docker.sock:/var/run/docker.sock
environment:
- ANSIBLE_VAULT_PASSWORD_FILE=./vault-password.txt
tty: true
privileged: true
working_dir: /ansible

160
dockerfiles/README.md Normal file
View File

@@ -0,0 +1,160 @@
# Docker образы для универсальной системы тестирования
## Обзор
Эта директория содержит Docker образы для различных операционных систем и компонентов, используемых в универсальной системе тестирования Ansible ролей.
## Структура
```
dockerfiles/
├── ansible-controller/ # Ansible контроллер с предустановленными коллекциями
├── alt-linux/ # ALT Linux с systemd
├── astra-linux/ # Astra Linux с systemd
├── redos/ # RED OS с systemd
├── Makefile # Команды для сборки образов
└── README.md # Документация
```
## Доступные образы
### ansible-controller
- **Базовый образ:** `quay.io/ansible/creator-ee:latest`
- **Описание:** Ansible контроллер с предустановленными коллекциями
- **Компоненты:**
- Ansible с коллекциями (community.docker, community.general, ansible.posix)
- Docker CLI
- kubectl
- Helm
- Kind
- Istio CLI
- Дополнительные роли (geerlingguy.docker, geerlingguy.kubernetes)
### alt-linux
- **Базовый образ:** `altlinux/p9`
- **Описание:** ALT Linux с systemd
- **Компоненты:**
- systemd
- Docker
- Docker Compose
- Python3
- Пользователь ansible
### astra-linux
- **Базовый образ:** `astralinux/astra-1.7`
- **Описание:** Astra Linux с systemd
- **Компоненты:**
- systemd
- Docker
- Docker Compose
- Python3
- Пользователь ansible
### redos
- **Базовый образ:** `redos/redos:9`
- **Описание:** RED OS с systemd
- **Компоненты:**
- systemd
- Docker
- Docker Compose
- Python3
- Пользователь ansible
## Использование
### Сборка всех образов
```bash
make docker-build
```
### Сборка конкретного образа
```bash
make docker-build IMAGE=ansible-controller
```
### Отправка образов в registry
```bash
make docker-push
```
### Очистка образов
```bash
make docker-clean
```
### Информация об образах
```bash
make docker-info
```
## Настройка registry
По умолчанию образы собираются с тегом `localhost:5000/имя:latest`. Для изменения registry:
```bash
make docker-build REGISTRY=my-registry.com
make docker-push REGISTRY=my-registry.com
```
## Использование в preset'ах
После сборки образов их можно использовать в preset'ах:
```yaml
# molecule/presets/my-preset.yml
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
alt: "localhost:5000/alt-linux:latest"
astra: "localhost:5000/astra-linux:latest"
redos: "localhost:5000/redos:latest"
hosts:
- name: alt-server
family: alt
groups: [servers]
- name: astra-server
family: astra
groups: [servers]
- name: redos-server
family: redos
groups: [servers]
```
## Лучшие практики
### 1. Версионирование образов
```bash
make docker-build VERSION=v1.0.0
```
### 2. Использование registry
```bash
make docker-push REGISTRY=my-registry.com VERSION=v1.0.0
```
### 3. Очистка старых образов
```bash
make docker-clean
```
## Troubleshooting
### Проблемы с сборкой
1. Проверьте доступность базовых образов
2. Убедитесь, что Docker запущен
3. Проверьте права доступа к Docker
### Проблемы с registry
1. Убедитесь, что registry доступен
2. Проверьте аутентификацию
3. Проверьте права на push
### Проблемы с образами
1. Проверьте размер образов
2. Убедитесь, что все зависимости установлены
3. Проверьте совместимость с базовыми образами
## Заключение
Эти Docker образы предоставляют готовую среду для тестирования Ansible ролей на различных операционных системах. Используйте их в своих preset'ах для создания универсальной системы тестирования.

View File

@@ -0,0 +1,51 @@
# AlmaLinux с systemd
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# https://hub.docker.com/_/almalinux
FROM almalinux:8
# Обновляем систему
RUN dnf update -y && dnf upgrade -y
# Устанавливаем systemd и необходимые пакеты
RUN dnf install -y \
systemd \
systemd-sysv \
dbus \
curl \
wget \
git \
vim \
nano \
jq \
python3 \
python3-pip \
&& dnf clean all
# Устанавливаем yq
RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \
&& chmod +x /usr/local/bin/yq
# Устанавливаем Docker
RUN dnf install -y dnf-plugins-core \
&& dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo \
&& dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Устанавливаем Docker Compose
RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \
&& chmod +x /usr/local/bin/docker-compose
# Настраиваем systemd
RUN systemctl set-default multi-user.target
# Создаем пользователя для Ansible
RUN useradd -m -s /bin/bash ansible \
&& echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Переключаемся на пользователя ansible
USER ansible
WORKDIR /home/ansible
# Команда по умолчанию
CMD ["/sbin/init"]

View File

@@ -0,0 +1,56 @@
# ALT Linux с systemd
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# https://hub.docker.com/_/alt/tags
FROM alt:p9
# Обновляем систему
RUN apt-get update && apt-get dist-upgrade -y
# Устанавливаем systemd и необходимые пакеты
RUN apt-get install -y \
systemd \
dbus \
curl \
wget \
git \
vim-enhanced \
nano \
htop \
tree \
jq \
python3 \
&& apt-get clean
# Устанавливаем pip для Python 3.7
RUN curl -sS https://bootstrap.pypa.io/pip/3.7/get-pip.py | python3
# Устанавливаем yq
RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \
&& chmod +x /usr/local/bin/yq
# Устанавливаем Docker вручную для ALT Linux
RUN apt-get update && apt-get install -y \
ca-certificates \
curl \
gnupg \
&& apt-get clean
# Устанавливаем Docker Compose
RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \
&& chmod +x /usr/local/bin/docker-compose
# Настраиваем systemd
RUN systemctl set-default multi-user.target
# Создаем пользователя для Ansible
RUN useradd -m -s /bin/bash ansible \
&& echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Переключаемся на пользователя ansible
USER ansible
WORKDIR /home/ansible
# Команда по умолчанию
CMD ["/sbin/init"]

View File

@@ -0,0 +1,89 @@
# Ansible Controller с предустановленными коллекциями
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
FROM ubuntu:22.04
# Обновляем систему
RUN apt-get update && apt-get upgrade -y && apt-get clean
# Устанавливаем Python и Ansible
RUN apt-get install -y \
python3 \
python3-pip \
python3-venv \
python3-dev \
build-essential \
&& apt-get clean
# Устанавливаем Ansible
RUN pip3 install ansible ansible-core
# Устанавливаем дополнительные пакеты
RUN apt-get install -y \
curl \
wget \
git \
vim \
nano \
htop \
tree \
jq \
&& apt-get clean
# Устанавливаем yq
RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \
&& chmod +x /usr/local/bin/yq
# Устанавливаем Docker CLI
RUN apt-get install -y docker.io docker-compose
# Устанавливаем kubectl
RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" \
&& chmod +x kubectl \
&& mv kubectl /usr/local/bin/
# Устанавливаем Helm
RUN curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Устанавливаем Kind
RUN curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-linux-amd64 \
&& chmod +x ./kind \
&& mv ./kind /usr/local/bin/
# Устанавливаем Istio CLI
RUN curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.22.1 sh - \
&& mv istio-1.22.1/bin/istioctl /usr/local/bin/ \
&& rm -rf istio-1.22.1
# Копируем requirements.yml
COPY requirements.yml /tmp/requirements.yml
# Устанавливаем Ansible коллекции
RUN ansible-galaxy collection install -r /tmp/requirements.yml
# Создаем пользователя ansible
RUN useradd -m -s /bin/bash ansible \
&& echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Создаем рабочую директорию
WORKDIR /ansible
# Устанавливаем права
RUN chown -R ansible:ansible /ansible
# Переключаемся на пользователя ansible
USER ansible
# Устанавливаем дополнительные роли
RUN ansible-galaxy install geerlingguy.docker \
&& ansible-galaxy install geerlingguy.kubernetes
# Настройки для работы с Docker
ENV DOCKER_HOST=unix:///var/run/docker.sock
ENV ANSIBLE_FORCE_COLOR=1
ENV ANSIBLE_STDOUT_CALLBACK=yaml
ENV ANSIBLE_CALLBACKS_ENABLED=profile_tasks
# Команда по умолчанию
CMD ["sleep", "infinity"]

View File

@@ -0,0 +1,23 @@
version: "3.9"
services:
ansible-controller:
build:
context: .
dockerfile: Dockerfile
container_name: ansible-controller
privileged: true
command: sleep infinity
environment:
DOCKER_HOST: unix:///var/run/docker.sock
ANSIBLE_VAULT_PASSWORD_FILE: /ansible/vault-password.txt
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- .:/ansible
working_dir: /ansible
networks:
- labnet
networks:
labnet:
external: true

View File

@@ -0,0 +1,9 @@
---
# Ansible Collections для Molecule Universal
collections:
- name: community.docker
version: ">=3.0.0"
- name: community.general
version: ">=7.0.0"
- name: ansible.posix
version: ">=1.5.4"

View File

@@ -0,0 +1,61 @@
# Astra Linux с systemd
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# https://registry.astralinux.ru/browse/library/
FROM registry.astralinux.ru/library/astra/ubi17:1.7.6.uu2
# Обновляем систему
RUN apt-get update && apt-get dist-upgrade -y
# Устанавливаем systemd и необходимые пакеты
RUN apt-get install -y \
systemd \
systemd-sysv \
dbus \
curl \
wget \
git \
vim \
nano \
htop \
tree \
jq \
python3 \
python3-pip \
&& apt-get clean
# Устанавливаем yq
RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \
&& chmod +x /usr/local/bin/yq
# Устанавливаем Docker вручную для AstraLinux
RUN apt-get update && apt-get install -y \
ca-certificates \
curl \
gnupg \
lsb-release \
&& mkdir -p /usr/share/keyrings \
&& curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \
&& echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian buster stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \
&& apt-get update \
&& apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin \
&& apt-get clean
# Устанавливаем Docker Compose
RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \
&& chmod +x /usr/local/bin/docker-compose
# Настраиваем systemd
RUN systemctl set-default multi-user.target
# Создаем пользователя для Ansible
RUN useradd -m -s /bin/bash ansible \
&& echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Переключаемся на пользователя ansible
USER ansible
WORKDIR /home/ansible
# Команда по умолчанию
CMD ["/sbin/init"]

View File

@@ -0,0 +1,48 @@
# CentOS с systemd
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
FROM quay.io/centos/centos:stream9
# Обновляем систему
RUN dnf update -y && dnf upgrade -y
# Устанавливаем systemd и необходимые пакеты
RUN dnf install -y --allowerasing \
systemd \
systemd-sysv \
dbus \
curl \
wget \
git \
vim \
nano \
jq \
python3 \
python3-pip \
&& dnf clean all
# Устанавливаем yq
RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \
&& chmod +x /usr/local/bin/yq
# Устанавливаем Docker
RUN curl -fsSL https://get.docker.com | sh
# Устанавливаем Docker Compose
RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \
&& chmod +x /usr/local/bin/docker-compose
# Настраиваем systemd
RUN systemctl set-default multi-user.target
# Создаем пользователя для Ansible
RUN useradd -m -s /bin/bash ansible \
&& echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Переключаемся на пользователя ansible
USER ansible
WORKDIR /home/ansible
# Команда по умолчанию
CMD ["/sbin/init"]

View File

@@ -0,0 +1,53 @@
# RED OS с systemd
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# https://registry.red-soft.ru/ubi7/ubi/tags
# docker search registry.red-soft.ru/ubi7/ubi
FROM registry.red-soft.ru/ubi7/ubi
# Обновляем систему
RUN dnf update -y && dnf upgrade -y
# Устанавливаем systemd и необходимые пакеты
RUN dnf install -y \
systemd \
systemd-sysv \
dbus \
curl \
wget \
git \
vim \
nano \
jq \
python3 \
python3-pip \
&& dnf clean all
# Устанавливаем yq
RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \
&& chmod +x /usr/local/bin/yq
# Устанавливаем Docker вручную для RED OS
RUN dnf install -y dnf-plugins-core \
&& dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo \
&& dnf install -y docker-ce docker-ce-cli containerd.io \
&& dnf clean all
# Устанавливаем Docker Compose
RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \
&& chmod +x /usr/local/bin/docker-compose
# Настраиваем systemd
RUN systemctl set-default multi-user.target
# Создаем пользователя для Ansible
RUN useradd -m -s /bin/bash ansible \
&& echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Переключаемся на пользователя ansible
USER ansible
WORKDIR /home/ansible
# Команда по умолчанию
CMD ["/sbin/init"]

View File

@@ -0,0 +1,48 @@
# RHEL с systemd
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
FROM registry.access.redhat.com/ubi8/ubi
# Обновляем систему
RUN dnf update -y && dnf upgrade -y
# Устанавливаем systemd и необходимые пакеты
RUN dnf install -y \
systemd \
systemd-sysv \
dbus \
curl \
wget \
git \
vim \
nano \
jq \
python3 \
python3-pip \
&& dnf clean all
# Устанавливаем yq
RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \
&& chmod +x /usr/local/bin/yq
# Устанавливаем Docker
RUN curl -fsSL https://get.docker.com | sh
# Устанавливаем Docker Compose
RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \
&& chmod +x /usr/local/bin/docker-compose
# Настраиваем systemd
RUN systemctl set-default multi-user.target
# Создаем пользователя для Ansible
RUN useradd -m -s /bin/bash ansible \
&& echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Переключаемся на пользователя ansible
USER ansible
WORKDIR /home/ansible
# Команда по умолчанию
CMD ["/sbin/init"]

View File

@@ -0,0 +1,50 @@
# Rocky Linux с systemd
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
FROM rockylinux:8
# Обновляем систему
RUN dnf update -y && dnf upgrade -y
# Устанавливаем systemd и необходимые пакеты
RUN dnf install -y \
systemd \
systemd-sysv \
dbus \
curl \
wget \
git \
vim \
nano \
jq \
python3 \
python3-pip \
&& dnf clean all
# Устанавливаем yq
RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \
&& chmod +x /usr/local/bin/yq
# Устанавливаем Docker
RUN dnf install -y dnf-plugins-core \
&& dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo \
&& dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Устанавливаем Docker Compose
RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \
&& chmod +x /usr/local/bin/docker-compose
# Настраиваем systemd
RUN systemctl set-default multi-user.target
# Создаем пользователя для Ansible
RUN useradd -m -s /bin/bash ansible \
&& echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Переключаемся на пользователя ansible
USER ansible
WORKDIR /home/ansible
# Команда по умолчанию
CMD ["/sbin/init"]

424
docs/examples.md Normal file
View File

@@ -0,0 +1,424 @@
# Примеры использования универсальной системы тестирования
## Пример 1: Тестирование кластера etcd + PostgreSQL + Patroni
### Описание
Этот пример демонстрирует тестирование высокодоступного кластера PostgreSQL с Patroni и etcd.
### Preset: etcd-patroni
```yaml
# molecule/presets/etcd-patroni.yml
hosts:
# ETCD кластер (5 узлов для высокой доступности)
- name: etcd1
family: debian
groups: [etcd, cluster]
- name: etcd2
family: rhel
groups: [etcd, cluster]
- name: etcd3
family: debian
groups: [etcd, cluster]
- name: etcd4
family: rhel
groups: [etcd, cluster]
- name: etcd5
family: debian
groups: [etcd, cluster]
# Patroni кластер (3 узла PostgreSQL)
- name: patroni1
family: rhel
groups: [patroni, database, cluster]
- name: patroni2
family: debian
groups: [patroni, database, cluster]
- name: patroni3
family: rhel
groups: [patroni, database, cluster]
# HAProxy для балансировки
- name: haproxy
family: debian
groups: [haproxy, loadbalancer]
publish: ["5000:5000", "5001:5001"] # RW и RO порты
# DinD узел для тестирования Docker Compose внутри
- name: app-dind
type: dind
groups: [apps, docker]
publish: ["8080:8080"]
```
### Запуск тестирования
```bash
# Информация о preset'е
make preset-info PRESET=etcd-patroni
# Тестирование с preset'ом
make preset-test PRESET=etcd-patroni
# Или через role test
make role test etcd-patroni
```
### Проверка результатов
```bash
# Проверить статус контейнеров
make container-info
# Проверить vault файлы
make vault-check
```
## Пример 2: Нагрузочное тестирование
### Описание
Этот пример демонстрирует тестирование под нагрузкой с множественными серверами и кэшем.
### Preset: performance
```yaml
# molecule/presets/performance.yml
hosts:
# Основные серверы (5 узлов)
- name: server1
family: debian
groups: [servers, web, app]
- name: server2
family: rhel
groups: [servers, web, app]
- name: server3
family: debian
groups: [servers, web, app]
- name: server4
family: rhel
groups: [servers, web, app]
- name: server5
family: debian
groups: [servers, web, app]
# База данных (3 узла)
- name: db1
family: rhel
groups: [database, db]
- name: db2
family: debian
groups: [database, db]
- name: db3
family: rhel
groups: [database, db]
# Кэш (3 узла Redis)
- name: cache1
family: debian
groups: [cache, redis]
- name: cache2
family: rhel
groups: [cache, redis]
- name: cache3
family: debian
groups: [cache, redis]
# Load balancer
- name: lb1
family: rhel
groups: [loadbalancer, haproxy]
publish: ["80:80", "443:443"]
# DinD узел для тестирования Docker Compose
- name: compose-dind
type: dind
groups: [apps, docker]
publish: ["8080:8080", "8081:8081"]
```
### Запуск тестирования
```bash
# Тестирование с performance preset'ом
make role test performance
# Проверка статуса
make container-info
```
## Пример 3: Тестирование безопасности
### Описание
Этот пример демонстрирует тестирование в безопасной среде с bastion хостами и изоляцией.
### Preset: security
```yaml
# molecule/presets/security.yml
hosts:
# Bastion хосты (точки входа)
- name: bastion1
family: rhel
groups: [bastion, security, jump]
publish: ["2222:22"]
- name: bastion2
family: debian
groups: [bastion, security, jump]
publish: ["2223:22"]
# Внутренние серверы (без внешнего доступа)
- name: internal1
family: rhel
groups: [internal, servers, app]
- name: internal2
family: debian
groups: [internal, servers, app]
- name: internal3
family: rhel
groups: [internal, servers, app]
# База данных (изолированная сеть)
- name: db-secure1
family: rhel
groups: [database, secure, internal]
- name: db-secure2
family: debian
groups: [database, secure, internal]
# Мониторинг и логирование
- name: monitor1
family: debian
groups: [monitoring, security, logs]
- name: monitor2
family: rhel
groups: [monitoring, security, logs]
# Firewall и сетевые компоненты
- name: fw1
family: rhel
groups: [firewall, network, security]
- name: fw2
family: debian
groups: [firewall, network, security]
# DOoD узел для тестирования Docker безопасности
- name: docker-secure
type: dood
family: debian
groups: [docker, security, apps]
publish: ["8080:8080"]
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
```
### Запуск тестирования
```bash
# Тестирование с security preset'ом
make role test security
# Проверка безопасности
make vault-check
make vault-scan
```
## Пример 4: Тестирование на разных ОС
### Описание
Этот пример демонстрирует тестирование на различных операционных системах.
### Preset: multi-os
```yaml
# molecule/presets/multi-os.yml
hosts:
# Debian/Ubuntu серверы
- name: ubuntu1
family: ubuntu
groups: [ubuntu, servers, web]
- name: debian1
family: debian
groups: [debian, servers, web]
- name: ubuntu2
family: ubuntu
groups: [ubuntu, servers, app]
- name: debian2
family: debian
groups: [debian, servers, app]
# RHEL/CentOS серверы
- name: rhel1
family: rhel
groups: [rhel, servers, web]
- name: centos1
family: centos
groups: [centos, servers, web]
- name: rhel2
family: rhel
groups: [rhel, servers, app]
- name: centos2
family: centos
groups: [centos, servers, app]
# База данных на разных ОС
- name: db-ubuntu
family: ubuntu
groups: [database, ubuntu, db]
- name: db-rhel
family: rhel
groups: [database, rhel, db]
# Load balancer
- name: lb-mixed
family: debian
groups: [loadbalancer, haproxy]
publish: ["80:80", "443:443"]
# DinD узел для тестирования Docker
- name: docker-mixed
type: dind
groups: [docker, apps]
publish: ["8080:8080"]
```
### Запуск тестирования
```bash
# Тестирование с multi-os preset'ом
make role test multi-os
# Проверка типов контейнеров
make container-types
```
## Пример 5: Создание собственного preset'а
### Описание
Этот пример демонстрирует создание собственного preset'а для специфических нужд.
### Создание preset'а
```bash
# Создать новый preset
cat > molecule/presets/my-custom.yml << 'EOF'
---
# Пресет для тестирования веб-приложения
# Автор: Ваше имя
# Сайт: https://your-site.com
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# systemd-ready образы
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
# Описание кластера
hosts:
# Веб-серверы
- name: web1
family: debian
groups: [web, servers]
publish: ["80:80", "443:443"]
- name: web2
family: rhel
groups: [web, servers]
publish: ["8080:80", "8443:443"]
# База данных
- name: db1
family: rhel
groups: [database, db]
- name: db2
family: debian
groups: [database, db]
# Кэш
- name: cache1
family: debian
groups: [cache, redis]
# DinD узел для тестирования
- name: app-dind
type: dind
groups: [apps, docker]
publish: ["8080:8080"]
EOF
```
### Использование preset'а
```bash
# Информация о preset'е
make preset-info PRESET=my-custom
# Тестирование с preset'ом
make preset-test PRESET=my-custom
# Или через role test
make role test my-custom
```
## Пример 6: Работа с Ansible Vault
### Создание vault файла
```bash
# Создать файл секретов
make vault create
# Ввести имя файла: secrets
# Ввести содержимое:
# ---
# database_password: "super_secret_password"
# api_key: "your_api_key_here"
# ssl_cert: "your_ssl_certificate"
```
### Использование в ролях
```yaml
# roles/my-role/tasks/main.yml
- name: Configure database
template:
src: database.conf.j2
dest: /etc/database.conf
vars:
db_password: "{{ database_password }}"
api_key: "{{ api_key }}"
```
### Проверка безопасности
```bash
# Проверить vault файлы
make vault-check
# Найти потенциальные секреты
make vault-scan
```
## Заключение
Эти примеры демонстрируют различные способы использования универсальной системы тестирования Ansible ролей. Вы можете:
1. Использовать готовые preset'ы для быстрого тестирования
2. Создавать собственные preset'ы для специфических нужд
3. Комбинировать различные типы контейнеров
4. Использовать Ansible Vault для безопасности
5. Тестировать на различных операционных системах
Для получения дополнительной информации используйте:
- `make help` - общая справка
- `make preset-list` - список preset'ов
- `make container-types` - типы контейнеров
- `make vault` - команды Vault

View File

@@ -0,0 +1,99 @@
# Тестирование vs Развертывание
## Автор: Сергей Антропов
## Сайт: https://devops.org.ru
## Различие между тестированием и развертыванием
### 🧪 Тестирование (molecule)
**Команда:** `make role test [preset]`
**Использует:**
- Динамический inventory, создаваемый в `molecule/default/create.yml`
- Preset файлы из `molecule/presets/`
- Docker контейнеры для изоляции тестов
- Временные контейнеры (u1, u2, u3)
**Процесс:**
1. Загружается preset конфигурация
2. Создаются Docker контейнеры согласно preset
3. Генерируется временный inventory файл
4. Запускаются тесты на контейнерах
5. Контейнеры удаляются после тестов
**Пример:**
```bash
make role test standart # Тестирование в 3 контейнерах
make role test minimal # Тестирование в 1 контейнере
```
### 🚀 Развертывание (deploy)
**Команда:** `make role deploy`
**Использует:**
- Статический inventory файл `inventory/hosts.ini`
- Реальные серверы
- SSH подключение
**Процесс:**
1. Проверяется наличие `inventory/hosts.ini`
2. Показывается содержимое inventory
3. Запускается dry-run (--check)
4. Запрашивается подтверждение
5. Выполняется развертывание на реальные серверы
**Пример:**
```bash
make role deploy # Развертывание на реальные серверы
```
## Конфигурация
### Для тестирования
- Preset файлы: `molecule/presets/*.yml`
- Динамический inventory создается в `create.yml`
- Контейнеры: Docker
### Для развертывания
- Inventory файл: `inventory/hosts.ini`
- Серверы: Реальные хосты
- Подключение: SSH
## Примеры конфигурации
### Preset для тестирования (molecule/presets/standart.yml)
```yaml
hosts:
- name: u1
family: debian
groups: [test]
- name: u2
family: rhel
groups: [test]
- name: u3
family: debian
groups: [test]
```
### Inventory для развертывания (inventory/hosts.ini)
```ini
[web_servers]
web1 ansible_host=192.168.1.10 ansible_user=ubuntu
web2 ansible_host=192.168.1.11 ansible_user=ubuntu
[db_servers]
db1 ansible_host=192.168.1.20 ansible_user=ubuntu
[all:vars]
ansible_ssh_private_key_file=~/.ssh/id_rsa
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
```
## Рекомендации
1. **Сначала тестируйте** с помощью `make role test [preset]`
2. **Затем развертывайте** с помощью `make role deploy`
3. **Используйте разные preset'ы** для разных сценариев тестирования
4. **Настройте inventory** для ваших реальных серверов

281
docs/universal-testing.md Normal file
View File

@@ -0,0 +1,281 @@
# Универсальная система тестирования Ansible ролей
## Обзор
Эта система предоставляет универсальную среду для тестирования и деплоя Ansible ролей с поддержкой различных типов контейнеров, автоматической генерации инвентаря и интеграции с Ansible Vault.
## Основные возможности
### 🐳 Типы контейнеров
#### Systemd контейнеры (по умолчанию)
- Полная поддержка systemd сервисов
- Работа как виртуальные машины
- Подходит для тестирования ролей
#### DinD (Docker-in-Docker)
- Изолированный Docker daemon
- Подходит для тестирования Docker Compose
- Полная изоляция от хостового Docker
#### DOoD (Docker-out-of-Docker)
- Доступ к хостовому Docker daemon
- Быстрое тестирование
- Подходит для CI/CD
### 📋 Preset'ы
#### etcd-patroni
- Кластер etcd (5 узлов)
- Кластер PostgreSQL с Patroni (3 узла)
- HAProxy для балансировки
- DinD узел для тестирования
#### performance
- 5 серверов приложений
- 3 узла базы данных
- 3 узла кэша Redis
- Load balancer
- DinD узел для тестирования
#### security
- Bastion хосты
- Внутренние серверы
- Изолированная база данных
- Мониторинг и логирование
- Firewall компоненты
- DOoD узел для тестирования
#### multi-os
- Тестирование на разных ОС
- Ubuntu, Debian, RHEL, CentOS
- Смешанные конфигурации
- DinD узел для тестирования
### 🔐 Ansible Vault интеграция
- Автоматическая расшифровка перед тестированием
- Безопасное хранение секретов
- Автоматическая повторная шифровка после тестирования
- Поддержка множественных vault'ов
## Использование
### Базовые команды
```bash
# Показать все preset'ы
make preset-list
# Информация о preset'е
make preset-info PRESET=etcd-patroni
# Тестирование с preset'ом
make preset-test PRESET=etcd-patroni
# Типы контейнеров
make container-types
# Информация о контейнерах
make container-info
# Проверка vault файлов
make vault-check
# Поиск секретов
make vault-scan
```
### Тестирование ролей
```bash
# С default preset
make role test
# С конкретным preset'ом
make role test etcd-patroni
make role test performance
make role test security
make role test multi-os
```
### Работа с Ansible Vault
```bash
# Создать файл секретов
make vault create
# Редактировать секреты
make vault edit
# Показать секреты
make vault show
# Зашифровать файл
make vault encrypt
# Расшифровать файл
make vault decrypt
```
## Структура проекта
```
.
├── molecule/
│ ├── default/
│ │ ├── create.yml # Создание контейнеров
│ │ ├── destroy.yml # Удаление контейнеров
│ │ ├── converge.yml # Запуск плейбуков
│ │ └── verify.yml # Проверка результатов
│ └── presets/
│ ├── etcd-patroni.yml
│ ├── performance.yml
│ ├── security.yml
│ └── multi-os.yml
├── files/
│ ├── requirements.yml
│ └── playbooks/
│ └── site.yml
├── vault/
│ └── secrets.yml
└── Makefile
```
## Создание собственных preset'ов
### Пример preset'а
```yaml
---
# Пресет для тестирования кластера etcd + PostgreSQL + Patroni
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# systemd-ready образы
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
# Описание кластера
hosts:
# Systemd узлы
- name: server1
family: debian
groups: [servers, web]
publish: ["80:80"]
# DinD узел
- name: app-dind
type: dind
groups: [apps, docker]
publish: ["8080:8080"]
# DOoD узел
- name: docker-secure
type: dood
family: debian
groups: [docker, security]
publish: ["8081:8081"]
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
```
### Параметры хостов
- `name` - имя хоста
- `family` - семейство ОС (debian, rhel, ubuntu, centos)
- `type` - тип контейнера (dind, dood)
- `groups` - группы для инвентаря
- `publish` - порты для публикации
- `env` - переменные окружения
- `volumes` - дополнительные тома
- `capabilities` - дополнительные возможности
## Лучшие практики
### 1. Использование групп
```yaml
hosts:
- name: web1
groups: [web, servers, production]
- name: db1
groups: [database, servers, production]
```
### 2. Безопасность
```yaml
# Используйте Ansible Vault для секретов
vault_targets:
- /ansible/vault/secrets.yml
- /ansible/files/playbooks/group_vars/*/vault.yml
- /ansible/files/playbooks/host_vars/*/vault.yml
```
### 3. Тестирование
```yaml
# Проверяйте различные сценарии
- name: Test web servers
hosts: web
tasks:
- name: Check nginx status
systemd:
name: nginx
state: started
```
## Troubleshooting
### Проблемы с контейнерами
```bash
# Проверить статус контейнеров
make container-info
# Очистить Docker ресурсы
make docker clean
```
### Проблемы с Vault
```bash
# Проверить vault файлы
make vault-check
# Найти потенциальные секреты
make vault-scan
```
### Проблемы с preset'ами
```bash
# Показать все preset'ы
make preset-list
# Информация о preset'е
make preset-info PRESET=имя_пресета
```
## Заключение
Универсальная система тестирования Ansible ролей предоставляет мощные инструменты для тестирования ролей в различных сценариях. Используйте preset'ы для быстрого создания тестовых сред, различные типы контейнеров для изоляции и Ansible Vault для безопасности.
Для получения дополнительной информации используйте:
- `make help` - общая справка
- `make role` - команды для ролей
- `make molecule` - команды Molecule
- `make vault` - команды Vault

View File

@@ -1 +0,0 @@
[all]

16
inventory/hosts.ini Normal file
View File

@@ -0,0 +1,16 @@
# Инвентори для развертывания на реальные серверы
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# Примеры серверов (замените на ваши реальные серверы)
[web_servers]
# web1 ansible_host=192.168.1.10 ansible_user=ubuntu
# web2 ansible_host=192.168.1.11 ansible_user=ubuntu
[db_servers]
# db1 ansible_host=192.168.1.20 ansible_user=ubuntu
[all:vars]
# Общие переменные для всех серверов
ansible_ssh_private_key_file=~/.ssh/id_rsa
ansible_ssh_common_args='-o StrictHostKeyChecking=no'

View File

@@ -1,6 +1,75 @@
---
- name: Converge
hosts: all
vars_files:
- ../../vars/secrets.yml
roles:
- hosts: localhost
gather_facts: false
vars:
# Получаем preset из переменной окружения или используем default
preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}"
preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml"
# перечисли файлы/глобы, которые нужно временно расшифровать
vault_targets:
- /ansible/vault/secrets.yml
- /ansible/files/playbooks/group_vars/*/vault.yml
- /ansible/files/playbooks/host_vars/*/vault.yml
- /ansible/roles/**/vars/vault.yml
tasks:
- name: Load preset configuration
include_vars: "{{ preset_file }}"
when: preset_file is file
ignore_errors: true
- name: Install collections
community.docker.docker_container_exec:
container: ansible-controller
command: bash -lc "ansible-galaxy collection install -r /ansible/requirements.yml --force --no-deps --upgrade >/dev/null 2>&1 || true"
- name: Preflight vault — normalize state (encrypt if plaintext, then decrypt)
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -euo pipefail; shopt -s nullglob globstar;
for p in {{ vault_targets | map('quote') | join(' ') }}; do
for f in $p; do
[ -f "$f" ] || continue;
if head -n1 "$f" | grep -q "^\$ANSIBLE_VAULT;"; then
echo "[vault] already encrypted: $f";
else
echo "[vault] plaintext -> encrypt: $f";
ansible-vault encrypt --encrypt-vault-id default --vault-password-file /ansible/vault-password.txt "$f";
fi
echo "[vault] decrypt for run: $f";
ansible-vault decrypt --vault-password-file /ansible/vault-password.txt "$f";
done
done
'
- name: Run lab playbook
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc "
ANSIBLE_ROLES_PATH=/ansible/roles
ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /ansible/files/playbooks/site.yml
"
- name: Post-run — re-encrypt secrets
community.docker.docker_container_exec:
container: ansible-controller
command: >
bash -lc '
set -euo pipefail; shopt -s nullglob globstar;
for p in {{ vault_targets | map('quote') | join(' ') }}; do
for f in $p; do
[ -f "$f" ] || continue;
if head -n1 "$f" | grep -q "^\$ANSIBLE_VAULT;"; then
echo "[vault] ok (encrypted): $f";
else
echo "[vault] encrypt back: $f";
ansible-vault encrypt --encrypt-vault-id default --vault-password-file /ansible/vault-password.txt "$f" || true;
fi
done
done
'
ignore_errors: true

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

@@ -0,0 +1,165 @@
---
- hosts: localhost
gather_facts: false
vars:
# Получаем preset из переменной окружения или используем default
preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}"
preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml"
# Fallback значения если preset файл не найден
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
ubuntu: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
centos: "quay.io/centos/centos:stream9-systemd"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
hosts:
- name: u1
family: debian
groups: [test]
tasks:
- name: Install required collections
command: ansible-galaxy collection install -r /workspace/requirements.yml
delegate_to: localhost
ignore_errors: true
register: collections_install
changed_when: false
run_once: true
become: true
vars:
ansible_python_interpreter: /usr/bin/python3
environment:
ANSIBLE_COLLECTIONS_PATH: /usr/share/ansible/collections
- name: Load preset configuration
include_vars: "{{ preset_file }}"
when: preset_file is file
ignore_errors: true
- 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 }}" }
when: item.family is defined and images[item.family] is defined
- 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([]) }}"
capabilities: "{{ systemd_defaults.capabilities | default([]) }}"
published_ports: "{{ item.publish | default([]) }}"
environment: "{{ item.env | default({}) }}"
state: started
restart_policy: unless-stopped
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control: { label: "{{ item.name }}" }
when: item.family is defined and images[item.family] is defined
# DinD nodes
- name: Start DinD nodes (docker:27-dind)
community.docker.docker_container:
name: "{{ item.name }}"
image: "docker:27-dind"
networks:
- name: "{{ docker_network }}"
privileged: true
environment:
DOCKER_TLS_CERTDIR: ""
published_ports: "{{ item.publish | default([]) }}"
volumes: "{{ (item.volumes | default([])) + [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([]) }}"
capabilities: "{{ systemd_defaults.capabilities | default([]) }}"
published_ports: "{{ item.publish | default([]) }}"
environment: "{{ item.env | default({}) }}"
state: started
restart_policy: unless-stopped
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list }}"
loop_control: { label: "{{ item.name }}" }
when: item.family is defined and images[item.family] is defined
# Build groups map
- name: Initialize groups map
set_fact:
groups_map: {}
- 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"
- name: Display inventory summary
debug:
msg: |
📋 Inventory Summary:
- Total hosts: {{ hosts | length }}
- Groups: {{ groups_map.keys() | list | join(', ') }}
- Systemd nodes: {{ hosts | selectattr('type','undefined') | list | length }}
- DinD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }}
- DOoD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list | length }}

View File

@@ -1,8 +1,60 @@
- name: Destroy containers on interrupt
hosts: localhost
---
- hosts: localhost
gather_facts: false
vars:
# Получаем preset из переменной окружения или используем default
preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}"
preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml"
# Fallback значения если preset файл не найден
docker_network: labnet
hosts:
- name: u1
family: debian
groups: [test]
tasks:
- name: Ensure containers are destroyed
docker_container:
- name: Load preset configuration
include_vars: "{{ preset_file }}"
when: preset_file is file
ignore_errors: true
- name: Stop and remove containers
community.docker.docker_container:
name: "{{ item.name }}"
state: absent
loop: "{{ molecule_yml.platforms }}"
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 custom volumes
community.docker.docker_volume:
name: "{{ item.volumes | default([]) | select('match', '^[^:]+$') | list }}"
state: absent
loop: "{{ hosts }}"
loop_control: { label: "{{ item.name }}" }
ignore_errors: true
when: item.volumes is defined
- name: Remove network
community.docker.docker_network:
name: "{{ docker_network }}"
state: absent
ignore_errors: true
- name: Display cleanup summary
debug:
msg: |
🧹 Cleanup Summary:
- Removed containers: {{ hosts | length }}
- Removed DinD volumes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }}
- Network: {{ docker_network }}

View File

@@ -1,61 +1,38 @@
---
dependency:
name: galaxy
enabled: false
options:
requirements-file: requirements.yml
# Универсальная конфигурация Molecule
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
driver:
name: docker
platforms:
- name: centos
image: "inecs/ansible:centos"
privileged: true
# Платформы будут созданы динамически через preset файлы
- name: placeholder
image: ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy
pre_build_image: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
- /var/run/docker.sock:/var/run/docker.sock
tmpfs:
- /tmp
- /run
- name: ubuntu
image: "inecs/ansible:ubuntu"
privileged: true
pre_build_image: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
- /var/run/docker.sock:/var/run/docker.sock
tmpfs:
- /tmp
- /run
provisioner:
name: ansible
connection_options:
ansible_connection: docker
ansible_user: root
config_options:
defaults:
stdout_callback: yaml
env:
ANSIBLE_PYTHON_INTERPRETER: /usr/bin/python3
lint:
name: ansible-lint
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
scenario:
name: default
test_sequence:
- dependency
- cleanup
- destroy
- syntax
- create
- prepare
- converge
- idempotence
- side_effect
- verify
- cleanup
- destroy
lint: |-
set -e
ansible-lint /workspace/roles/

View File

@@ -1,43 +0,0 @@
- name: Prepare
hosts: all
tasks:
- name: Detect OS family
ansible.builtin.setup:
gather_subset:
- "min"
- name: Обновляем пакеты для работы с Ansible в RockyLinux (Centos/RedHat)
when: ansible_facts['os_family'] == "RedHat"
block:
- name: Устанавливаем репозиторий AppStream (если его нет)
ansible.builtin.raw: dnf config-manager --set-enabled appstream
changed_when: false
- name: Установить rsync
ansible.builtin.raw: dnf install -y rsync
changed_when: false
- name: Устанавливаем Python 3.8
ansible.builtin.raw: dnf install -y python38 python38-pip
changed_when: false
- name: Обновляем символическую ссылку python3
ansible.builtin.raw: alternatives --set python /usr/bin/python3.8
changed_when: false
# - name: Fix repository URLs
# ansible.builtin.command:
# cmd: sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
# changed_when: false
# - name: Update baseurl
# ansible.builtin.command:
# cmd: sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
# changed_when: false
# - name: Install required packages
# ansible.builtin.yum:
# name:
# - epel-release
# - python3
# - python3-pip
# state: present

View File

@@ -1,7 +0,0 @@
---
- name: Prepare
hosts: all
tasks:
- name: Reun verify
debug:
msg: "Hello, Verify!"

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: ../../deploy.yml

View File

@@ -1,132 +1,122 @@
---
# Проверка работы systemd, docker и docker-compose в образах
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
- hosts: localhost
gather_facts: false
vars:
# Получаем preset из переменной окружения или используем default
preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}"
preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml"
# Fallback значения если preset файл не найден
docker_network: labnet
hosts:
- name: u1
family: debian
groups: [test]
- name: Verify systemd, docker and docker-compose services
hosts: all
gather_facts: true
tasks:
- name: Display OS information
debug:
msg: "Тестирование на {{ ansible_distribution }} {{ ansible_distribution_version }}"
- name: Load preset configuration
include_vars: "{{ preset_file }}"
when: preset_file is file
ignore_errors: true
- name: Check if systemd is available and running
systemd:
name: systemd
state: started
# Проверка systemd узлов
- name: Check systemd nodes status
community.docker.docker_container_exec:
container: "{{ item.name }}"
command: systemctl is-system-running
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control: { label: "{{ item.name }}" }
register: systemd_status
failed_when: false
ignore_errors: true
- name: Display systemd status
- name: Display systemd nodes status
debug:
msg: "Systemd статус: {{ 'Доступен и запущен' if systemd_status is succeeded else 'Недоступен или не запущен' }}"
msg: "Systemd node {{ item.0.name }}: {{ item.1.stdout | default('unknown') }}"
loop: "{{ systemd_status.results | default([]) }}"
when: systemd_status is defined
- name: Check systemd version
command: systemd --version
register: systemd_version
failed_when: false
changed_when: false
# Проверка DinD узлов
- name: Check DinD nodes docker daemon
community.docker.docker_container_exec:
container: "{{ item.name }}"
command: docker version --format '{{.Server.Version}}'
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}"
loop_control: { label: "{{ item.name }}" }
register: dind_status
ignore_errors: true
- name: Display systemd version
- name: Display DinD nodes status
debug:
msg: "Версия systemd: {{ systemd_version.stdout_lines[0] if systemd_version.stdout_lines else 'Не определена' }}"
msg: "DinD node {{ item.0.name }}: Docker {{ item.1.stdout | default('not running') }}"
loop: "{{ dind_status.results | default([]) }}"
when: dind_status is defined
- name: Check if docker service exists
stat:
path: /usr/bin/docker
register: docker_binary
# Проверка DOoD узлов
- name: Check DOoD nodes docker access
community.docker.docker_container_exec:
container: "{{ item.name }}"
command: docker ps --format '{{.Names}}'
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list }}"
loop_control: { label: "{{ item.name }}" }
register: dood_status
ignore_errors: true
- name: Check if docker service exists (alternative path)
stat:
path: /usr/local/bin/docker
register: docker_binary_alt
- name: Display docker binary status
- name: Display DOoD nodes status
debug:
msg: "Docker binary: {{ 'Найден в /usr/bin/docker' if docker_binary.stat.exists else ('Найден в /usr/local/bin/docker' if docker_binary_alt.stat.exists else 'Не найден') }}"
msg: "DOoD node {{ item.0.name }}: Can access {{ item.1.stdout_lines | length | default(0) }} containers"
loop: "{{ dood_status.results | default([]) }}"
when: dood_status is defined
- name: Check docker version
command: docker --version
register: docker_version
failed_when: false
changed_when: false
# Проверка сетевого подключения
- name: Test network connectivity between nodes
community.docker.docker_container_exec:
container: "{{ item.0.name }}"
command: ping -c 1 {{ item.1.name }}
loop: "{{ hosts | subelements(hosts, 'name') }}"
loop_control: { label: "{{ item.0.name }} -> {{ item.1.name }}" }
when: item.0.name != item.1.name
register: ping_results
ignore_errors: true
- name: Display docker version
- name: Display network connectivity results
debug:
msg: "Версия Docker: {{ docker_version.stdout if docker_version.stdout else 'Docker не установлен' }}"
msg: "Network test {{ item.0.name }} -> {{ item.1.name }}: {{ 'OK' if item.2.rc == 0 else 'FAILED' }}"
loop: "{{ ping_results.results | default([]) }}"
when: ping_results is defined
- name: Check if docker daemon is running
command: docker info
register: docker_info
failed_when: false
changed_when: false
# Проверка портов
- name: Check published ports
community.docker.docker_container_exec:
container: "{{ item.name }}"
command: netstat -tlnp
loop: "{{ hosts | selectattr('publish','defined') | list }}"
loop_control: { label: "{{ item.name }}" }
register: port_status
ignore_errors: true
- name: Display docker daemon status
- name: Display port status
debug:
msg: "Docker daemon: {{ 'Запущен' if docker_info is succeeded else 'Не запущен или недоступен' }}"
msg: "Node {{ item.0.name }} ports: {{ item.1.stdout_lines | select('match', 'LISTEN') | list | length }} listening"
loop: "{{ port_status.results | default([]) }}"
when: port_status is defined
- name: Check if docker-compose binary exists
stat:
path: /usr/local/bin/docker-compose
register: docker_compose_binary
- name: Check if docker-compose binary exists (alternative path)
stat:
path: /usr/bin/docker-compose
register: docker_compose_binary_alt
- name: Check if docker compose plugin exists
command: docker compose version
register: docker_compose_plugin
failed_when: false
changed_when: false
- name: Display docker-compose status
debug:
msg: "Docker Compose: {{ 'Найден как binary' if docker_compose_binary.stat.exists or docker_compose_binary_alt.stat.exists else ('Найден как plugin' if docker_compose_plugin is succeeded else 'Не найден') }}"
- name: Display docker-compose version
debug:
msg: "Версия Docker Compose: {{ docker_compose_plugin.stdout if docker_compose_plugin is succeeded else 'Docker Compose не установлен' }}"
- name: Test docker functionality
command: docker run --rm hello-world
register: docker_test
failed_when: false
changed_when: false
- name: Display docker test result
debug:
msg: "Тест Docker: {{ 'Успешно' if docker_test is succeeded else 'Ошибка - ' + docker_test.stderr }}"
- name: Check systemd services status
command: systemctl list-units --type=service --state=running
register: running_services
failed_when: false
changed_when: false
- name: Display running services count
debug:
msg: "Количество запущенных сервисов: {{ running_services.stdout_lines | length }}"
- name: Check for docker-related systemd services
command: systemctl list-units --type=service | grep -i docker
register: docker_services
failed_when: false
changed_when: false
- name: Display docker services
debug:
msg: "Docker сервисы: {{ docker_services.stdout_lines if docker_services.stdout_lines else 'Не найдены' }}"
- name: Final summary
# Проверка групп
- name: Display inventory groups
debug:
msg: |
========================================
РЕЗУЛЬТАТЫ ПРОВЕРКИ ОБРАЗА {{ ansible_distribution }}:
========================================
Systemd: {{ '✓ Работает' if systemd_status is succeeded else '✗ Не работает' }}
Docker: {{ '✓ Установлен и работает' if docker_info is succeeded else '✗ Не установлен или не работает' }}
Docker Compose: {{ '✓ Доступен' if (docker_compose_binary.stat.exists or docker_compose_binary_alt.stat.exists or docker_compose_plugin is succeeded) else '✗ Недоступен' }}
========================================
📋 Inventory Groups:
{% for group, members in (groups_map | default({}) | dictsort) %}
- {{ group }}: {{ members | join(', ') }}
{% endfor %}
# Финальная сводка
- name: Display verification summary
debug:
msg: |
✅ Verification Summary:
- Total hosts: {{ hosts | length }}
- Systemd nodes: {{ hosts | selectattr('type','undefined') | list | length }}
- DinD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }}
- DOoD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list | length }}
- Groups: {{ groups_map.keys() | list | join(', ') }}
- Network: {{ docker_network }}

View File

@@ -0,0 +1,29 @@
---
#description: Стандартный пресет по умолчанию для тестирования с 2 хостами (Debian + RHEL)
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# systemd-ready образы
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
hosts:
# Стандартный набор - 2 хоста для базового тестирования
- name: u1
family: debian
groups: [test, web]
- name: u2
family: rhel
groups: [test, web]

View File

@@ -0,0 +1,44 @@
---
#description: Пресет с Docker контейнерами (DinD + DOoD) для тестирования Docker-задач
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# systemd-ready образы
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
hosts:
# Тестовые хосты
- name: test1
family: debian
groups: [test]
- name: test2
family: rhel
groups: [test]
# DinD узел (Docker-in-Docker)
- name: docker1
type: dind
groups: [docker]
publish: ["8080:8080"]
# DOoD узел (Docker-out-of-Docker)
- name: dood1
type: dood
family: debian
groups: [dood]
publish: ["8081:8081"]
env:
DOCKER_HOST: unix:///var/run/docker.sock

View File

@@ -0,0 +1,62 @@
---
#description: Пресет для тестирования кластера etcd + PostgreSQL + Patroni (9 хостов)
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# systemd-ready образы
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
# Описание кластера etcd + Patroni + HAProxy
hosts:
# ETCD кластер (5 узлов для высокой доступности)
- name: etcd1
family: debian
groups: [etcd, cluster]
- name: etcd2
family: rhel
groups: [etcd, cluster]
- name: etcd3
family: debian
groups: [etcd, cluster]
- name: etcd4
family: rhel
groups: [etcd, cluster]
- name: etcd5
family: debian
groups: [etcd, cluster]
# Patroni кластер (3 узла PostgreSQL)
- name: patroni1
family: rhel
groups: [patroni, database, cluster]
- name: patroni2
family: debian
groups: [patroni, database, cluster]
- name: patroni3
family: rhel
groups: [patroni, database, cluster]
# HAProxy для балансировки
- name: haproxy
family: debian
groups: [haproxy, loadbalancer]
publish: ["5000:5000", "5001:5001"] # RW и RO порты
# DinD узел для тестирования Docker Compose внутри
- name: app-dind
type: dind
groups: [apps, docker]
publish: ["8080:8080"]

View File

@@ -0,0 +1,25 @@
---
#description: Минимальный пресет для быстрого тестирования с 1 хостом (Debian)
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# systemd-ready образы
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
hosts:
# Минимальный набор - один хост
- name: u1
family: debian
groups: [test]

View File

@@ -0,0 +1,70 @@
---
#description: Пресет для тестирования на разных ОС с 12 хостами (Debian + RHEL)
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# systemd-ready образы для разных ОС
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
# Описание кластера с разными ОС
hosts:
# Debian серверы
- name: debian1
family: debian
groups: [debian, servers, web]
- name: debian2
family: debian
groups: [debian, servers, web]
- name: debian3
family: debian
groups: [debian, servers, app]
- name: debian4
family: debian
groups: [debian, servers, app]
# RHEL серверы
- name: rhel1
family: rhel
groups: [rhel, servers, web]
- name: rhel2
family: rhel
groups: [rhel, servers, web]
- name: rhel3
family: rhel
groups: [rhel, servers, app]
- name: rhel4
family: rhel
groups: [rhel, servers, app]
# База данных на разных ОС
- name: db-debian
family: debian
groups: [database, debian, db]
- name: db-rhel
family: rhel
groups: [database, rhel, db]
# Load balancer
- name: lb-mixed
family: debian
groups: [loadbalancer, haproxy]
publish: ["80:80", "443:443"]
# DinD узел для тестирования Docker
- name: docker-mixed
type: dind
groups: [docker, apps]
publish: ["8080:8080"]

View File

@@ -0,0 +1,73 @@
---
#description: Пресет для нагрузочного тестирования с 12 хостами (серверы + БД + кэш)
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# systemd-ready образы
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
# Описание кластера для нагрузочного тестирования
hosts:
# Основные серверы (5 узлов)
- name: server1
family: debian
groups: [servers, web, app]
- name: server2
family: rhel
groups: [servers, web, app]
- name: server3
family: debian
groups: [servers, web, app]
- name: server4
family: rhel
groups: [servers, web, app]
- name: server5
family: debian
groups: [servers, web, app]
# База данных (3 узла)
- name: db1
family: rhel
groups: [database, db]
- name: db2
family: debian
groups: [database, db]
- name: db3
family: rhel
groups: [database, db]
# Кэш (3 узла Redis)
- name: cache1
family: debian
groups: [cache, redis]
- name: cache2
family: rhel
groups: [cache, redis]
- name: cache3
family: debian
groups: [cache, redis]
# Load balancer
- name: lb1
family: rhel
groups: [loadbalancer, haproxy]
publish: ["80:80", "443:443"]
# DinD узел для тестирования Docker Compose
- name: compose-dind
type: dind
groups: [apps, docker]
publish: ["8080:8080", "8081:8081"]

View File

@@ -0,0 +1,76 @@
---
#description: Пресет для тестирования безопасности с 10 хостами (bastion + internal + monitoring)
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# systemd-ready образы
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
# Описание кластера для тестирования безопасности
hosts:
# Bastion хосты (точки входа)
- name: bastion1
family: rhel
groups: [bastion, security, jump]
publish: ["2222:22"]
- name: bastion2
family: debian
groups: [bastion, security, jump]
publish: ["2223:22"]
# Внутренние серверы (без внешнего доступа)
- name: internal1
family: rhel
groups: [internal, servers, app]
- name: internal2
family: debian
groups: [internal, servers, app]
- name: internal3
family: rhel
groups: [internal, servers, app]
# База данных (изолированная сеть)
- name: db-secure1
family: rhel
groups: [database, secure, internal]
- name: db-secure2
family: debian
groups: [database, secure, internal]
# Мониторинг и логирование
- name: monitor1
family: debian
groups: [monitoring, security, logs]
- name: monitor2
family: rhel
groups: [monitoring, security, logs]
# Firewall и сетевые компоненты
- name: fw1
family: rhel
groups: [firewall, network, security]
- name: fw2
family: debian
groups: [firewall, network, security]
# DOoD узел для тестирования Docker безопасности
- name: docker-secure
type: dood
family: debian
groups: [docker, security, apps]
publish: ["8080:8080"]
env:
DOCKER_HOST: "unix:///var/run/docker.sock"

View File

@@ -0,0 +1,32 @@
---
#description: Стандартный пресет для тестирования с 3 хостами (Debian + RHEL)
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# systemd-ready образы
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
rhel: "quay.io/centos/centos:stream9-systemd"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
hosts:
# Стандартный набор - 3 хоста
- name: u1
family: debian
groups: [test]
- name: u2
family: rhel
groups: [test]
- name: u3
family: debian
groups: [test]

25
molecule/presets/test.yml Normal file
View File

@@ -0,0 +1,25 @@
---
#description: Минимальный пресет для быстрого тестирования с 1 хостом (Debian)
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
docker_network: labnet
generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini"
# systemd-ready образы
images:
debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy"
systemd_defaults:
privileged: true
command: "/sbin/init"
volumes:
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
tmpfs: ["/run", "/run/lock"]
capabilities: ["SYS_ADMIN"]
hosts:
# Минимальный набор - один хост
- name: u1
family: debian
groups: [test]

View File

@@ -1,4 +1,9 @@
---
# Ansible Collections для Molecule Universal
collections:
- name: maxhoesel.proxmox
version: 5.0.1
- name: community.docker
version: ">=3.0.0"
- name: community.general
version: ">=7.0.0"
- name: ansible.posix
version: ">=1.5.4"

View File

@@ -1 +0,0 @@
---

View File

@@ -0,0 +1,60 @@
---
# Переменные по умолчанию для роли nginx
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# Основные настройки nginx
nginx_user: "nginx"
nginx_worker_processes: "auto"
nginx_worker_connections: 1024
nginx_keepalive_timeout: 65
# Настройки сервера
nginx_server_name: "{{ ansible_fqdn | default(ansible_hostname) }}"
nginx_listen_port: 80
nginx_root_dir: "/var/www/html"
nginx_index_file: "index.html"
# Настройки логов
nginx_access_log: "/var/log/nginx/access.log"
nginx_error_log: "/var/log/nginx/error.log"
# Настройки безопасности
nginx_server_tokens: "off"
nginx_hide_version: true
# Настройки производительности
nginx_sendfile: "on"
nginx_tcp_nopush: "on"
nginx_tcp_nodelay: "on"
# Настройки gzip
nginx_gzip: true
nginx_gzip_vary: "on"
nginx_gzip_min_length: 1024
nginx_gzip_types:
- "text/plain"
- "text/css"
- "text/xml"
- "text/javascript"
- "application/javascript"
- "application/xml+rss"
- "application/json"
# Настройки для разных ОС
nginx_packages:
- nginx
# Дополнительные пакеты для Ubuntu/Debian
nginx_ubuntu_packages:
- nginx
- nginx-common
# Дополнительные пакеты для RHEL/CentOS
nginx_rhel_packages:
- nginx
- nginx-mod-http-geoip
- nginx-mod-http-image-filter
- nginx-mod-http-xslt-filter
- nginx-mod-mail
- nginx-mod-stream

View File

@@ -0,0 +1,44 @@
---
# Обработчики для роли nginx
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
- name: Restart nginx
systemd:
name: nginx
state: restarted
listen: restart nginx
tags:
- nginx
- service
- restart
- name: Reload nginx
systemd:
name: nginx
state: reloaded
listen: reload nginx
tags:
- nginx
- service
- reload
- name: Start nginx
systemd:
name: nginx
state: started
listen: start nginx
tags:
- nginx
- service
- start
- name: Stop nginx
systemd:
name: nginx
state: stopped
listen: stop nginx
tags:
- nginx
- service
- stop

26
roles/nginx/meta/main.yml Normal file
View File

@@ -0,0 +1,26 @@
---
# Метаданные роли nginx
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
galaxy_info:
author: Сергей Антропов
description: Простая роль для установки и настройки nginx
company: DevOps.org.ru
license: MIT
min_ansible_version: "2.9"
platforms:
- name: Ubuntu
versions:
- jammy
- focal
- name: EL
versions:
- all
galaxy_tags:
- web
- nginx
- http
- server
dependencies: []

196
roles/nginx/tasks/main.yml Normal file
View File

@@ -0,0 +1,196 @@
---
# Основные задачи для роли nginx
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
- name: Установка nginx на Ubuntu/Debian
apt:
name: "{{ nginx_ubuntu_packages }}"
state: present
update_cache: true
when: ansible_os_family == "Debian"
tags:
- nginx
- install
- debian
- name: Установка nginx на RHEL/CentOS
yum:
name: "{{ nginx_rhel_packages }}"
state: present
when: ansible_os_family == "RedHat"
tags:
- nginx
- install
- rhel
- name: Включение и запуск nginx на Ubuntu/Debian
systemd:
name: nginx
enabled: true
state: started
when: ansible_os_family == "Debian"
tags:
- nginx
- service
- debian
- name: Включение и запуск nginx на RHEL/CentOS
systemd:
name: nginx
enabled: true
state: started
when: ansible_os_family == "RedHat"
tags:
- nginx
- service
- rhel
- name: Создание директории для веб-контента
file:
path: "{{ nginx_root_dir }}"
state: directory
owner: "{{ nginx_user }}"
group: "{{ nginx_user }}"
mode: '0755'
tags:
- nginx
- config
- directories
- name: Создание тестовой страницы
copy:
content: |
<!DOCTYPE html>
<html>
<head>
<title>Nginx Test Page</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.container { max-width: 600px; margin: 0 auto; }
h1 { color: #333; }
.info { background: #f4f4f4; padding: 20px; border-radius: 5px; }
</style>
</head>
<body>
<div class="container">
<h1>Nginx работает!</h1>
<div class="info">
<p><strong>Сервер:</strong> {{ ansible_hostname }}</p>
<p><strong>ОС:</strong> {{ ansible_distribution }} \
{{ ansible_distribution_version }}</p>
<p><strong>Время:</strong> {{ ansible_date_time.iso8601 }}</p>
<p><strong>Роль:</strong> nginx (Сергей Антропов)</p>
</div>
</div>
</body>
</html>
dest: "{{ nginx_root_dir }}/{{ nginx_index_file }}"
owner: "{{ nginx_user }}"
group: "{{ nginx_user }}"
mode: '0644'
notify: restart nginx
tags:
- nginx
- config
- content
- name: Создание резервной копии конфигурации nginx
copy:
src: "{{ item }}"
dest: "{{ item }}.backup"
remote_src: true
mode: '0644'
owner: root
group: root
loop:
- /etc/nginx/nginx.conf
- /etc/nginx/sites-available/default
ignore_errors: true
when: ansible_os_family == "Debian"
tags:
- nginx
- config
- backup
- name: Создание резервной копии конфигурации nginx (RHEL)
copy:
src: "{{ item }}"
dest: "{{ item }}.backup"
remote_src: true
mode: '0644'
owner: root
group: root
loop:
- /etc/nginx/nginx.conf
- /etc/nginx/conf.d/default.conf
ignore_errors: true
when: ansible_os_family == "RedHat"
tags:
- nginx
- config
- backup
- name: Настройка основной конфигурации nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
backup: true
notify: restart nginx
tags:
- nginx
- config
- main
- name: Настройка виртуального хоста (Ubuntu/Debian)
template:
src: default.conf.j2
dest: /etc/nginx/sites-available/default
owner: root
group: root
mode: '0644'
backup: true
when: ansible_os_family == "Debian"
notify: restart nginx
tags:
- nginx
- config
- vhost
- debian
- name: Настройка виртуального хоста (RHEL/CentOS)
template:
src: default.conf.j2
dest: /etc/nginx/conf.d/default.conf
owner: root
group: root
mode: '0644'
backup: true
when: ansible_os_family == "RedHat"
notify: restart nginx
tags:
- nginx
- config
- vhost
- rhel
- name: Проверка конфигурации nginx
command: nginx -t
register: nginx_config_test
changed_when: false
tags:
- nginx
- config
- test
- name: Показать результат проверки конфигурации
debug:
msg: "{{ nginx_config_test.stdout_lines }}"
when: nginx_config_test.stdout_lines is defined
tags:
- nginx
- config
- test

View File

@@ -0,0 +1,67 @@
# Конфигурация виртуального хоста nginx
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# Сгенерировано: {{ ansible_date_time.iso8601 }}
server {
listen {{ nginx_listen_port }};
server_name {{ nginx_server_name }};
# Настройки безопасности
{% if nginx_hide_version %}
server_tokens off;
{% endif %}
# Корневая директория
root {{ nginx_root_dir }};
index {{ nginx_index_file }};
# Настройки логов для этого виртуального хоста
access_log {{ nginx_access_log }};
error_log {{ nginx_error_log }};
# Основная локация
location / {
try_files $uri $uri/ =404;
}
# Настройки для статических файлов
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Настройки безопасности
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Настройки для favicon
location = /favicon.ico {
log_not_found off;
access_log off;
}
# Настройки для robots.txt
location = /robots.txt {
log_not_found off;
access_log off;
}
# Настройки для health check
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# Настройки для статуса nginx
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}

View File

@@ -0,0 +1,58 @@
# Основная конфигурация nginx
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# Сгенерировано: {{ ansible_date_time.iso8601 }}
user {{ nginx_user }};
worker_processes {{ nginx_worker_processes }};
error_log {{ nginx_error_log }};
pid /run/nginx.pid;
events {
worker_connections {{ nginx_worker_connections }};
}
http {
# Основные настройки
sendfile {{ nginx_sendfile }};
tcp_nopush {{ nginx_tcp_nopush }};
tcp_nodelay {{ nginx_tcp_nodelay }};
keepalive_timeout {{ nginx_keepalive_timeout }};
types_hash_max_size 2048;
server_tokens {{ nginx_server_tokens }};
# Настройки MIME типов
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Настройки логирования
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log {{ nginx_access_log }} main;
# Настройки gzip
{% if nginx_gzip %}
gzip {{ nginx_gzip_vary }};
gzip_min_length {{ nginx_gzip_min_length }};
gzip_types
{% for gzip_type in nginx_gzip_types %}
{{ gzip_type }}{% if not loop.last %} {% endif %}
{% endfor %};
{% endif %}
# Настройки безопасности
{% if nginx_hide_version %}
server_tokens off;
{% endif %}
# Включение конфигураций виртуальных хостов
{% if ansible_os_family == "Debian" %}
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
{% elif ansible_os_family == "RedHat" %}
include /etc/nginx/conf.d/*.conf;
{% endif %}
}

52
scripts/test-playbook.yml Normal file
View File

@@ -0,0 +1,52 @@
---
# Простой тестовый playbook для проверки 3 контейнеров
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
- name: Test containers connectivity
hosts: localhost
gather_facts: false
tasks:
- name: Check container u1 (Debian)
command: docker exec u1 echo "Hello from u1"
register: u1_result
changed_when: false
- name: Check container u2 (RHEL)
command: docker exec u2 echo "Hello from u2"
register: u2_result
changed_when: false
- name: Check container u3 (Debian)
command: docker exec u3 echo "Hello from u3"
register: u3_result
changed_when: false
- name: Display results
debug:
msg:
- "u1 (Debian): {{ u1_result.stdout }}"
- "u2 (RHEL): {{ u2_result.stdout }}"
- "u3 (Debian): {{ u3_result.stdout }}"
- name: Install nginx on u1
command: docker exec u1 bash -c "apt-get update && apt-get install -y nginx"
register: nginx_u1
changed_when: false
- name: Install nginx on u2
command: docker exec u2 bash -c "yum install -y nginx"
register: nginx_u2
changed_when: false
- name: Install nginx on u3
command: docker exec u3 bash -c "apt-get update && apt-get install -y nginx"
register: nginx_u3
changed_when: false
- name: Display nginx installation results
debug:
msg:
- "Nginx installation on u1: {{ 'SUCCESS' if nginx_u1.rc == 0 else 'FAILED' }}"
- "Nginx installation on u2: {{ 'SUCCESS' if nginx_u2.rc == 0 else 'FAILED' }}"
- "Nginx installation on u3: {{ 'SUCCESS' if nginx_u3.rc == 0 else 'FAILED' }}"

83
scripts/test-standart.sh Executable file
View File

@@ -0,0 +1,83 @@
#!/bin/bash
# Скрипт для тестирования с preset standart
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
set -e
echo "🚀 Запуск тестирования с preset standart..."
# Очищаем старые контейнеры
echo "🧹 Очистка старых контейнеров..."
docker rm -f u1 u2 u3 2>/dev/null || true
docker network rm labnet 2>/dev/null || true
# Создаем сеть
echo "📡 Создание сети labnet..."
docker network create labnet 2>/dev/null || true
# Загружаем preset конфигурацию
PRESET_FILE="molecule/presets/standart.yml"
if [ ! -f "$PRESET_FILE" ]; then
echo "❌ Ошибка: Пресет файл $PRESET_FILE не найден!"
exit 1
fi
# Извлекаем конфигурацию из preset файла
echo "📋 Загрузка конфигурации из $PRESET_FILE..."
# Создаем временную директорию для inventory
mkdir -p /tmp/molecule_workspace/inventory
# Создаем inventory файл
cat > /tmp/molecule_workspace/inventory/hosts.ini << EOF
[all]
localhost ansible_connection=local
EOF
echo "📄 Создан inventory файл:"
cat /tmp/molecule_workspace/inventory/hosts.ini
# Запускаем контейнеры
echo "🐳 Создание контейнеров..."
# u1 - Debian
echo "Создание u1 (Debian)..."
docker run -d --name u1 \
--network labnet \
-p 2201:22 \
ubuntu:20.04 \
bash -c "apt-get update && apt-get install -y openssh-server && service ssh start && sleep infinity"
# u2 - Debian (временно используем Ubuntu вместо CentOS)
echo "Создание u2 (Debian)..."
docker run -d --name u2 \
--network labnet \
-p 2202:22 \
ubuntu:20.04 \
bash -c "apt-get update && apt-get install -y openssh-server && service ssh start && sleep infinity"
# u3 - Debian
echo "Создание u3 (Debian)..."
docker run -d --name u3 \
--network labnet \
-p 2203:22 \
ubuntu:20.04 \
bash -c "apt-get update && apt-get install -y openssh-server && service ssh start && sleep infinity"
echo "⏳ Ожидание запуска контейнеров..."
sleep 10
# Проверяем статус контейнеров
echo "📊 Статус контейнеров:"
docker ps --filter "name=u[123]" --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
# Запускаем тесты
echo "🧪 Запуск тестов..."
ansible-playbook -i /tmp/molecule_workspace/inventory/hosts.ini scripts/test-playbook.yml
echo "🧹 Очистка контейнеров..."
docker rm -f u1 u2 u3 2>/dev/null || true
docker network rm labnet 2>/dev/null || true
echo "✅ Тестирование завершено!"

View File

View File

@@ -1 +0,0 @@
password123

33
vault/secrets.yml Normal file
View File

@@ -0,0 +1,33 @@
---
# Основные секреты для тестирования
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
# Пароли для баз данных
database_passwords:
root_password: "database-root-password"
app_user_password: "database-app-password"
monitoring_user_password: "monitoring-user-password"
# SSL сертификаты
ssl_certificates:
server_cert: |
-----BEGIN CERTIFICATE-----
# Server certificate content
-----END CERTIFICATE-----
server_key: |
-----BEGIN PRIVATE KEY-----
# Server private key content
-----END PRIVATE KEY-----
# API ключи
api_keys:
github_token: "ghp_example_token"
dockerhub_token: "dckr_example_token"
monitoring_api_key: "monitoring_api_key_example"
# Строки подключения
database_connections:
primary: "mysql://user:password@db1:3306/app"
replica: "mysql://user:password@db2:3306/app"
cache: "redis://cache1:6379/0"