feat: Добавлена система пресетов для Molecule
- Создана система пресетов для быстрого переключения между конфигурациями - Добавлены пресеты: minimal, standard, docker, cluster - Обновлена структура проекта с папками cicd/, vault/, scripts/ - Упрощена система vault с функциональными секретами - Добавлены скрипты для работы с пресетами - Обновлен Makefile с командами для пресетов - Удалены старые файлы и структуры Автор: Сергей Антропов Сайт: https://devops.org.ru
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,6 +1,10 @@
|
|||||||
# ---> Ansible
|
# ---> Ansible
|
||||||
*.retry
|
*.retry
|
||||||
|
|
||||||
|
# ---> Vault (секретные файлы)
|
||||||
|
vault/.vault
|
||||||
|
vault/secrets/*.yml
|
||||||
|
|
||||||
# ---> Python
|
# ---> Python
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
|||||||
@@ -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 "Работа пайплайна завершена"
|
|
||||||
|
|
||||||
40
Dockerfile
40
Dockerfile
@@ -1,40 +0,0 @@
|
|||||||
# Используем готовый образ с Ansible
|
|
||||||
FROM geerlingguy/docker-ubuntu2204-ansible:latest
|
|
||||||
|
|
||||||
# Добавляем метаданные
|
|
||||||
LABEL maintainer="Сергей Антропов <sergey@antropoff.ru>"
|
|
||||||
LABEL description="Этот Dockerfile создан для внедрения подхода IaC в Ansible."
|
|
||||||
LABEL version="0.1"
|
|
||||||
LABEL contact.website="https://devops.org.ru"
|
|
||||||
|
|
||||||
# Устанавливаем переменные окружения
|
|
||||||
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
|
|
||||||
|
|
||||||
# Команда по умолчанию
|
|
||||||
CMD ["/bin/bash"]
|
|
||||||
@@ -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"]
|
|
||||||
@@ -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"]
|
|
||||||
262
Makefile
262
Makefile
@@ -1,135 +1,130 @@
|
|||||||
# Глобальные переменные
|
# AnsibleTemplate - Универсальная система тестирования Ansible ролей
|
||||||
IMAGE ?= ansible
|
# Автор: Сергей Антропов
|
||||||
TAG ?= 0.1
|
# Сайт: https://devops.org.ru
|
||||||
REGISTRY ?= inecs/ansible
|
|
||||||
# По умолчанию используем docker. Для локальной разработки используйте docker-compose
|
|
||||||
RUN_MODE ?= docker
|
|
||||||
|
|
||||||
# Определение команды RUN в зависимости от RUN_MODE
|
.PHONY: molecule vault git help
|
||||||
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
|
|
||||||
|
|
||||||
view create edit show delete test lint deploy new init build rebuild prune release images push pull shell:
|
|
||||||
@true
|
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Инициализация новой роли
|
# Работа с пресетами
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
init:
|
# Пресеты
|
||||||
@echo "Шаг 1: Создание Docker-образа..."
|
preset-list:
|
||||||
@make docker build
|
@./scripts/list-presets.sh
|
||||||
@echo "Шаг 2: Создание Docker-образов для запуска Molecule..."
|
|
||||||
@make docker images
|
preset-use:
|
||||||
@echo "Шаг 3: Создание нового vault-файла с паролем..."
|
@./scripts/use-preset.sh $(word 2, $(MAKECMDGOALS))
|
||||||
@read -p "Введите пароль для vault: " VAULT_PASSWORD; \
|
|
||||||
echo "$$VAULT_PASSWORD" > vault-password.txt; \
|
# Псевдонимы для пресетов
|
||||||
make vault create
|
preset-minimal:
|
||||||
@echo "Шаг 4: Создание нового брэнча в гите..."
|
@./scripts/use-preset.sh minimal
|
||||||
@make git new
|
|
||||||
@echo "Шаг 5: Создание новой роли..."
|
preset-standard:
|
||||||
@make role new
|
@./scripts/use-preset.sh standard
|
||||||
|
|
||||||
|
preset-docker:
|
||||||
|
@./scripts/use-preset.sh docker
|
||||||
|
|
||||||
|
preset-cluster:
|
||||||
|
@./scripts/use-preset.sh cluster
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Управление контейнерами с помощью docker compose или docker run
|
# Работа с Molecule Universal
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
docker:
|
molecule:
|
||||||
@case "$(word 2, $(MAKECMDGOALS))" in \
|
@case "$(word 2, $(MAKECMDGOALS))" in \
|
||||||
build) \
|
create) \
|
||||||
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; \
|
clear; \
|
||||||
echo "Entering to Ansible container shell..."; \
|
echo "Создание тестового окружения..."; \
|
||||||
$(RUN) bash ;; \
|
cd molecule/universal && molecule create -s universal;; \
|
||||||
release) \
|
converge) \
|
||||||
docker buildx create --use --name multiarch-builder --driver docker-container; \
|
clear; \
|
||||||
docker login $(REGISTRY); \
|
echo "Запуск плейбуков..."; \
|
||||||
docker buildx build -t $(REGISTRY)/$(IMAGE):$(TAG) -t $(REGISTRY)/$(IMAGE):latest --platform linux/amd64,linux/arm64 --push .;; \
|
cd molecule/universal && molecule converge -s universal;; \
|
||||||
images) \
|
verify) \
|
||||||
docker buildx create --use --name multiarch-builder --driver docker-container; \
|
clear; \
|
||||||
echo "Логинимся в Docker Hub..."; \
|
echo "Проверка результатов..."; \
|
||||||
docker login; \
|
cd molecule/universal && molecule verify -s universal;; \
|
||||||
echo "Собираем и пушим основной Ansible образ..."; \
|
destroy) \
|
||||||
docker buildx build -t $(REGISTRY)/$(IMAGE):$(TAG) -t $(REGISTRY)/$(IMAGE):latest --platform linux/amd64,linux/arm64 --push .; \
|
clear; \
|
||||||
echo "Собираем и пушим образ CentOS..."; \
|
echo "Удаление тестового окружения..."; \
|
||||||
docker buildx build -t $(REGISTRY):centos --platform linux/amd64,linux/arm64 --push -f Dockerfile-CentOS .; \
|
cd molecule/universal && molecule destroy -s universal;; \
|
||||||
echo "Собираем и пушим образ Ubuntu..."; \
|
test) \
|
||||||
docker buildx build -t $(REGISTRY):ubuntu --platform linux/amd64,linux/arm64 --push -f Dockerfile-Ubuntu .; \
|
clear; \
|
||||||
echo "Образы успешно опубликованы в Docker Hub: $(REGISTRY)";; \
|
echo "Полный цикл тестирования..."; \
|
||||||
*) echo "Unknown action. Available actions: build, rebuild, prune, release";; \
|
cd molecule/universal && molecule test -s universal;; \
|
||||||
|
*) \
|
||||||
|
clear; \
|
||||||
|
echo "Доступные команды:"; \
|
||||||
|
echo " make molecule create - создать окружение"; \
|
||||||
|
echo " make molecule converge - запустить плейбуки"; \
|
||||||
|
echo " make molecule verify - проверить результаты"; \
|
||||||
|
echo " make molecule destroy - удалить окружение"; \
|
||||||
|
echo " make molecule test - полный цикл тестирования"; \
|
||||||
|
;; \
|
||||||
esac
|
esac
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Работа с ролью
|
# Работа с Ansible Vault
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
vault:
|
vault:
|
||||||
@case "$(word 2, $(MAKECMDGOALS))" in \
|
@case "$(word 2, $(MAKECMDGOALS))" in \
|
||||||
show) $(RUN) bash -c "ansible-vault view --vault-password-file vault-password.txt vars/secrets.yml";; \
|
show) \
|
||||||
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
|
|
||||||
|
|
||||||
role:
|
|
||||||
@case "$(word 2, $(MAKECMDGOALS))" in \
|
|
||||||
new) \
|
|
||||||
clear; \
|
clear; \
|
||||||
echo "Введите название новой роли на английском:"; \
|
echo "Доступные файлы секретов:"; \
|
||||||
read ROLE_NAME; \
|
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
|
||||||
echo "Введите описание роли:"; \
|
echo ""; \
|
||||||
read ROLE_DESC; \
|
read -p "Введите имя файла (без .yml): " FILE; \
|
||||||
cp -r default/ "roles/$${ROLE_NAME}"; \
|
ansible-vault view --vault-password-file vault/.vault vault/$$FILE.yml;; \
|
||||||
printf "\n- name: $${ROLE_DESC}" >> roles/deploy.yaml; \
|
create) \
|
||||||
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; \
|
clear; \
|
||||||
echo "Check your role..."; \
|
echo "Создание файла секретов:"; \
|
||||||
$(RUN) bash -c "ansible-vault decrypt --vault-password-file vault-password.txt vars/secrets.yml"; \
|
read -p "Введите имя файла (без .yml): " FILE; \
|
||||||
$(RUN) bash -c "ansible-lint roles/*"; \
|
ansible-vault create --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \
|
||||||
$(RUN) bash -c "ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file vault-password.txt";; \
|
edit) \
|
||||||
test) \
|
|
||||||
clear; \
|
clear; \
|
||||||
echo "Running test roles..."; \
|
echo "Доступные файлы секретов:"; \
|
||||||
$(RUN) bash -c "ansible-vault decrypt --vault-password-file vault-password.txt vars/secrets.yml"; \
|
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
|
||||||
$(RUN) bash -c "docker login $(REGISTRY) && molecule test --parallel --destroy=always"; \
|
echo ""; \
|
||||||
$(RUN) bash -c "ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file vault-password.txt";; \
|
read -p "Введите имя файла (без .yml): " FILE; \
|
||||||
deploy) \
|
ansible-vault edit --vault-password-file vault/.vault vault/$$FILE.yml;; \
|
||||||
|
delete) \
|
||||||
clear; \
|
clear; \
|
||||||
echo "Deploying roles to production..."; \
|
echo "Доступные файлы секретов:"; \
|
||||||
$(RUN) bash -c "ansible-playbook roles/deploy.yaml";; \
|
ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \
|
||||||
*) echo "Unknown action";; \
|
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; \
|
||||||
|
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; \
|
||||||
|
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; \
|
||||||
|
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
|
esac
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
@@ -153,5 +148,44 @@ git:
|
|||||||
NEW_BRANCH="$$BRANCH_NAME"; \
|
NEW_BRANCH="$$BRANCH_NAME"; \
|
||||||
git checkout -b $$NEW_BRANCH; \
|
git checkout -b $$NEW_BRANCH; \
|
||||||
echo "Создана и переключена на новую ветку: $$NEW_BRANCH";; \
|
echo "Создана и переключена на новую ветку: $$NEW_BRANCH";; \
|
||||||
*) echo "Unknown action. Available actions: push, pull, cluster-branch";; \
|
*) \
|
||||||
|
clear; \
|
||||||
|
echo "Доступные команды:"; \
|
||||||
|
echo " make git push - запушить изменения"; \
|
||||||
|
echo " make git pull - получить изменения"; \
|
||||||
|
echo " make git new - создать новую ветку";; \
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
####################################################################################################
|
||||||
|
# Справка
|
||||||
|
####################################################################################################
|
||||||
|
help:
|
||||||
|
@clear
|
||||||
|
@echo "=========================================="
|
||||||
|
@echo "AnsibleTemplate - Универсальная система"
|
||||||
|
@echo "тестирования Ansible ролей"
|
||||||
|
@echo "=========================================="
|
||||||
|
@echo ""
|
||||||
|
@echo "📁 Структура проекта:"
|
||||||
|
@echo " scripts/ - Скрипты автоматизации"
|
||||||
|
@echo " inventory/ - Инвентори файлы"
|
||||||
|
@echo " molecule/universal/ - Molecule конфигурация"
|
||||||
|
@echo " roles/ - Ansible роли"
|
||||||
|
@echo " vars/ - Переменные"
|
||||||
|
@echo ""
|
||||||
|
@echo "🚀 Основные команды:"
|
||||||
|
@echo " make molecule create - создать тестовое окружение"
|
||||||
|
@echo " make molecule test - полный цикл тестирования"
|
||||||
|
@echo " make molecule generateinventory - сгенерировать инвентори"
|
||||||
|
@echo " make vault create - создать файл секретов"
|
||||||
|
@echo " make git new - создать новую ветку"
|
||||||
|
@echo ""
|
||||||
|
@echo "📖 Для подробной справки:"
|
||||||
|
@echo " make molecule - команды Molecule"
|
||||||
|
@echo " make vault - команды Vault"
|
||||||
|
@echo " make git - команды Git"
|
||||||
|
@echo "=========================================="
|
||||||
|
|
||||||
|
# Пустые цели для совместимости
|
||||||
|
view create edit show delete test lint deploy new advanced:
|
||||||
|
@true
|
||||||
62
README.md
62
README.md
@@ -1,62 +0,0 @@
|
|||||||
# AnsibleTemplate
|
|
||||||
|
|
||||||
Темплейт для создания, проверки и тестирование ролей Ansible с помощью контейнеров Docker.
|
|
||||||
|
|
||||||
### С чего начать?
|
|
||||||
|
|
||||||
На вашей машине вам необходимо сбилдить образ, где будут запускаться все роли через docker-compose.
|
|
||||||
|
|
||||||
Это можно сделать самостоятельно:
|
|
||||||
|
|
||||||
- **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)
|
|
||||||
|
|
||||||
Или ввести команду:
|
|
||||||
|
|
||||||
- **make init** - которая создаст файл секретов с паролем. Сбилдит образ. И создаст новую роль.
|
|
||||||
|
|
||||||
### Работа с ролью
|
|
||||||
- **make role new** - создать новую роль из шаблона. Название роли пишется на английском, описание роли на любом языке
|
|
||||||
- **make role lint** - проверяет все роли в папке roles/* на наличие ошибок
|
|
||||||
- **make role test** - позволяет тестировать роль, указанную в molecule/default/converge.yml
|
|
||||||
сразу на двух контейнерах (RedHat и Ubuntu)
|
|
||||||
- **make role deploy** - запускает роль в продакшен. Все хосты берет из файла inventory/hosts
|
|
||||||
|
|
||||||
### Работа с файлом переменных
|
|
||||||
|
|
||||||
Все переменные защищены через **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 для нормального тестирования ролей.
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[defaults]
|
[defaults]
|
||||||
inventory = inventory/hosts
|
inventory = inventory/hosts.ini
|
||||||
vault_password_file = vault-password.txt
|
vault_password_file = vault/.vault
|
||||||
remote_user = devops
|
remote_user = devops
|
||||||
host_key_checking = False
|
host_key_checking = False
|
||||||
enable_plugins = yaml, ini
|
enable_plugins = yaml, ini
|
||||||
|
|||||||
51
cicd/.gitlab-ci.yml
Normal file
51
cicd/.gitlab-ci.yml
Normal 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
|
||||||
53
cicd/azure-devops/azure-pipelines.yml
Normal file
53
cicd/azure-devops/azure-pipelines.yml
Normal 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
70
cicd/github/workflows.yml
Normal 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
59
cicd/jenkins/Jenkinsfile
vendored
Normal 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!'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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:
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Пример таски
|
|
||||||
debug:
|
|
||||||
msg: "Привет! Я запустился на Debian/Ubuntu!"
|
|
||||||
@@ -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"
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Пример таски
|
|
||||||
debug:
|
|
||||||
msg: "Привет! Я запустился на RedHat/CentOS/Fedora!"
|
|
||||||
@@ -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
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
[all]
|
|
||||||
29
inventory/hosts.ini
Normal file
29
inventory/hosts.ini
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Автоматически сгенерированный инвентори
|
||||||
|
# Автор: Сергей Антропов
|
||||||
|
# Сайт: https://devops.org.ru
|
||||||
|
|
||||||
|
[all:vars]
|
||||||
|
ansible_connection=community.docker.docker
|
||||||
|
ansible_python_interpreter=/usr/bin/python3
|
||||||
|
|
||||||
|
[all]
|
||||||
|
controller
|
||||||
|
|
||||||
|
[docker]
|
||||||
|
docker1
|
||||||
|
|
||||||
|
[dood]
|
||||||
|
dood1
|
||||||
|
|
||||||
|
[test]
|
||||||
|
test1
|
||||||
|
test2
|
||||||
|
test3
|
||||||
|
|
||||||
|
[all]
|
||||||
|
controller
|
||||||
|
test1
|
||||||
|
test2
|
||||||
|
test3
|
||||||
|
docker1
|
||||||
|
dood1
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Converge
|
|
||||||
hosts: all
|
|
||||||
vars_files:
|
|
||||||
- ../../vars/secrets.yml
|
|
||||||
roles:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
- name: Destroy containers on interrupt
|
|
||||||
hosts: localhost
|
|
||||||
tasks:
|
|
||||||
- name: Ensure containers are destroyed
|
|
||||||
docker_container:
|
|
||||||
name: "{{ item.name }}"
|
|
||||||
state: absent
|
|
||||||
loop: "{{ molecule_yml.platforms }}"
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
---
|
|
||||||
dependency:
|
|
||||||
name: galaxy
|
|
||||||
enabled: false
|
|
||||||
options:
|
|
||||||
requirements-file: requirements.yml
|
|
||||||
|
|
||||||
driver:
|
|
||||||
name: docker
|
|
||||||
|
|
||||||
platforms:
|
|
||||||
- name: centos
|
|
||||||
image: "inecs/ansible:centos"
|
|
||||||
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
|
|
||||||
- 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
|
|
||||||
env:
|
|
||||||
ANSIBLE_PYTHON_INTERPRETER: /usr/bin/python3
|
|
||||||
lint:
|
|
||||||
name: ansible-lint
|
|
||||||
|
|
||||||
verifier:
|
|
||||||
name: ansible
|
|
||||||
|
|
||||||
scenario:
|
|
||||||
name: default
|
|
||||||
test_sequence:
|
|
||||||
- dependency
|
|
||||||
- cleanup
|
|
||||||
- destroy
|
|
||||||
- syntax
|
|
||||||
- create
|
|
||||||
- prepare
|
|
||||||
- converge
|
|
||||||
- idempotence
|
|
||||||
- side_effect
|
|
||||||
- verify
|
|
||||||
- cleanup
|
|
||||||
- destroy
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Prepare
|
|
||||||
hosts: all
|
|
||||||
tasks:
|
|
||||||
- name: Reun verify
|
|
||||||
debug:
|
|
||||||
msg: "Hello, Verify!"
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
---
|
|
||||||
# Проверка работы systemd, docker и docker-compose в образах
|
|
||||||
# Автор: Сергей Антропов
|
|
||||||
# Сайт: https://devops.org.ru
|
|
||||||
|
|
||||||
- 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: Check if systemd is available and running
|
|
||||||
systemd:
|
|
||||||
name: systemd
|
|
||||||
state: started
|
|
||||||
register: systemd_status
|
|
||||||
failed_when: false
|
|
||||||
|
|
||||||
- name: Display systemd status
|
|
||||||
debug:
|
|
||||||
msg: "Systemd статус: {{ 'Доступен и запущен' if systemd_status is succeeded else 'Недоступен или не запущен' }}"
|
|
||||||
|
|
||||||
- name: Check systemd version
|
|
||||||
command: systemd --version
|
|
||||||
register: systemd_version
|
|
||||||
failed_when: false
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Display systemd version
|
|
||||||
debug:
|
|
||||||
msg: "Версия systemd: {{ systemd_version.stdout_lines[0] if systemd_version.stdout_lines else 'Не определена' }}"
|
|
||||||
|
|
||||||
- name: Check if docker service exists
|
|
||||||
stat:
|
|
||||||
path: /usr/bin/docker
|
|
||||||
register: docker_binary
|
|
||||||
|
|
||||||
- name: Check if docker service exists (alternative path)
|
|
||||||
stat:
|
|
||||||
path: /usr/local/bin/docker
|
|
||||||
register: docker_binary_alt
|
|
||||||
|
|
||||||
- name: Display docker binary 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 'Не найден') }}"
|
|
||||||
|
|
||||||
- name: Check docker version
|
|
||||||
command: docker --version
|
|
||||||
register: docker_version
|
|
||||||
failed_when: false
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Display docker version
|
|
||||||
debug:
|
|
||||||
msg: "Версия Docker: {{ docker_version.stdout if docker_version.stdout else 'Docker не установлен' }}"
|
|
||||||
|
|
||||||
- name: Check if docker daemon is running
|
|
||||||
command: docker info
|
|
||||||
register: docker_info
|
|
||||||
failed_when: false
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Display docker daemon status
|
|
||||||
debug:
|
|
||||||
msg: "Docker daemon: {{ 'Запущен' if docker_info is succeeded else 'Не запущен или недоступен' }}"
|
|
||||||
|
|
||||||
- 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
|
|
||||||
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 '✗ Недоступен' }}
|
|
||||||
========================================
|
|
||||||
99
molecule/presets/README.md
Normal file
99
molecule/presets/README.md
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# Пресеты для Molecule
|
||||||
|
|
||||||
|
## Описание
|
||||||
|
|
||||||
|
Пресеты - это готовые конфигурации для быстрого развертывания тестовых окружений. Каждый пресет содержит определенный набор хостов и настроек.
|
||||||
|
|
||||||
|
## Доступные пресеты
|
||||||
|
|
||||||
|
### `minimal.yml`
|
||||||
|
- **Описание**: Минимальный набор для быстрого тестирования
|
||||||
|
- **Хосты**: 1 хост (Debian)
|
||||||
|
- **Использование**: Для простых тестов и отладки
|
||||||
|
|
||||||
|
### `standard.yml`
|
||||||
|
- **Описание**: Стандартный набор для тестирования
|
||||||
|
- **Хосты**: 3 хоста (Debian + RHEL)
|
||||||
|
- **Использование**: Для большинства тестов
|
||||||
|
|
||||||
|
### `docker.yml`
|
||||||
|
- **Описание**: Пресет с Docker контейнерами
|
||||||
|
- **Хосты**: 2 systemd + 1 DinD + 1 DOoD
|
||||||
|
- **Использование**: Для тестирования Docker-приложений
|
||||||
|
|
||||||
|
### `cluster.yml`
|
||||||
|
- **Описание**: Пресет для кластерного тестирования
|
||||||
|
- **Хосты**: 8 хостов (web, app, database, loadbalancer, monitoring)
|
||||||
|
- **Использование**: Для тестирования сложных архитектур
|
||||||
|
|
||||||
|
## Использование
|
||||||
|
|
||||||
|
### Через Makefile
|
||||||
|
```bash
|
||||||
|
# Показать все пресеты
|
||||||
|
make preset list
|
||||||
|
|
||||||
|
# Переключиться на пресет
|
||||||
|
make preset use minimal
|
||||||
|
make preset use standard
|
||||||
|
make preset use docker
|
||||||
|
make preset use cluster
|
||||||
|
```
|
||||||
|
|
||||||
|
### Через скрипт
|
||||||
|
```bash
|
||||||
|
# Показать все пресеты
|
||||||
|
./scripts/use-preset.sh
|
||||||
|
|
||||||
|
# Переключиться на пресет
|
||||||
|
./scripts/use-preset.sh minimal
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ручное переключение
|
||||||
|
```bash
|
||||||
|
# Скопировать пресет в hosts.yml
|
||||||
|
cp molecule/presets/minimal.yml molecule/universal/hosts.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Создание собственного пресета
|
||||||
|
|
||||||
|
1. Скопируйте существующий пресет:
|
||||||
|
```bash
|
||||||
|
cp molecule/presets/standard.yml molecule/presets/my-preset.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Отредактируйте файл под свои нужды
|
||||||
|
|
||||||
|
3. Используйте новый пресет:
|
||||||
|
```bash
|
||||||
|
make preset use my-preset
|
||||||
|
```
|
||||||
|
|
||||||
|
## Структура пресета
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
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"
|
||||||
|
|
||||||
|
systemd_defaults:
|
||||||
|
privileged: true
|
||||||
|
command: "/sbin/init"
|
||||||
|
volumes:
|
||||||
|
- "/sys/fs/cgroup:/sys/fs/cgroup:ro"
|
||||||
|
tmpfs: ["/run", "/run/lock"]
|
||||||
|
capabilities: ["SYS_ADMIN"]
|
||||||
|
|
||||||
|
hosts:
|
||||||
|
- name: host1
|
||||||
|
family: debian
|
||||||
|
groups: [test]
|
||||||
|
- name: docker1
|
||||||
|
type: dind
|
||||||
|
groups: [docker]
|
||||||
|
publish: ["8080:8080"]
|
||||||
|
```
|
||||||
57
molecule/presets/cluster.yml
Normal file
57
molecule/presets/cluster.yml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
# Пресет для кластерного тестирования
|
||||||
|
# Автор: Сергей Антропов
|
||||||
|
# Сайт: 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:
|
||||||
|
# Web серверы
|
||||||
|
- name: web1
|
||||||
|
family: debian
|
||||||
|
groups: [web]
|
||||||
|
- name: web2
|
||||||
|
family: rhel
|
||||||
|
groups: [web]
|
||||||
|
|
||||||
|
# App серверы
|
||||||
|
- name: app1
|
||||||
|
family: debian
|
||||||
|
groups: [app]
|
||||||
|
- name: app2
|
||||||
|
family: rhel
|
||||||
|
groups: [app]
|
||||||
|
|
||||||
|
# Database серверы
|
||||||
|
- name: db1
|
||||||
|
family: debian
|
||||||
|
groups: [database]
|
||||||
|
- name: db2
|
||||||
|
family: rhel
|
||||||
|
groups: [database]
|
||||||
|
|
||||||
|
# Load Balancer
|
||||||
|
- name: lb1
|
||||||
|
family: rhel
|
||||||
|
groups: [loadbalancer]
|
||||||
|
publish: ["80:80", "443:443"]
|
||||||
|
|
||||||
|
# Мониторинг
|
||||||
|
- name: monitor1
|
||||||
|
family: debian
|
||||||
|
groups: [monitoring]
|
||||||
|
publish: ["3000:3000", "9090:9090"]
|
||||||
44
molecule/presets/docker.yml
Normal file
44
molecule/presets/docker.yml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
# Пресет с 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
|
||||||
25
molecule/presets/minimal.yml
Normal file
25
molecule/presets/minimal.yml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
# Минимальный пресет для быстрого тестирования
|
||||||
|
# Автор: Сергей Антропов
|
||||||
|
# Сайт: 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]
|
||||||
32
molecule/presets/standard.yml
Normal file
32
molecule/presets/standard.yml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
# Стандартный пресет для тестирования
|
||||||
|
# Автор: Сергей Антропов
|
||||||
|
# Сайт: 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]
|
||||||
52
molecule/universal/converge.yml
Normal file
52
molecule/universal/converge.yml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
gather_facts: false
|
||||||
|
vars:
|
||||||
|
# перечисли файлы/глобы, которые нужно временно расшифровать
|
||||||
|
vault_targets:
|
||||||
|
- /ansible/vault/secrets.yml
|
||||||
|
# добавляй сюда свои пути (host_vars/*/vault.yml, group_vars/*/vault.yml, и т.п.)
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Install required collections (use repo's requirements.yml)
|
||||||
|
community.docker.docker_container_exec:
|
||||||
|
container: ansible
|
||||||
|
command: bash -lc "ansible-galaxy collection install -r /ansible/requirements.yml || true"
|
||||||
|
|
||||||
|
- name: Decrypt vault targets (best-effort)
|
||||||
|
community.docker.docker_container_exec:
|
||||||
|
container: ansible
|
||||||
|
command: >
|
||||||
|
bash -lc '
|
||||||
|
set -euo pipefail;
|
||||||
|
for p in {{ vault_targets | map('quote') | join(' ') }}; do
|
||||||
|
if [ -e "$p" ]; then
|
||||||
|
echo "[vault] decrypt $p";
|
||||||
|
ansible-vault decrypt --vault-password-file /ansible/vault-password.txt "$p" || true;
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
'
|
||||||
|
|
||||||
|
- name: Run external playbook (your lab play)
|
||||||
|
community.docker.docker_container_exec:
|
||||||
|
container: ansible
|
||||||
|
command: >
|
||||||
|
bash -lc "
|
||||||
|
ANSIBLE_ROLES_PATH=/ansible/roles
|
||||||
|
ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /ansible/molecule/universal/site.yml
|
||||||
|
"
|
||||||
|
|
||||||
|
- name: Re-encrypt vault targets (always)
|
||||||
|
community.docker.docker_container_exec:
|
||||||
|
container: ansible
|
||||||
|
command: >
|
||||||
|
bash -lc '
|
||||||
|
set -euo pipefail;
|
||||||
|
for p in {{ vault_targets | map('quote') | join(' ') }}; do
|
||||||
|
if [ -e "$p" ]; then
|
||||||
|
echo "[vault] encrypt $p";
|
||||||
|
ansible-vault encrypt --encrypt-vault-id default --vault-password-file /ansible/vault-password.txt "$p" || true;
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
'
|
||||||
|
ignore_errors: true
|
||||||
107
molecule/universal/create.yml
Normal file
107
molecule/universal/create.yml
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
gather_facts: false
|
||||||
|
vars_files:
|
||||||
|
- hosts.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Ensure network exists
|
||||||
|
community.docker.docker_network:
|
||||||
|
name: "{{ docker_network }}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
# SYSTEMD nodes
|
||||||
|
- name: Pull systemd images
|
||||||
|
community.docker.docker_image:
|
||||||
|
name: "{{ images[item.family] }}"
|
||||||
|
source: pull
|
||||||
|
loop: "{{ hosts | selectattr('type','undefined') | list }}"
|
||||||
|
loop_control: { label: "{{ item.name }}" }
|
||||||
|
|
||||||
|
- name: Start systemd nodes
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
image: "{{ images[item.family] }}"
|
||||||
|
networks: [ { name: "{{ docker_network }}" } ]
|
||||||
|
privileged: "{{ systemd_defaults.privileged }}"
|
||||||
|
command: "{{ systemd_defaults.command }}"
|
||||||
|
volumes: "{{ (systemd_defaults.volumes | default([])) + (item.volumes | default([])) }}"
|
||||||
|
tmpfs: "{{ (systemd_defaults.tmpfs | default([])) + (item.tmpfs | default([])) }}"
|
||||||
|
capabilities: "{{ (systemd_defaults.capabilities | default([])) + (item.capabilities | default([])) }}"
|
||||||
|
published_ports: "{{ item.publish | default([]) }}"
|
||||||
|
env: "{{ item.env | default({}) }}"
|
||||||
|
state: started
|
||||||
|
restart_policy: unless-stopped
|
||||||
|
loop: "{{ hosts | selectattr('type','undefined') | list }}"
|
||||||
|
loop_control: { label: "{{ item.name }}" }
|
||||||
|
|
||||||
|
# DinD nodes
|
||||||
|
- name: Start DinD nodes (docker:27-dind)
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
image: "docker:27-dind"
|
||||||
|
privileged: true
|
||||||
|
environment: { DOCKER_TLS_CERTDIR: "" }
|
||||||
|
networks: [ { name: "{{ docker_network }}" } ]
|
||||||
|
published_ports: "{{ item.publish | default([]) }}"
|
||||||
|
volumes: [ "{{ item.name }}-docker:/var/lib/docker" ]
|
||||||
|
state: started
|
||||||
|
restart_policy: unless-stopped
|
||||||
|
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}"
|
||||||
|
loop_control: { label: "{{ item.name }}" }
|
||||||
|
|
||||||
|
# DOoD nodes (mount docker.sock)
|
||||||
|
- name: Start DOoD nodes (systemd + docker.sock mount)
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
image: "{{ images[item.family] }}"
|
||||||
|
networks: [ { name: "{{ docker_network }}" } ]
|
||||||
|
privileged: "{{ systemd_defaults.privileged }}"
|
||||||
|
command: "{{ systemd_defaults.command }}"
|
||||||
|
volumes: "{{ (systemd_defaults.volumes | default([])) + ['/var/run/docker.sock:/var/run/docker.sock'] + (item.volumes | default([])) }}"
|
||||||
|
tmpfs: "{{ (systemd_defaults.tmpfs | default([])) + (item.tmpfs | default([])) }}"
|
||||||
|
capabilities: "{{ (systemd_defaults.capabilities | default([])) + (item.capabilities | default([])) }}"
|
||||||
|
published_ports: "{{ item.publish | default([]) }}"
|
||||||
|
env: "{{ item.env | default({}) }}"
|
||||||
|
state: started
|
||||||
|
restart_policy: unless-stopped
|
||||||
|
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list }}"
|
||||||
|
loop_control: { label: "{{ item.name }}" }
|
||||||
|
|
||||||
|
# Build groups map
|
||||||
|
- name: Build groups map {group: [hosts]}
|
||||||
|
set_fact:
|
||||||
|
groups_map: "{{ groups_map | default({}) }}"
|
||||||
|
- name: Append hosts to groups
|
||||||
|
set_fact:
|
||||||
|
groups_map: "{{ groups_map | combine({ item_group: (groups_map[item_group] | default([])) + [item_name] }) }}"
|
||||||
|
loop: "{{ hosts | subelements('groups', skip_missing=True) }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.0.name }}"
|
||||||
|
vars:
|
||||||
|
item_name: "{{ item.0.name }}"
|
||||||
|
item_group: "{{ item.1 }}"
|
||||||
|
|
||||||
|
# Render inventory
|
||||||
|
- name: Render inventory ini
|
||||||
|
set_fact:
|
||||||
|
inv_content: |
|
||||||
|
[all:vars]
|
||||||
|
ansible_connection=community.docker.docker
|
||||||
|
ansible_python_interpreter=/usr/bin/python3
|
||||||
|
|
||||||
|
{% for group, members in (groups_map | dictsort) %}
|
||||||
|
[{{ group }}]
|
||||||
|
{% for h in members %}{{ h }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
[all]
|
||||||
|
{% for h in hosts %}{{ h.name }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
- name: Write inventory file
|
||||||
|
copy:
|
||||||
|
dest: "{{ generated_inventory }}"
|
||||||
|
content: "{{ inv_content }}"
|
||||||
|
mode: "0644"
|
||||||
29
molecule/universal/destroy.yml
Normal file
29
molecule/universal/destroy.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
gather_facts: false
|
||||||
|
vars_files:
|
||||||
|
- hosts.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Remove containers
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
state: absent
|
||||||
|
force_kill: true
|
||||||
|
loop: "{{ hosts }}"
|
||||||
|
loop_control: { label: "{{ item.name }}" }
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Remove DinD volumes
|
||||||
|
community.docker.docker_volume:
|
||||||
|
name: "{{ item.name }}-docker"
|
||||||
|
state: absent
|
||||||
|
loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}"
|
||||||
|
loop_control: { label: "{{ item.name }}" }
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Remove network
|
||||||
|
community.docker.docker_network:
|
||||||
|
name: "{{ docker_network }}"
|
||||||
|
state: absent
|
||||||
|
ignore_errors: true
|
||||||
44
molecule/universal/hosts.yml
Normal file
44
molecule/universal/hosts.yml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
# Пресет с 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
|
||||||
28
molecule/universal/molecule.yml
Normal file
28
molecule/universal/molecule.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
# Универсальная конфигурация Molecule
|
||||||
|
# Автор: Сергей Антропов
|
||||||
|
# Сайт: https://devops.org.ru
|
||||||
|
|
||||||
|
driver:
|
||||||
|
name: delegated
|
||||||
|
|
||||||
|
provisioner:
|
||||||
|
name: ansible
|
||||||
|
config_options:
|
||||||
|
defaults:
|
||||||
|
stdout_callback: yaml
|
||||||
|
env:
|
||||||
|
ANSIBLE_STDOUT_CALLBACK: yaml
|
||||||
|
inventory:
|
||||||
|
links:
|
||||||
|
hosts: "${MOLECULE_EPHEMERAL_DIRECTORY}/inventory/hosts.ini"
|
||||||
|
|
||||||
|
dependency:
|
||||||
|
name: galaxy
|
||||||
|
|
||||||
|
verifier:
|
||||||
|
name: ansible
|
||||||
|
|
||||||
|
lint: |-
|
||||||
|
set -e
|
||||||
|
ansible-lint
|
||||||
95
molecule/universal/site.yml
Normal file
95
molecule/universal/site.yml
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
---
|
||||||
|
# Универсальный плейбук для тестирования
|
||||||
|
# Автор: Сергей Антропов
|
||||||
|
# Сайт: 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
|
||||||
|
package:
|
||||||
|
name:
|
||||||
|
- curl
|
||||||
|
- jq
|
||||||
|
- ca-certificates
|
||||||
|
- iproute2
|
||||||
|
- iputils-ping
|
||||||
|
- procps
|
||||||
|
- net-tools
|
||||||
|
- sudo
|
||||||
|
- vim
|
||||||
|
state: present
|
||||||
|
|
||||||
|
# ===== ТЕСТОВЫЕ РОЛИ =====
|
||||||
|
- name: Deploy example role to test hosts
|
||||||
|
hosts: test
|
||||||
|
become: true
|
||||||
|
roles:
|
||||||
|
- example
|
||||||
|
vars:
|
||||||
|
example_package_name: "nginx"
|
||||||
|
example_directory: "/opt/example"
|
||||||
|
example_setting: "test"
|
||||||
|
example_port: 8080
|
||||||
|
|
||||||
|
- name: Deploy example role to docker hosts (DinD)
|
||||||
|
hosts: docker
|
||||||
|
become: true
|
||||||
|
roles:
|
||||||
|
- example
|
||||||
|
vars:
|
||||||
|
example_package_name: "docker"
|
||||||
|
example_directory: "/opt/docker-example"
|
||||||
|
example_setting: "dind"
|
||||||
|
example_port: 8080
|
||||||
|
|
||||||
|
- name: Deploy example role to dood hosts (DOoD)
|
||||||
|
hosts: dood
|
||||||
|
become: true
|
||||||
|
roles:
|
||||||
|
- example
|
||||||
|
vars:
|
||||||
|
example_package_name: "docker"
|
||||||
|
example_directory: "/opt/dood-example"
|
||||||
|
example_setting: "dood"
|
||||||
|
example_port: 8081
|
||||||
|
|
||||||
|
# ===== Пример: поднять compose внутри DinD-хостов =====
|
||||||
|
- name: Deploy stack inside DinD nodes
|
||||||
|
hosts: docker
|
||||||
|
gather_facts: false
|
||||||
|
vars:
|
||||||
|
docker_host: "tcp://{{ inventory_hostname }}:2375"
|
||||||
|
stack_dir: /root/stack
|
||||||
|
tasks:
|
||||||
|
- name: Create stack directory
|
||||||
|
file:
|
||||||
|
path: "{{ stack_dir }}"
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Create simple docker-compose.yml
|
||||||
|
copy:
|
||||||
|
dest: "{{ stack_dir }}/docker-compose.yml"
|
||||||
|
content: |
|
||||||
|
version: '3.8'
|
||||||
|
services:
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
ports:
|
||||||
|
- "8080:80"
|
||||||
|
environment:
|
||||||
|
- NGINX_HOST=localhost
|
||||||
|
- NGINX_PORT=80
|
||||||
|
|
||||||
|
- name: Deploy stack with docker-compose
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: "{{ stack_dir }}"
|
||||||
|
state: present
|
||||||
|
docker_host: "{{ docker_host }}"
|
||||||
263
molecule/universal/verify.yml
Normal file
263
molecule/universal/verify.yml
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
---
|
||||||
|
# Универсальные проверки для тестового стенда
|
||||||
|
# Автор: Сергей Антропов
|
||||||
|
# Сайт: https://devops.org.ru
|
||||||
|
|
||||||
|
- name: Verify web servers
|
||||||
|
hosts: web
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Check nginx service status
|
||||||
|
systemd:
|
||||||
|
name: nginx
|
||||||
|
register: nginx_status
|
||||||
|
|
||||||
|
- name: Verify nginx is running
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- nginx_status.status.ActiveState == "active"
|
||||||
|
- nginx_status.status.SubState == "running"
|
||||||
|
fail_msg: "nginx service is not running"
|
||||||
|
success_msg: "nginx service is running"
|
||||||
|
|
||||||
|
- name: Test nginx response
|
||||||
|
uri:
|
||||||
|
url: "http://{{ inventory_hostname }}"
|
||||||
|
method: GET
|
||||||
|
register: nginx_response
|
||||||
|
|
||||||
|
- name: Verify nginx response
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- nginx_response.status == 200
|
||||||
|
fail_msg: "nginx is not responding"
|
||||||
|
success_msg: "nginx is responding correctly"
|
||||||
|
|
||||||
|
- name: Verify app servers
|
||||||
|
hosts: app
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Check Python installation
|
||||||
|
command: python3 --version
|
||||||
|
register: python_version
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Verify Python is installed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- python_version.rc == 0
|
||||||
|
fail_msg: "Python3 is not installed"
|
||||||
|
success_msg: "Python3 is installed: {{ python_version.stdout }}"
|
||||||
|
|
||||||
|
- name: Check app file exists
|
||||||
|
stat:
|
||||||
|
path: /opt/myapp/app.py
|
||||||
|
register: app_file
|
||||||
|
|
||||||
|
- name: Verify app file exists
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- app_file.stat.exists
|
||||||
|
fail_msg: "App file does not exist"
|
||||||
|
success_msg: "App file exists and is executable"
|
||||||
|
|
||||||
|
- name: Verify database servers
|
||||||
|
hosts: database
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Check SQLite installation
|
||||||
|
command: sqlite3 --version
|
||||||
|
register: sqlite_version
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Verify SQLite is installed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- sqlite_version.rc == 0
|
||||||
|
fail_msg: "SQLite is not installed"
|
||||||
|
success_msg: "SQLite is installed: {{ sqlite_version.stdout }}"
|
||||||
|
|
||||||
|
- name: Check database file exists
|
||||||
|
stat:
|
||||||
|
path: /var/lib/mydb/sample.db
|
||||||
|
register: db_file
|
||||||
|
|
||||||
|
- name: Verify database file exists
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- db_file.stat.exists
|
||||||
|
fail_msg: "Database file does not exist"
|
||||||
|
success_msg: "Database file exists"
|
||||||
|
|
||||||
|
- name: Test database query
|
||||||
|
command: sqlite3 /var/lib/mydb/sample.db "SELECT COUNT(*) FROM users;"
|
||||||
|
register: db_query
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Verify database query
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- db_query.rc == 0
|
||||||
|
- db_query.stdout | int > 0
|
||||||
|
fail_msg: "Database query failed"
|
||||||
|
success_msg: "Database query successful: {{ db_query.stdout }} users found"
|
||||||
|
|
||||||
|
- name: Verify cache servers
|
||||||
|
hosts: cache
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Check Redis service status
|
||||||
|
systemd:
|
||||||
|
name: redis
|
||||||
|
register: redis_status
|
||||||
|
|
||||||
|
- name: Verify Redis is running
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- redis_status.status.ActiveState == "active"
|
||||||
|
- redis_status.status.SubState == "running"
|
||||||
|
fail_msg: "Redis service is not running"
|
||||||
|
success_msg: "Redis service is running"
|
||||||
|
|
||||||
|
- name: Test Redis connection
|
||||||
|
command: redis-cli ping
|
||||||
|
register: redis_ping
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Verify Redis connection
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- redis_ping.rc == 0
|
||||||
|
- redis_ping.stdout == "PONG"
|
||||||
|
fail_msg: "Redis is not responding"
|
||||||
|
success_msg: "Redis is responding correctly"
|
||||||
|
|
||||||
|
- name: Verify load balancer
|
||||||
|
hosts: loadbalancer
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Check HAProxy service status
|
||||||
|
systemd:
|
||||||
|
name: haproxy
|
||||||
|
register: haproxy_status
|
||||||
|
|
||||||
|
- name: Verify HAProxy is running
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- haproxy_status.status.ActiveState == "active"
|
||||||
|
- haproxy_status.status.SubState == "running"
|
||||||
|
fail_msg: "HAProxy service is not running"
|
||||||
|
success_msg: "HAProxy service is running"
|
||||||
|
|
||||||
|
- name: Check HAProxy configuration
|
||||||
|
stat:
|
||||||
|
path: /etc/haproxy/haproxy.cfg
|
||||||
|
register: haproxy_config
|
||||||
|
|
||||||
|
- name: Verify HAProxy configuration exists
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- haproxy_config.stat.exists
|
||||||
|
fail_msg: "HAProxy configuration does not exist"
|
||||||
|
success_msg: "HAProxy configuration exists"
|
||||||
|
|
||||||
|
- name: Verify monitoring
|
||||||
|
hosts: monitoring
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Check monitoring tools
|
||||||
|
command: which htop
|
||||||
|
register: htop_check
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Verify monitoring tools are installed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- htop_check.rc == 0
|
||||||
|
fail_msg: "Monitoring tools are not installed"
|
||||||
|
success_msg: "Monitoring tools are installed"
|
||||||
|
|
||||||
|
- name: Check monitoring script
|
||||||
|
stat:
|
||||||
|
path: /usr/local/bin/system-info.sh
|
||||||
|
register: monitor_script
|
||||||
|
|
||||||
|
- name: Verify monitoring script exists
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- monitor_script.stat.exists
|
||||||
|
fail_msg: "Monitoring script does not exist"
|
||||||
|
success_msg: "Monitoring script exists"
|
||||||
|
|
||||||
|
- name: Test monitoring script
|
||||||
|
command: /usr/local/bin/system-info.sh
|
||||||
|
register: monitor_output
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Verify monitoring script works
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- monitor_output.rc == 0
|
||||||
|
- monitor_output.stdout | length > 0
|
||||||
|
fail_msg: "Monitoring script failed"
|
||||||
|
success_msg: "Monitoring script works correctly"
|
||||||
|
|
||||||
|
- name: Network connectivity tests
|
||||||
|
hosts: all
|
||||||
|
tasks:
|
||||||
|
- name: Test connectivity to web servers
|
||||||
|
wait_for:
|
||||||
|
host: "{{ item }}"
|
||||||
|
port: 80
|
||||||
|
timeout: 10
|
||||||
|
loop:
|
||||||
|
- web1
|
||||||
|
- web2
|
||||||
|
when: "'web' not in group_names"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Test connectivity to app servers
|
||||||
|
wait_for:
|
||||||
|
host: "{{ item }}"
|
||||||
|
port: 8080
|
||||||
|
timeout: 10
|
||||||
|
loop:
|
||||||
|
- app1
|
||||||
|
when: "'app' not in group_names"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Test connectivity to cache servers
|
||||||
|
wait_for:
|
||||||
|
host: "{{ item }}"
|
||||||
|
port: 6379
|
||||||
|
timeout: 10
|
||||||
|
loop:
|
||||||
|
- cache1
|
||||||
|
when: "'cache' not in group_names"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Test connectivity to load balancer
|
||||||
|
wait_for:
|
||||||
|
host: lb1
|
||||||
|
port: 80
|
||||||
|
timeout: 10
|
||||||
|
when: "'loadbalancer' not in group_names"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Final verification summary
|
||||||
|
hosts: localhost
|
||||||
|
gather_facts: false
|
||||||
|
tasks:
|
||||||
|
- name: Display verification summary
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
========================================
|
||||||
|
Verification Summary
|
||||||
|
========================================
|
||||||
|
- Web servers: {{ 'OK' if web_servers_ok is defined else 'SKIPPED' }}
|
||||||
|
- App servers: {{ 'OK' if app_servers_ok is defined else 'SKIPPED' }}
|
||||||
|
- Database servers: {{ 'OK' if database_servers_ok is defined else 'SKIPPED' }}
|
||||||
|
- Cache servers: {{ 'OK' if cache_servers_ok is defined else 'SKIPPED' }}
|
||||||
|
- Load balancer: {{ 'OK' if loadbalancer_ok is defined else 'SKIPPED' }}
|
||||||
|
- Monitoring: {{ 'OK' if monitoring_ok is defined else 'SKIPPED' }}
|
||||||
|
========================================
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
---
|
---
|
||||||
|
# Ansible Collections для Molecule Universal
|
||||||
collections:
|
collections:
|
||||||
- name: maxhoesel.proxmox
|
- name: community.docker
|
||||||
version: 5.0.1
|
version: ">=3.0.0"
|
||||||
|
- name: community.general
|
||||||
|
version: ">=7.0.0"
|
||||||
|
- name: ansible.posix
|
||||||
|
version: ">=1.4.0"
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
---
|
|
||||||
10
scripts/list-presets.sh
Executable file
10
scripts/list-presets.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Скрипт для показа всех пресетов
|
||||||
|
# Автор: Сергей Антропов
|
||||||
|
# Сайт: https://devops.org.ru
|
||||||
|
|
||||||
|
clear
|
||||||
|
echo "Доступные пресеты:"
|
||||||
|
for file in molecule/presets/*.yml; do
|
||||||
|
echo " $(basename "$file" .yml)"
|
||||||
|
done
|
||||||
35
scripts/use-preset.sh
Executable file
35
scripts/use-preset.sh
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Скрипт для переключения между пресетами
|
||||||
|
# Автор: Сергей Антропов
|
||||||
|
# Сайт: https://devops.org.ru
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
PRESET_DIR="molecule/presets"
|
||||||
|
HOSTS_FILE="molecule/universal/hosts.yml"
|
||||||
|
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
echo "Использование: $0 <preset_name>"
|
||||||
|
echo ""
|
||||||
|
echo "Доступные пресеты:"
|
||||||
|
ls -1 "$PRESET_DIR"/*.yml | sed 's/.*\///' | sed 's/\.yml$//' | sed 's/^/ /'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PRESET="$1"
|
||||||
|
PRESET_FILE="$PRESET_DIR/$PRESET.yml"
|
||||||
|
|
||||||
|
if [ ! -f "$PRESET_FILE" ]; then
|
||||||
|
echo "Ошибка: Пресет '$PRESET' не найден!"
|
||||||
|
echo "Доступные пресеты:"
|
||||||
|
ls -1 "$PRESET_DIR"/*.yml | sed 's/.*\///' | sed 's/\.yml$//' | sed 's/^/ /'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Переключение на пресет: $PRESET"
|
||||||
|
cp "$PRESET_FILE" "$HOSTS_FILE"
|
||||||
|
echo "Готово! Теперь используется пресет: $PRESET"
|
||||||
|
echo ""
|
||||||
|
echo "Для применения изменений выполните:"
|
||||||
|
echo " make molecule destroy"
|
||||||
|
echo " make molecule create"
|
||||||
@@ -1 +0,0 @@
|
|||||||
password123
|
|
||||||
33
vault/secrets.yml
Normal file
33
vault/secrets.yml
Normal 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"
|
||||||
Reference in New Issue
Block a user