From 0b981ca61edc367ffb7100f458d5fcd7f1f55bd9 Mon Sep 17 00:00:00 2001 From: Sergey Antropoff Date: Wed, 22 Oct 2025 20:31:23 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D0=B0?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B5=D1=81=D0=B5=D1=82=D0=BE=D0=B2=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20Molecule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Создана система пресетов для быстрого переключения между конфигурациями - Добавлены пресеты: minimal, standard, docker, cluster - Обновлена структура проекта с папками cicd/, vault/, scripts/ - Упрощена система vault с функциональными секретами - Добавлены скрипты для работы с пресетами - Обновлен Makefile с командами для пресетов - Удалены старые файлы и структуры Автор: Сергей Антропов Сайт: https://devops.org.ru --- .../.gitkeep => .cursor/commands/docs.md | 0 .gitignore | 4 + .gitlab-ci.yml | 89 ------ Dockerfile | 40 --- Dockerfile-CentOS | 54 ---- Dockerfile-Ubuntu | 62 ---- Makefile | 264 ++++++++++-------- README.md | 62 ---- ansible.cfg | 4 +- cicd/.gitlab-ci.yml | 51 ++++ cicd/azure-devops/azure-pipelines.yml | 53 ++++ cicd/github/workflows.yml | 70 +++++ {gitlab => cicd/gitlab}/config.json | 0 {gitlab => cicd/gitlab}/docker-compose.yaml | 0 {gitlab => cicd/gitlab}/runner/config.toml | 0 cicd/jenkins/Jenkinsfile | 59 ++++ default/deploy.yaml | 10 - default/meta/.gitkeep | 0 default/tasks/debian/main.yaml | 4 - default/tasks/main.yaml | 12 - default/tasks/redhat/main.yaml | 4 - default/templates/.gitkeep | 0 default/tests/.gitkeep | 0 docker-compose.yaml | 12 - inventory/hosts | 1 - inventory/hosts.ini | 29 ++ molecule/default/converge.yml | 6 - molecule/default/destroy.yml | 8 - molecule/default/molecule.yml | 61 ---- molecule/default/no-prepare.yml | 43 --- molecule/default/no-verify.yml | 7 - molecule/default/verify.yml | 132 --------- molecule/presets/README.md | 99 +++++++ molecule/presets/cluster.yml | 57 ++++ molecule/presets/docker.yml | 44 +++ molecule/presets/minimal.yml | 25 ++ molecule/presets/standard.yml | 32 +++ molecule/universal/converge.yml | 52 ++++ molecule/universal/create.yml | 107 +++++++ molecule/universal/destroy.yml | 29 ++ molecule/universal/hosts.yml | 44 +++ molecule/universal/molecule.yml | 28 ++ molecule/universal/site.yml | 95 +++++++ molecule/universal/verify.yml | 263 +++++++++++++++++ requirements.yml | 9 +- {default/files => roles}/.gitkeep | 0 roles/deploy.yaml | 1 - scripts/list-presets.sh | 10 + scripts/use-preset.sh | 35 +++ vars/.gitkeep | 0 vault-password.txt | 1 - {default/handlers => vault}/.gitkeep | 0 vault/secrets.yml | 33 +++ 53 files changed, 1377 insertions(+), 728 deletions(-) rename default/defaults/.gitkeep => .cursor/commands/docs.md (100%) delete mode 100644 .gitlab-ci.yml delete mode 100644 Dockerfile delete mode 100644 Dockerfile-CentOS delete mode 100644 Dockerfile-Ubuntu delete mode 100644 README.md create mode 100644 cicd/.gitlab-ci.yml create mode 100644 cicd/azure-devops/azure-pipelines.yml create mode 100644 cicd/github/workflows.yml rename {gitlab => cicd/gitlab}/config.json (100%) rename {gitlab => cicd/gitlab}/docker-compose.yaml (100%) rename {gitlab => cicd/gitlab}/runner/config.toml (100%) create mode 100644 cicd/jenkins/Jenkinsfile delete mode 100644 default/deploy.yaml delete mode 100644 default/meta/.gitkeep delete mode 100644 default/tasks/debian/main.yaml delete mode 100644 default/tasks/main.yaml delete mode 100644 default/tasks/redhat/main.yaml delete mode 100644 default/templates/.gitkeep delete mode 100644 default/tests/.gitkeep delete mode 100644 docker-compose.yaml delete mode 100644 inventory/hosts create mode 100644 inventory/hosts.ini delete mode 100644 molecule/default/converge.yml delete mode 100644 molecule/default/destroy.yml delete mode 100644 molecule/default/molecule.yml delete mode 100644 molecule/default/no-prepare.yml delete mode 100644 molecule/default/no-verify.yml delete mode 100644 molecule/default/verify.yml create mode 100644 molecule/presets/README.md create mode 100644 molecule/presets/cluster.yml create mode 100644 molecule/presets/docker.yml create mode 100644 molecule/presets/minimal.yml create mode 100644 molecule/presets/standard.yml create mode 100644 molecule/universal/converge.yml create mode 100644 molecule/universal/create.yml create mode 100644 molecule/universal/destroy.yml create mode 100644 molecule/universal/hosts.yml create mode 100644 molecule/universal/molecule.yml create mode 100644 molecule/universal/site.yml create mode 100644 molecule/universal/verify.yml rename {default/files => roles}/.gitkeep (100%) delete mode 100644 roles/deploy.yaml create mode 100755 scripts/list-presets.sh create mode 100755 scripts/use-preset.sh delete mode 100644 vars/.gitkeep delete mode 100644 vault-password.txt rename {default/handlers => vault}/.gitkeep (100%) create mode 100644 vault/secrets.yml diff --git a/default/defaults/.gitkeep b/.cursor/commands/docs.md similarity index 100% rename from default/defaults/.gitkeep rename to .cursor/commands/docs.md diff --git a/.gitignore b/.gitignore index 52fd67b..0efb408 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ # ---> Ansible *.retry +# ---> Vault (секретные файлы) +vault/.vault +vault/secrets/*.yml + # ---> Python # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 791c0d1..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -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 "Работа пайплайна завершена" - diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index dfe699f..0000000 --- a/Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -# Используем готовый образ с Ansible -FROM geerlingguy/docker-ubuntu2204-ansible:latest - -# Добавляем метаданные -LABEL maintainer="Сергей Антропов " -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"] \ No newline at end of file diff --git a/Dockerfile-CentOS b/Dockerfile-CentOS deleted file mode 100644 index 1ed526a..0000000 --- a/Dockerfile-CentOS +++ /dev/null @@ -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"] \ No newline at end of file diff --git a/Dockerfile-Ubuntu b/Dockerfile-Ubuntu deleted file mode 100644 index 416bce7..0000000 --- a/Dockerfile-Ubuntu +++ /dev/null @@ -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"] \ No newline at end of file diff --git a/Makefile b/Makefile index fb5437e..00538ab 100644 --- a/Makefile +++ b/Makefile @@ -1,135 +1,130 @@ -# Глобальные переменные -IMAGE ?= ansible -TAG ?= 0.1 -REGISTRY ?= inecs/ansible -# По умолчанию используем docker. Для локальной разработки используйте docker-compose -RUN_MODE ?= docker +# AnsibleTemplate - Универсальная система тестирования Ansible ролей +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru -# Определение команды 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 - -view create edit show delete test lint deploy new init build rebuild prune release images push pull shell: - @true +.PHONY: molecule vault git help #################################################################################################### -# Инициализация новой роли +# Работа с пресетами #################################################################################################### -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 +# Пресеты +preset-list: + @./scripts/list-presets.sh + +preset-use: + @./scripts/use-preset.sh $(word 2, $(MAKECMDGOALS)) + +# Псевдонимы для пресетов +preset-minimal: + @./scripts/use-preset.sh minimal + +preset-standard: + @./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 \ - 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) \ + create) \ 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";; \ + echo "Создание тестового окружения..."; \ + cd molecule/universal && molecule create -s universal;; \ + converge) \ + clear; \ + echo "Запуск плейбуков..."; \ + cd molecule/universal && molecule converge -s universal;; \ + verify) \ + clear; \ + echo "Проверка результатов..."; \ + cd molecule/universal && molecule verify -s universal;; \ + destroy) \ + clear; \ + echo "Удаление тестового окружения..."; \ + cd molecule/universal && molecule destroy -s universal;; \ + test) \ + clear; \ + echo "Полный цикл тестирования..."; \ + 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 #################################################################################################### -# Работа с ролью +# Работа с Ansible Vault #################################################################################################### 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 - -role: - @case "$(word 2, $(MAKECMDGOALS))" in \ - new) \ + show) \ 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) \ + echo "Доступные файлы секретов:"; \ + ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ + echo ""; \ + read -p "Введите имя файла (без .yml): " FILE; \ + ansible-vault view --vault-password-file vault/.vault vault/$$FILE.yml;; \ + create) \ 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";; \ - test) \ + echo "Создание файла секретов:"; \ + read -p "Введите имя файла (без .yml): " FILE; \ + ansible-vault create --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \ + edit) \ 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";; \ - deploy) \ + echo "Доступные файлы секретов:"; \ + ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ + echo ""; \ + read -p "Введите имя файла (без .yml): " FILE; \ + ansible-vault edit --vault-password-file vault/.vault vault/$$FILE.yml;; \ + delete) \ clear; \ - echo "Deploying roles to production..."; \ - $(RUN) bash -c "ansible-playbook roles/deploy.yaml";; \ - *) echo "Unknown action";; \ + 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; \ + 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 #################################################################################################### @@ -153,5 +148,44 @@ git: NEW_BRANCH="$$BRANCH_NAME"; \ git checkout -b $$NEW_BRANCH; \ echo "Создана и переключена на новую ветку: $$NEW_BRANCH";; \ - *) echo "Unknown action. Available actions: push, pull, cluster-branch";; \ - esac \ No newline at end of file + *) \ + clear; \ + echo "Доступные команды:"; \ + echo " make git push - запушить изменения"; \ + echo " make git pull - получить изменения"; \ + echo " make git new - создать новую ветку";; \ + 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 \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index b371258..0000000 --- a/README.md +++ /dev/null @@ -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 для нормального тестирования ролей. \ No newline at end of file diff --git a/ansible.cfg b/ansible.cfg index d43f8b2..234678a 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -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 diff --git a/cicd/.gitlab-ci.yml b/cicd/.gitlab-ci.yml new file mode 100644 index 0000000..46c6e74 --- /dev/null +++ b/cicd/.gitlab-ci.yml @@ -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 \ No newline at end of file diff --git a/cicd/azure-devops/azure-pipelines.yml b/cicd/azure-devops/azure-pipelines.yml new file mode 100644 index 0000000..ab8e86f --- /dev/null +++ b/cicd/azure-devops/azure-pipelines.yml @@ -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() diff --git a/cicd/github/workflows.yml b/cicd/github/workflows.yml new file mode 100644 index 0000000..8a3b5a9 --- /dev/null +++ b/cicd/github/workflows.yml @@ -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/ diff --git a/gitlab/config.json b/cicd/gitlab/config.json similarity index 100% rename from gitlab/config.json rename to cicd/gitlab/config.json diff --git a/gitlab/docker-compose.yaml b/cicd/gitlab/docker-compose.yaml similarity index 100% rename from gitlab/docker-compose.yaml rename to cicd/gitlab/docker-compose.yaml diff --git a/gitlab/runner/config.toml b/cicd/gitlab/runner/config.toml similarity index 100% rename from gitlab/runner/config.toml rename to cicd/gitlab/runner/config.toml diff --git a/cicd/jenkins/Jenkinsfile b/cicd/jenkins/Jenkinsfile new file mode 100644 index 0000000..52dbe53 --- /dev/null +++ b/cicd/jenkins/Jenkinsfile @@ -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!' + } + } +} diff --git a/default/deploy.yaml b/default/deploy.yaml deleted file mode 100644 index 61ab8b8..0000000 --- a/default/deploy.yaml +++ /dev/null @@ -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: \ No newline at end of file diff --git a/default/meta/.gitkeep b/default/meta/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/default/tasks/debian/main.yaml b/default/tasks/debian/main.yaml deleted file mode 100644 index 4c32e03..0000000 --- a/default/tasks/debian/main.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -- name: Пример таски - debug: - msg: "Привет! Я запустился на Debian/Ubuntu!" diff --git a/default/tasks/main.yaml b/default/tasks/main.yaml deleted file mode 100644 index 2b9ddee..0000000 --- a/default/tasks/main.yaml +++ /dev/null @@ -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" diff --git a/default/tasks/redhat/main.yaml b/default/tasks/redhat/main.yaml deleted file mode 100644 index 64e5c36..0000000 --- a/default/tasks/redhat/main.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -- name: Пример таски - debug: - msg: "Привет! Я запустился на RedHat/CentOS/Fedora!" diff --git a/default/templates/.gitkeep b/default/templates/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/default/tests/.gitkeep b/default/tests/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/docker-compose.yaml b/docker-compose.yaml deleted file mode 100644 index e920595..0000000 --- a/docker-compose.yaml +++ /dev/null @@ -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 \ No newline at end of file diff --git a/inventory/hosts b/inventory/hosts deleted file mode 100644 index a4a29bb..0000000 --- a/inventory/hosts +++ /dev/null @@ -1 +0,0 @@ -[all] diff --git a/inventory/hosts.ini b/inventory/hosts.ini new file mode 100644 index 0000000..2e9df5f --- /dev/null +++ b/inventory/hosts.ini @@ -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 diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml deleted file mode 100644 index 749dcda..0000000 --- a/molecule/default/converge.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: Converge - hosts: all - vars_files: - - ../../vars/secrets.yml - roles: \ No newline at end of file diff --git a/molecule/default/destroy.yml b/molecule/default/destroy.yml deleted file mode 100644 index 82979c7..0000000 --- a/molecule/default/destroy.yml +++ /dev/null @@ -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 }}" \ No newline at end of file diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml deleted file mode 100644 index f374694..0000000 --- a/molecule/default/molecule.yml +++ /dev/null @@ -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 - diff --git a/molecule/default/no-prepare.yml b/molecule/default/no-prepare.yml deleted file mode 100644 index 57b792f..0000000 --- a/molecule/default/no-prepare.yml +++ /dev/null @@ -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 diff --git a/molecule/default/no-verify.yml b/molecule/default/no-verify.yml deleted file mode 100644 index 5e80115..0000000 --- a/molecule/default/no-verify.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Prepare - hosts: all - tasks: - - name: Reun verify - debug: - msg: "Hello, Verify!" diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml deleted file mode 100644 index a8aa9f6..0000000 --- a/molecule/default/verify.yml +++ /dev/null @@ -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 '✗ Недоступен' }} - ======================================== diff --git a/molecule/presets/README.md b/molecule/presets/README.md new file mode 100644 index 0000000..bbf94f2 --- /dev/null +++ b/molecule/presets/README.md @@ -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"] +``` diff --git a/molecule/presets/cluster.yml b/molecule/presets/cluster.yml new file mode 100644 index 0000000..1a4ffd9 --- /dev/null +++ b/molecule/presets/cluster.yml @@ -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"] diff --git a/molecule/presets/docker.yml b/molecule/presets/docker.yml new file mode 100644 index 0000000..500383e --- /dev/null +++ b/molecule/presets/docker.yml @@ -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 diff --git a/molecule/presets/minimal.yml b/molecule/presets/minimal.yml new file mode 100644 index 0000000..c096043 --- /dev/null +++ b/molecule/presets/minimal.yml @@ -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] diff --git a/molecule/presets/standard.yml b/molecule/presets/standard.yml new file mode 100644 index 0000000..aff8ee6 --- /dev/null +++ b/molecule/presets/standard.yml @@ -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] diff --git a/molecule/universal/converge.yml b/molecule/universal/converge.yml new file mode 100644 index 0000000..7e3ebd8 --- /dev/null +++ b/molecule/universal/converge.yml @@ -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 \ No newline at end of file diff --git a/molecule/universal/create.yml b/molecule/universal/create.yml new file mode 100644 index 0000000..6353e15 --- /dev/null +++ b/molecule/universal/create.yml @@ -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" \ No newline at end of file diff --git a/molecule/universal/destroy.yml b/molecule/universal/destroy.yml new file mode 100644 index 0000000..59f1710 --- /dev/null +++ b/molecule/universal/destroy.yml @@ -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 \ No newline at end of file diff --git a/molecule/universal/hosts.yml b/molecule/universal/hosts.yml new file mode 100644 index 0000000..500383e --- /dev/null +++ b/molecule/universal/hosts.yml @@ -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 diff --git a/molecule/universal/molecule.yml b/molecule/universal/molecule.yml new file mode 100644 index 0000000..9d03a0b --- /dev/null +++ b/molecule/universal/molecule.yml @@ -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 \ No newline at end of file diff --git a/molecule/universal/site.yml b/molecule/universal/site.yml new file mode 100644 index 0000000..2d06cd4 --- /dev/null +++ b/molecule/universal/site.yml @@ -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 }}" \ No newline at end of file diff --git a/molecule/universal/verify.yml b/molecule/universal/verify.yml new file mode 100644 index 0000000..b498eb7 --- /dev/null +++ b/molecule/universal/verify.yml @@ -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' }} + ======================================== \ No newline at end of file diff --git a/requirements.yml b/requirements.yml index cf12a33..1ddda93 100644 --- a/requirements.yml +++ b/requirements.yml @@ -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.4.0" diff --git a/default/files/.gitkeep b/roles/.gitkeep similarity index 100% rename from default/files/.gitkeep rename to roles/.gitkeep diff --git a/roles/deploy.yaml b/roles/deploy.yaml deleted file mode 100644 index 73b314f..0000000 --- a/roles/deploy.yaml +++ /dev/null @@ -1 +0,0 @@ ---- \ No newline at end of file diff --git a/scripts/list-presets.sh b/scripts/list-presets.sh new file mode 100755 index 0000000..f622806 --- /dev/null +++ b/scripts/list-presets.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Скрипт для показа всех пресетов +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +clear +echo "Доступные пресеты:" +for file in molecule/presets/*.yml; do + echo " $(basename "$file" .yml)" +done diff --git a/scripts/use-preset.sh b/scripts/use-preset.sh new file mode 100755 index 0000000..49f1044 --- /dev/null +++ b/scripts/use-preset.sh @@ -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 " + 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" diff --git a/vars/.gitkeep b/vars/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/vault-password.txt b/vault-password.txt deleted file mode 100644 index 2d27916..0000000 --- a/vault-password.txt +++ /dev/null @@ -1 +0,0 @@ -password123 \ No newline at end of file diff --git a/default/handlers/.gitkeep b/vault/.gitkeep similarity index 100% rename from default/handlers/.gitkeep rename to vault/.gitkeep diff --git a/vault/secrets.yml b/vault/secrets.yml new file mode 100644 index 0000000..f70e574 --- /dev/null +++ b/vault/secrets.yml @@ -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"