feat: улучшения роли devops и тестирования

- Убрана подстановка значений по умолчанию для devops_password и devops_ssh_public_key
- Добавлена строгая валидация секретов из vault/secrets.yml с детальными сообщениями об ошибках
- Убран подробный вывод установки пакетов в тасках
- Исправлена проблема с созданием симлинков в vault/ при тестировании
- Обновлена логика загрузки vault переменных в molecule тестах
- Добавлена очистка симлинков в destroy.yml для дополнительной безопасности

Автор: Сергей Антропов
Сайт: https://devops.org.ru
This commit is contained in:
Сергей Антропов
2025-10-29 18:53:52 +03:00
parent f6d1182193
commit cb5045fb79
23 changed files with 821 additions and 679 deletions

111
Makefile
View File

@@ -91,7 +91,27 @@ role:
-e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule_workspace \
-e MOLECULE_VAULT_ENABLED=$${MOLECULE_VAULT_ENABLED:-false} \
$(DOCKER_IMAGE) \
bash -c "mkdir -p /tmp/molecule_workspace/inventory && cd molecule/default && ansible-playbook -i localhost, create.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace && ansible-playbook -i localhost, converge.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace && ansible-playbook -i /tmp/molecule_workspace/inventory/hosts.ini site.yml; ansible-playbook -i localhost, destroy.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace; echo '✅ Тестирование завершено'";; \
bash -c " \
echo '=== СОЗДАНИЕ ТЕСТОВЫХ КОНТЕЙНЕРОВ ==='; \
mkdir -p /tmp/molecule_workspace/inventory && \
cd molecule/default && \
ansible-playbook -i localhost, create.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace && \
echo ''; \
echo '=== НАСТРОЙКА VAULT И ПЕРЕМЕННЫХ ==='; \
ansible-playbook -i localhost, converge.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace && \
echo ''; \
echo '=== ПРОВЕРКА ПОДКЛЮЧЕНИЯ К КОНТЕЙНЕРАМ ==='; \
ansible all -i /tmp/molecule_workspace/inventory/hosts.ini -m ping && \
echo ''; \
echo '=== ЗАПУСК RUN.YML НА ТЕСТОВЫХ КОНТЕЙНЕРАХ ==='; \
ansible-playbook -i /tmp/molecule_workspace/inventory/hosts.ini run.yml -v -e vault_devops_password="123123" -e vault_devops_ssh_public_key="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDBjzRt/b5Xe/tgQS2rvOBXOSBq1hychcnbz6G4m9Ps6hQXCxLA0hcrzPIRGazeWEslqsBynSm4fVJC6zAnExEd7KsNxS5gsMxmcHsghuU6/IA62tP8w8tXKEWaCGMQyfcUO/MIrdEjAg8txl3FIxdlcYwBTLW9nJggOmUn9w1YOA6ECNBDUbTwZC62yomJhQoAK0W+uVkKSLTqRIvd0oZJEF+0dtzBrhhe7cjR6fuoLpkB1/Q9bQImVfAxEiiExhFWFMxcyf4SGxpmsbKI4rJ3eBvsMmhrX76p1bYX4fKGiBaqNyXqThYWYybXfDfaITQR87SIrVt4U4NzS79ZFfQ142VPs+YISiy/+/VKZ1NjHo1fRZJSqBtsWJCsvtuM6C2+dRZ0JqwwMlHKLNhmerYMLJMQxkxdB5jRxafC+3T0aFNIsFIa7MdC8i3WQBk5z5huY5pslkPWnmKTfCi3gLjWNhfW9xEgKAww6hGrZR/zlQXZQrmQ2LGspzXFngd9tmk= linux@key" && \
echo ''; \
echo '=== ЗАПУСК ROLES/DEPLOY.YML НА ТЕСТОВЫХ КОНТЕЙНЕРАХ ==='; \
ansible-playbook -i /tmp/molecule_workspace/inventory/hosts.ini ../../roles/deploy.yml -v -e vault_devops_password="123123" -e vault_devops_ssh_public_key="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDBjzRt/b5Xe/tgQS2rvOBXOSBq1hychcnbz6G4m9Ps6hQXCxLA0hcrzPIRGazeWEslqsBynSm4fVJC6zAnExEd7KsNxS5gsMxmcHsghuU6/IA62tP8w8tXKEWaCGMQyfcUO/MIrdEjAg8txl3FIxdlcYwBTLW9nJggOmUn9w1YOA6ECNBDUbTwZC62yomJhQoAK0W+uVkKSLTqRIvd0oZJEF+0dtzBrhhe7cjR6fuoLpkB1/Q9bQImVfAxEiiExhFWFMxcyf4SGxpmsbKI4rJ3eBvsMmhrX76p1bYX4fKGiBaqNyXqThYWYybXfDfaITQR87SIrVt4U4NzS79ZFfQ142VPs+YISiy/+/VKZ1NjHo1fRZJSqBtsWJCsvtuM6C2+dRZ0JqwwMlHKLNhmerYMLJMQxkxdB5jRxafC+3T0aFNIsFIa7MdC8i3WQBk5z5huY5pslkPWnmKTfCi3gLjWNhfW9xEgKAww6hGrZR/zlQXZQrmQ2LGspzXFngd9tmk= linux@key" && \
echo ''; \
echo '=== ОЧИСТКА РЕСУРСОВ ==='; \
ansible-playbook -i localhost, destroy.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace && \
echo '✅ Тестирование завершено'";; \
deploy) \
echo "🚀 Развертывание ролей на реальные серверы..."; \
echo ""; \
@@ -223,26 +243,6 @@ presets:
echo ""; \
echo "🐳 Образы:"; \
grep -E "^- " "molecule/presets/$(PRESET).yml" | grep -E "family:" | sed 's/.*family: / - /' || echo "Образы не найдены";; \
test) \
if [ -z "$(PRESET)" ]; then \
echo "❌ Ошибка: Укажите PRESET=имя_пресета"; \
echo "💡 Пример: make presets test PRESET=etcd-patroni"; \
exit 1; \
fi; \
if [ ! -f "molecule/presets/$(PRESET).yml" ]; then \
echo "❌ Ошибка: Пресет '$(PRESET)' не найден!"; \
echo "💡 Доступные пресеты:"; \
make presets list; \
exit 1; \
fi; \
echo "🚀 Тестирование с пресетом: $(PRESET)"; \
echo ""; \
docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \
-v /var/run/docker.sock:/var/run/docker.sock \
-e ANSIBLE_FORCE_COLOR=1 \
-e MOLECULE_PRESET=$(PRESET) \
$(DOCKER_IMAGE) \
bash -c "cd molecule/default && molecule test" || echo "✅ Тестирование завершено";; \
*) \
echo "🎯 Доступные команды:"; \
echo ""; \
@@ -253,15 +253,9 @@ presets:
echo " 💡 Показывает: описание, хосты, сеть, образы"; \
echo " 💡 Требует: PRESET=имя_пресета"; \
echo ""; \
echo " 🚀 make presets test - запустить тест с preset'ом"; \
echo " 💡 Запускает: molecule test с выбранным preset'ом"; \
echo " 💡 Требует: PRESET=имя_пресета"; \
echo ""; \
echo "💡 Примеры:"; \
echo " make presets list # показать все preset'ы"; \
echo " make presets info PRESET=etcd-patroni # информация о etcd-patroni"; \
echo " make presets test PRESET=minimal # тест с minimal preset"; \
echo " make presets test PRESET=performance # тест с performance preset";; \
echo " make presets info PRESET=etcd-patroni # информация о etcd-patroni";; \
esac
# =============================================================================
@@ -1571,12 +1565,6 @@ help:
@echo "📋 PRESET'Ы (тестовые окружения):"
@echo " make presets list - показать все доступные preset'ы"
@echo " make presets info - подробная информация о preset'е"
@echo " make presets test - запустить тест с preset'ом"
@echo ""
@echo "🖼️ СОБСТВЕННЫЕ ОБРАЗЫ (DevOpsLab):"
@echo " make custom-images test [minimal|full|performance] - тест с собственными образами"
@echo " make custom-images check - проверить наличие собственных образов"
@echo " make custom-images build - собрать все образы для тестирования"
@echo ""
@echo "🐳 DOCKER ОБРАЗЫ (Multi-Arch):"
@echo " make docker prepare - подготовка к работе с Docker Hub"
@@ -1641,7 +1629,6 @@ help:
@echo ""
@echo "💡 ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:"
@echo " make presets list # показать все preset'ы"
@echo " make presets test PRESET=etcd-patroni # тест с etcd-patroni"
@echo " make role test minimal # быстрый тест"
@echo " make role test all-images # тест всех образов"
@echo " make docker setup-builder # настройка multi-arch builder"
@@ -1658,60 +1645,6 @@ help:
@echo "📖 Подробная справка: make [команда]"
@echo "=========================================="
# =============================================================================
# КОМАНДЫ ДЛЯ РАБОТЫ С СОБСТВЕННЫМИ ОБРАЗАМИ
# =============================================================================
custom-images:
@case "$(word 2, $(MAKECMDGOALS))" in \
test) \
echo "🧪 Тестирование с собственными образами DevOpsLab..."; \
if [ -z "$(word 3, $(MAKECMDGOALS))" ]; then \
echo "💡 Использование: make custom-images test [minimal|full|performance]"; \
echo "💡 По умолчанию: minimal"; \
./scripts/test-custom-images.sh minimal; \
else \
./scripts/test-custom-images.sh $(word 3, $(MAKECMDGOALS)); \
fi;; \
check) \
echo "🔍 Проверка наличия собственных образов..."; \
./scripts/test-custom-images.sh check;; \
build) \
echo "🔨 Сборка всех образов для тестирования..."; \
$(MAKE) docker build;; \
*) \
echo "🎯 Доступные команды:"; \
echo ""; \
echo " 🧪 make custom-images test [minimal|full|performance] - тест с собственными образами"; \
echo " 💡 minimal - минимальный тест (4 хоста)"; \
echo " 💡 full - полный тест (все образы)"; \
echo " 💡 performance - тест производительности (8 хостов)"; \
echo ""; \
echo " 🔍 make custom-images check - проверить наличие собственных образов"; \
echo " 💡 Показывает: какие образы есть, какие отсутствуют"; \
echo " 💡 Предлагает: команды для сборки отсутствующих образов"; \
echo ""; \
echo " 🔨 make custom-images build - собрать все образы для тестирования"; \
echo " 💡 Выполняет: make docker build"; \
echo " 💡 Собирает: все образы DevOpsLab"; \
echo ""; \
echo "💡 Пресеты для тестирования:"; \
echo " - custom-minimal.yml - минимальный тест (4 хоста)"; \
echo " - custom-images.yml - полный тест (все образы)"; \
echo " - custom-performance.yml - тест производительности (8 хостов)"; \
echo ""; \
echo "💡 Собственные образы:"; \
echo " - inecs/ansible-lab:ansible-controller-latest"; \
echo " - inecs/ansible-lab:alt9-latest"; \
echo " - inecs/ansible-lab:alt10-latest"; \
echo " - inecs/ansible-lab:astra-linux-latest"; \
echo " - inecs/ansible-lab:redos-latest"; \
echo " - inecs/ansible-lab:rhel-latest"; \
echo " - inecs/ansible-lab:centos-latest"; \
echo " - inecs/ansible-lab:alma-latest"; \
echo " - inecs/ansible-lab:rocky-latest"; \
echo " - inecs/ansible-lab:ubuntu-latest"; \
echo " - inecs/ansible-lab:debian-latest";; \
esac
# =============================================================================
# АВТОМАТИЗАЦИЯ

View File

@@ -48,7 +48,7 @@ DevOpsLab/
│ │ ├── create.yml # Создание контейнеров
│ │ ├── converge.yml # Запуск тестов
│ │ ├── destroy.yml # Удаление контейнеров
│ │ ├── site.yml # Основной playbook
│ │ ├── run.yml # Основной playbook для обновления контейнеров
│ │ ├── verify.yml # Проверка конфигурации
│ │ └── molecule.yml # Конфигурация Molecule
│ └── presets/ # Preset конфигурации
@@ -596,7 +596,7 @@ make custom-images # справка по собственным
### Развертывание и конфигурация
- **[docs/site-yml-guide.md](docs/site-yml-guide.md)** - Руководство по файлу site.yml
- **[docs/run-yml-guide.md](docs/run-yml-guide.md)** - Руководство по файлу run.yml
- **[docs/deploy-yml-customization.md](docs/deploy-yml-customization.md)** - Полное руководство по кастомизации deploy.yml
### Безопасность и качество

View File

@@ -111,7 +111,7 @@ docker run --rm \
-v $(pwd):/workspace \
-w /workspace \
inecs/ansible-lab:ansible-controller-latest \
ansible-playbook site.yml
ansible-playbook run.yml
```
### 2. k8s

View File

@@ -91,7 +91,7 @@ jobs:
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add molecule/default/site.yml roles/deploy.yml
git add molecule/default/run.yml roles/deploy.yml
git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles"
git push
@@ -272,7 +272,7 @@ stages:
- script: |
git config --local user.email "action@azure.com"
git config --local user.name "Azure DevOps"
git add molecule/default/site.yml deploy.yml
git add molecule/default/run.yml deploy.yml
git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles"
git push
displayName: 'Commit Changes'
@@ -480,7 +480,7 @@ pipeline {
sh '''
git config --local user.email "jenkins@example.com"
git config --local user.name "Jenkins"
git add molecule/default/site.yml roles/deploy.yml
git add molecule/default/run.yml roles/deploy.yml
git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles"
git push
'''
@@ -656,7 +656,7 @@ update-playbooks:
- ./scripts/update-playbooks.sh
- git config --local user.email "gitlab@example.com"
- git config --local user.name "GitLab CI"
- git add molecule/default/site.yml deploy.yml
- git add molecule/default/run.yml deploy.yml
- git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles"
- git push
only:

View File

@@ -415,7 +415,7 @@ make role deploy
### 1. Автоматическое включение в playbook'и
Роль автоматически включается в:
- `molecule/default/site.yml` (для тестирования)
- `molecule/default/run.yml` (для тестирования)
- `roles/deploy.yml` (для продакшн развертывания)
### 2. Обновление playbook'ов

View File

@@ -88,7 +88,7 @@ docker run --rm \
-v $(pwd):/workspace \
-w /workspace \
inecs/ansible-lab:ansible-controller-latest \
ansible-playbook site.yml
ansible-playbook run.yml
```
### k8s

View File

@@ -26,7 +26,7 @@ molecule/
│ ├── converge.yml # Выполнение ролей в контейнерах
│ ├── verify.yml # Проверка результатов тестирования
│ ├── destroy.yml # Удаление тестовых контейнеров
│ └── site.yml # Основной playbook для тестирования
│ └── run.yml # Основной playbook для обновления контейнеров
└── presets/ # Preset конфигурации для разных сценариев
├── minimal.yml # Минимальный preset (1 хост)
├── performance.yml # Performance preset (12 хостов)
@@ -392,12 +392,12 @@ vars:
command: >
bash -lc "
ANSIBLE_ROLES_PATH=/workspace/roles
ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /workspace/molecule/default/site.yml
ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /workspace/molecule/default/run.yml
"
```
- **Назначение:** Выполнение основного playbook'а
- **Функции:**
- Запуск `site.yml` в ansible-controller контейнере
- Запуск `run.yml` в ansible-controller контейнере
- Использование сгенерированного инвентори
- Установка пути к ролям
@@ -602,7 +602,7 @@ vars:
- **Назначение:** Отображение сводки по очистке
- **Функция:** Информация о удаленных ресурсах
### 6. `molecule/default/site.yml` - Основной playbook
### 6. `molecule/default/run.yml` - Основной playbook
**Назначение:** Основной playbook для тестирования ролей.

View File

@@ -290,13 +290,13 @@ make clean-containers
make role lint
# Тест с verbose выводом
ansible-playbook -i inventory/hosts.ini site.yml -vvv
ansible-playbook -i inventory/hosts.ini run.yml -vvv
# Проверка переменных
ansible-inventory --list -i inventory/hosts.ini
# Dry-run без выполнения
ansible-playbook -i inventory/hosts.ini site.yml --check
ansible-playbook -i inventory/hosts.ini run.yml --check
```
### Проблемы с ролями
@@ -318,14 +318,14 @@ yamllint roles/docker/tasks/main.yml
```bash
# Проверка переменных
ansible-playbook -i inventory/hosts.ini site.yml --list-tags
ansible-playbook -i inventory/hosts.ini site.yml --list-tasks
ansible-playbook -i inventory/hosts.ini run.yml --list-tags
ansible-playbook -i inventory/hosts.ini run.yml --list-tasks
# Выполнение конкретной задачи
ansible-playbook -i inventory/hosts.ini site.yml --tags docker
ansible-playbook -i inventory/hosts.ini run.yml --tags docker
# Debug режим
ansible-playbook -i inventory/hosts.ini site.yml -vvv
ansible-playbook -i inventory/hosts.ini run.yml -vvv
```
## 📈 Сбор диагностической информации

248
docs/run-yml-guide.md Normal file
View File

@@ -0,0 +1,248 @@
# Руководство по файлу run.yml
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## 📋 Описание
Файл `molecule/default/run.yml` является **универсальным playbook'ом для обновления тестовых контейнеров**. Этот файл отвечает за подготовку окружения и установку необходимых утилит внутри контейнеров при запуске тестов.
## 🎯 Назначение
### Основные функции:
1. **Обновление пакетов** в контейнерах при запуске тестов
2. **Установка common tools** для корректной работы тестов
3. **Подготовка окружения** для тестирования ролей
4. **Импорт roles/deploy.yml** для запуска ролей
## 🏗️ Структура файла
### 1. Подготовка окружения для тестирования
```yaml
- name: Подготовка окружения для тестирования
hosts: all
become: true
tasks:
# Задачи подготовки...
```
**Что делает:**
- Обновляет кеш пакетов для всех поддерживаемых ОС
- Устанавливает необходимые утилиты
- Настраивает пользователя для тестирования
- Создает рабочие директории
### 2. Импорт deploy.yml
```yaml
- import_playbook: ../../roles/deploy.yml
```
**Что делает:**
- Импортирует `roles/deploy.yml` для запуска ролей
- Разделяет логику: `run.yml` - подготовка, `deploy.yml` - роли
- Обеспечивает единую точку управления ролями
## 🐧 Поддерживаемые ОС
### Debian/Ubuntu
- **Менеджер пакетов:** `apt`
- **Обновление:** `apt update`
- **Утилиты:** `curl`, `jq`, `ca-certificates`, `iproute2`, `iputils-ping`, `procps`, `net-tools`, `sudo`, `vim`, `wget`, `unzip`, `git`
### RHEL/CentOS/AlmaLinux/Rocky
- **Менеджер пакетов:** `yum`
- **Обновление:** `yum update_cache`
- **Утилиты:** `curl`, `jq`, `ca-certificates`, `iproute`, `iputils`, `procps-ng`, `net-tools`, `sudo`, `vim`, `wget`, `unzip`, `git`
### Alt Linux
- **Менеджер пакетов:** `apt` (специальная версия)
- **Обновление:** `apt update`
- **Утилиты:** `curl`, `jq`, `ca-certificates`, `iproute2`, `iputils`, `procps`, `net-tools`, `sudo`, `vim`, `wget`, `unzip`, `git`
## 🏷️ Теги (Tags)
### setup
- Обновление пакетов
- Установка утилит
- Настройка пользователей
- Создание директорий
### update
- Обновление кеша пакетов
- Обновление списка пакетов
### tools
- Установка common tools
- Установка системных утилит
### python
- Установка Python 3
- Установка pip
- Установка venv
### user
- Создание тестового пользователя
- Настройка домашней директории
### sudo
- Настройка sudo для тестового пользователя
- Конфигурация прав доступа
### directory
- Создание рабочих директорий
- Настройка прав доступа
### roles
- Запуск тестирования ролей
- Выполнение функциональных тестов
### test
- Тестирование функциональности
- Проверка работоспособности
## 🚀 Использование
### Запуск полного тестирования
```bash
make role test
```
### Запуск только подготовки окружения
```bash
make role test --tags setup
```
### Запуск только обновления пакетов
```bash
make role test --tags update
```
### Запуск только установки утилит
```bash
make role test --tags tools
```
### Запуск только тестирования ролей
```bash
make role test --tags roles
```
## 🔧 Настройка
### Переменные окружения
```bash
# Настройка тестового пользователя
export TEST_USER=testuser
# Настройка рабочей директории
export TEST_DIR=/tmp/ansible-test
# Настройка прав доступа
export TEST_MODE=0755
```
### Кастомизация утилит
Для добавления дополнительных утилит отредактируйте соответствующие секции:
```yaml
# Для Debian/Ubuntu
- name: Install common tools (Debian/Ubuntu)
apt:
name:
- curl
- jq
- your-custom-tool # Добавьте сюда
state: present
```
## 🐛 Troubleshooting
### Проблема: Ошибка обновления пакетов
**Решение:** Проверьте доступность репозиториев и интернет-соединение
### Проблема: Не удается установить утилиты
**Решение:** Проверьте названия пакетов для конкретной ОС
### Проблема: Ошибка создания пользователя
**Решение:** Проверьте права доступа и существование пользователя
### Проблема: Ошибка настройки sudo
**Решение:** Проверьте синтаксис файла sudoers
## 📊 Мониторинг
### Логи выполнения
```bash
# Просмотр логов тестирования
make role test 2>&1 | tee test.log
# Фильтрация по тегам
grep "TASK \[.*\]" test.log
```
### Проверка установленных утилит
```bash
# В контейнере
which curl jq vim git
```
### Проверка пользователя
```bash
# В контейнере
id testuser
sudo -l -U testuser
```
## 🔄 Автоматическое обновление
Файл `run.yml` автоматически обновляется при добавлении новых ролей:
```bash
# Автоматическое обновление
make update-playbooks
```
**Что происходит:**
1. Обнаруживаются все роли в директории `roles/`
2. Обновляется секция "Тестирование всех ролей"
3. Добавляются новые роли в список
## 📝 Примеры использования
### Тестирование конкретной роли
```bash
# Тестирование только роли ping
make role test minimal ping
```
### Тестирование с конкретным preset'ом
```bash
# Тестирование с preset'ом performance
make role test performance
```
### Отладка проблем
```bash
# Запуск с подробным выводом
make role test --verbose
```
## 🎯 Лучшие практики
1. **Всегда используйте теги** для разделения задач
2. **Проверяйте совместимость** утилит с ОС
3. **Тестируйте на разных образах** перед коммитом
4. **Используйте idempotent задачи** для стабильности
5. **Документируйте изменения** в комментариях
## 🔗 Связанные файлы
- `molecule/default/molecule.yml` - конфигурация Molecule
- `roles/deploy.yml` - playbook для продакшн развертывания
- `inventory/hosts.ini` - инвентори для тестирования
- `Makefile` - команды для запуска тестов

View File

@@ -1,11 +1,11 @@
# Руководство по файлу site.yml
# Руководство по файлу run.yml
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## 📋 Описание
Файл `molecule/default/site.yml` является **универсальным playbook'ом для тестирования Ansible ролей** в контейнерах. Этот файл отвечает за подготовку окружения и установку необходимых утилит внутри контейнеров при запуске тестов.
Файл `molecule/default/run.yml` является **универсальным playbook'ом для обновления тестовых контейнеров**. Этот файл отвечает за подготовку окружения и установку необходимых утилит внутри контейнеров при запуске тестов.
## 🎯 Назначение
@@ -42,7 +42,7 @@
**Что делает:**
- Импортирует `roles/deploy.yml` для запуска ролей
- Разделяет логику: `site.yml` - подготовка, `deploy.yml` - роли
- Разделяет логику: `run.yml` - подготовка, `deploy.yml` - роли
- Обеспечивает единую точку управления ролями
## 🐧 Поддерживаемые ОС
@@ -200,7 +200,7 @@ sudo -l -U testuser
## 🔄 Автоматическое обновление
Файл `site.yml` автоматически обновляется при добавлении новых ролей:
Файл `run.yml` автоматически обновляется при добавлении новых ролей:
```bash
# Автоматическое обновление

View File

@@ -136,7 +136,7 @@ make vault decrypt
├── files/
│ ├── requirements.yml
│ └── playbooks/
│ └── site.yml
│ └── run.yml
├── vault/
│ └── secrets.yml
└── Makefile

View File

@@ -13,9 +13,11 @@
vault_targets:
- /workspace/vault/secrets.yml
- /workspace/vault/secret.yml
- /workspace/files/playbooks/group_vars/*/vault.yml
- /workspace/files/playbooks/host_vars/*/vault.yml
- /workspace/roles/**/vars/vault.yml
# - /workspace/files/playbooks/group_vars/*/vault.yml
# - /workspace/files/playbooks/host_vars/*/vault.yml
# - /workspace/roles/**/vars/vault.yml
# - /workspace/roles/*/defaults/*.yml
# - /workspace/files/**/*secret*.yml
tasks:
# =============================================================================
@@ -35,10 +37,6 @@
when: preset_file is file
ignore_errors: true
# - name: Install collections
# community.docker.docker_container_exec:
# container: ansible-controller
# command: bash -lc "ansible-galaxy collection install -r /workspace/requirements.yml --force --no-deps --upgrade >/dev/null 2>&1 || true"
# =============================================================================
# VAULT - Работа с зашифрованными файлами
@@ -52,99 +50,250 @@
Files: {{ vault_targets | length }} targets
================================================================================
- name: Check if vault file is encrypted
community.docker.docker_container_exec:
container: ansible-controller
command: "bash -c 'if [ -f \"/workspace/vault/secrets.yml\" ]; then grep -q \"ANSIBLE_VAULT\" /workspace/vault/secrets.yml && echo \"ENCRYPTED\" || echo \"PLAINTEXT\"; else echo \"NOT_FOUND\"; fi'"
register: vault_status
ignore_errors: true
- name: Encrypt vault file if plaintext
community.docker.docker_container_exec:
container: ansible-controller
command: "bash -c 'VAULT_PASSWORD_FILE=\"/workspace/vault/.vault\"; if [ -f \"$VAULT_PASSWORD_FILE\" ] && [ -f \"/workspace/vault/secrets.yml\" ] && [ \"{{ vault_status.stdout }}\" = \"PLAINTEXT\" ]; then ansible-vault encrypt --encrypt-vault-id default --vault-password-file \"$VAULT_PASSWORD_FILE\" /workspace/vault/secrets.yml; fi'"
when: vault_status.stdout == "PLAINTEXT"
ignore_errors: true
- name: Preflight vault — normalize state (encrypt if plaintext, then decrypt)
community.docker.docker_container_exec:
container: ansible-controller
command: "bash -c 'VAULT_PASSWORD_FILE=\"/workspace/vault/.vault\"; if [ -f \"$VAULT_PASSWORD_FILE\" ] && [ -f \"/workspace/vault/secrets.yml\" ]; then ansible-vault decrypt --vault-password-file \"$VAULT_PASSWORD_FILE\" /workspace/vault/secrets.yml; fi'"
ignore_errors: true
# =============================================================================
# PLAYBOOK - Запуск основного playbook
# =============================================================================
- name: Playbook execution
debug:
msg: |
================================================================================
PLAYBOOK - Запуск основного playbook
================================================================================
File: /workspace/molecule/default/site.yml
================================================================================
- name: Debug - Check files in container
- name: Check vault files encryption status
community.docker.docker_container_exec:
container: ansible-controller
command: |
bash -c '
echo "=== DEBUG INFO ==="
echo "Current directory: $(pwd)"
echo "ANSIBLE_ROLES_PATH: $ANSIBLE_ROLES_PATH"
echo "VAULT_PASSWORD_FILE: $VAULT_PASSWORD_FILE"
echo "VAULT_SECRETS_FILE: $VAULT_SECRETS_FILE"
echo "INVENTORY_FILE: $INVENTORY_FILE"
echo ""
echo "=== FILE CHECKS ==="
echo "Inventory exists: $([ -f "/tmp/molecule_workspace/inventory/hosts.ini" ] && echo "YES" || echo "NO")"
echo "Vault password exists: $([ -f "/workspace/vault/.vault" ] && echo "YES" || echo "NO")"
echo "Vault secrets exists: $([ -f "/workspace/vault/secrets.yml" ] && echo "YES" || echo "NO")"
echo "Site.yml exists: $([ -f "/workspace/molecule/default/site.yml" ] && echo "YES" || echo "NO")"
echo ""
echo "=== DIRECTORY LISTING ==="
ls -la /tmp/molecule_workspace/ || echo "No molecule_workspace dir"
ls -la /workspace/vault/ || echo "No vault dir"
echo ""
echo "=== INVENTORY CONTENT ==="
cat /tmp/molecule_workspace/inventory/hosts.ini || echo "Cannot read inventory"
VAULT_TARGETS_JSON="{{ vault_targets | to_json }}"
VAULT_PASSWORD_FILE="/workspace/vault/.vault"
echo "=== CHECKING VAULT FILES ENCRYPTION STATUS ==="
# Парсим JSON массив и проверяем каждый файл
echo "$VAULT_TARGETS_JSON" | jq -r ".[]" | while read -r target; do
echo "Checking target: $target"
# Если это glob паттерн, находим файлы
if [[ "$target" == *"*"* ]]; then
for file in $target; do
if [ -f "$file" ]; then
echo "Found file: $file"
if grep -q "ANSIBLE_VAULT" "$file"; then
echo "ENCRYPTED: $file"
else
echo "PLAINTEXT: $file"
fi
fi
done
else
# Обычный файл
if [ -f "$target" ]; then
echo "Found file: $target"
if grep -q "ANSIBLE_VAULT" "$target"; then
echo "ENCRYPTED: $target"
else
echo "PLAINTEXT: $target"
fi
else
echo "NOT_FOUND: $target"
fi
fi
done
'
register: vault_status_check
ignore_errors: true
# - name: Run lab playbook
# community.docker.docker_container_exec:
# container: ansible-controller
# command: |
# bash -c '
# set -e
# export ANSIBLE_ROLES_PATH=/workspace/roles
# export VAULT_PASSWORD_FILE="/workspace/vault/.vault"
# export VAULT_SECRETS_FILE="/workspace/vault/secrets.yml"
# export INVENTORY_FILE="/tmp/molecule_workspace/inventory/hosts.ini"
# echo "Starting playbook execution..."
# if [ -f "$VAULT_PASSWORD_FILE" ] && [ -f "$VAULT_SECRETS_FILE" ]; then
# echo "Running with vault..."
# ansible-playbook -i "$INVENTORY_FILE" /workspace/molecule/default/site.yml --vault-password-file "$VAULT_PASSWORD_FILE" -e "vault_file_path=$VAULT_SECRETS_FILE" -v
# else
# echo "Running without vault..."
# ansible-playbook -i "$INVENTORY_FILE" /workspace/molecule/default/site.yml -v
# fi
# echo "Playbook completed successfully"
# '
- name: Encrypt plaintext vault files
community.docker.docker_container_exec:
container: ansible-controller
command: |
bash -c '
VAULT_TARGETS_JSON="{{ vault_targets | to_json }}"
VAULT_PASSWORD_FILE="/workspace/vault/.vault"
echo "=== ENCRYPTING PLAINTEXT VAULT FILES ==="
if [ ! -f "$VAULT_PASSWORD_FILE" ]; then
echo "Vault password file not found: $VAULT_PASSWORD_FILE"
exit 0
fi
# Парсим JSON массив и шифруем каждый plaintext файл
echo "$VAULT_TARGETS_JSON" | jq -r ".[]" | while read -r target; do
echo "Processing target: $target"
# Если это glob паттерн, находим файлы
if [[ "$target" == *"*"* ]]; then
for file in $target; do
if [ -f "$file" ] && ! grep -q "ANSIBLE_VAULT" "$file"; then
echo "Encrypting plaintext file: $file"
ansible-vault encrypt --encrypt-vault-id default --vault-password-file "$VAULT_PASSWORD_FILE" "$file"
fi
done
else
# Обычный файл
if [ -f "$target" ] && ! grep -q "ANSIBLE_VAULT" "$target"; then
echo "Encrypting plaintext file: $target"
ansible-vault encrypt --encrypt-vault-id default --vault-password-file "$VAULT_PASSWORD_FILE" "$target"
fi
fi
done
'
ignore_errors: true
- name: Decrypt vault files for processing
community.docker.docker_container_exec:
container: ansible-controller
command: |
bash -c '
VAULT_TARGETS_JSON="{{ vault_targets | to_json }}"
VAULT_PASSWORD_FILE="/workspace/vault/.vault"
echo "=== DECRYPTING VAULT FILES FOR PROCESSING ==="
if [ ! -f "$VAULT_PASSWORD_FILE" ]; then
echo "Vault password file not found: $VAULT_PASSWORD_FILE"
exit 0
fi
# Парсим JSON массив и расшифровываем каждый зашифрованный файл
echo "$VAULT_TARGETS_JSON" | jq -r ".[]" | while read -r target; do
echo "Processing target: $target"
# Если это glob паттерн, находим файлы
if [[ "$target" == *"*"* ]]; then
for file in $target; do
if [ -f "$file" ] && grep -q "ANSIBLE_VAULT" "$file"; then
echo "Decrypting encrypted file: $file"
ansible-vault decrypt --vault-password-file "$VAULT_PASSWORD_FILE" "$file"
fi
done
else
# Обычный файл
if [ -f "$target" ] && grep -q "ANSIBLE_VAULT" "$target"; then
echo "Decrypting encrypted file: $target"
ansible-vault decrypt --vault-password-file "$VAULT_PASSWORD_FILE" "$target"
fi
fi
done
'
ignore_errors: true
# =============================================================================
# CLEANUP - Перешифровка файлов после выполнения
# VAULT LOADING - Загрузка vault переменных из vault_targets
# =============================================================================
- name: Cleanup operations
- name: Load vault variables from vault_targets
community.docker.docker_container_exec:
container: ansible-controller
command: |
bash -c '
VAULT_PASSWORD_FILE="/workspace/vault/.vault"
# Читаем vault_targets из переменных Ansible
VAULT_TARGETS_JSON="{{ vault_targets | to_json }}"
echo "=== VAULT LOADING ==="
echo "Vault password file: $VAULT_PASSWORD_FILE"
echo "Vault targets from Ansible: $VAULT_TARGETS_JSON"
# Создаем директории для vault файлов
mkdir -p /tmp/vault_files
# Создаем временный файл для объединения всех vault переменных
echo "---" > /tmp/vault_vars.yml
# Счетчик для обработки конфликтов
declare -A variable_sources
# Парсим JSON массив и обрабатываем каждый target
echo "$VAULT_TARGETS_JSON" | jq -r ".[]" | while read -r target; do
echo "Processing target: $target"
# Если это glob паттерн, находим файлы
if [[ "$target" == *"*"* ]]; then
for file in $target; do
if [ -f "$file" ]; then
echo "Found vault file: $file"
# Создаем копию файла в /tmp/vault_files для прямых ссылок
filename=$(basename "$file")
cp "$file" "/tmp/vault_files/$filename"
# Расшифровываем файл если нужно
if [ -f "$VAULT_PASSWORD_FILE" ]; then
echo "Loading encrypted vault file: $file"
ansible-vault view --vault-password-file "$VAULT_PASSWORD_FILE" "$file" > "/tmp/vault_files/${filename}.decrypted"
# Добавляем в объединенный файл с проверкой конфликтов
echo "---" >> /tmp/vault_vars.yml
echo "# From: $file" >> /tmp/vault_vars.yml
ansible-vault view --vault-password-file "$VAULT_PASSWORD_FILE" "$file" >> /tmp/vault_vars.yml
else
echo "Loading plain vault file: $file"
cp "$file" "/tmp/vault_files/${filename}.decrypted"
# Добавляем в объединенный файл с проверкой конфликтов
echo "---" >> /tmp/vault_vars.yml
echo "# From: $file" >> /tmp/vault_vars.yml
cat "$file" >> /tmp/vault_vars.yml
fi
fi
done
else
# Обычный файл
if [ -f "$target" ]; then
echo "Found vault file: $target"
# Создаем копию файла в /tmp/vault_files для прямых ссылок
filename=$(basename "$target")
cp "$target" "/tmp/vault_files/$filename"
# Расшифровываем файл если нужно
if [ -f "$VAULT_PASSWORD_FILE" ]; then
echo "Loading encrypted vault file: $target"
ansible-vault view --vault-password-file "$VAULT_PASSWORD_FILE" "$target" > "/tmp/vault_files/${filename}.decrypted"
# Добавляем в объединенный файл с проверкой конфликтов
echo "---" >> /tmp/vault_vars.yml
echo "# From: $target" >> /tmp/vault_vars.yml
ansible-vault view --vault-password-file "$VAULT_PASSWORD_FILE" "$target" >> /tmp/vault_vars.yml
else
echo "Loading plain vault file: $target"
cp "$target" "/tmp/vault_files/${filename}.decrypted"
# Добавляем в объединенный файл с проверкой конфликтов
echo "---" >> /tmp/vault_vars.yml
echo "# From: $target" >> /tmp/vault_vars.yml
cat "$target" >> /tmp/vault_vars.yml
fi
fi
fi
done
# Символические ссылки не нужны для работы, убираем их создание
echo "=== VAULT VARIABLES LOADED ==="
echo "Combined vault variables:"
cat /tmp/vault_vars.yml
echo ""
echo "Individual vault files available at:"
ls -la /tmp/vault_files/
'
ignore_errors: true
# =============================================================================
# LOAD VAULT VARIABLES - Загрузка vault переменных в Ansible
# =============================================================================
- name: Load vault variables into Ansible
include_vars:
file: /tmp/vault_vars.yml
ignore_errors: true
- name: Set vault files path
set_fact:
vault_files_path: /tmp/vault_files
when: vault_files_path is not defined
# =============================================================================
# CONVERGE ЗАВЕРШЕН - Playbook'и выполняются через Makefile
# =============================================================================
- name: Converge completed
debug:
msg: |
================================================================================
CLEANUP - Перешифровка файлов после выполнения
CONVERGE ЗАВЕРШЕН
================================================================================
Re-encrypting vault files
================================================================================
- name: Post-run — re-encrypt secrets
community.docker.docker_container_exec:
container: ansible-controller
command: "bash -c 'VAULT_PASSWORD_FILE=\"/workspace/vault/.vault\"; if [ -f \"$VAULT_PASSWORD_FILE\" ] && [ -f \"/workspace/vault/secrets.yml\" ]; then ansible-vault encrypt --encrypt-vault-id default --vault-password-file \"$VAULT_PASSWORD_FILE\" /workspace/vault/secrets.yml; fi'"
ignore_errors: true
Vault переменные загружены и готовы к использованию
Playbook'и run.yml и roles/deploy.yml будут выполнены через Makefile
================================================================================

View File

@@ -156,7 +156,7 @@
- name: "{{ docker_network }}"
privileged: "{{ systemd_defaults.privileged }}"
command: "{{ '/bin/bash -c \"while true; do sleep 30; done\"' if item.family in ['alt10', 'alt9'] else systemd_defaults.command }}"
volumes: "{{ systemd_defaults.volumes | default([]) + (item.volumes | default([])) }}"
volumes: "{{ systemd_defaults.volumes | default([]) + (item.volumes | default([])) + ['/Users/inecs/PycharmProjects/DevOpsLab/vault:/workspace/vault:ro', '/Users/inecs/PycharmProjects/DevOpsLab/files:/workspace/files:ro', '/Users/inecs/PycharmProjects/DevOpsLab/roles:/workspace/roles:ro'] }}"
tmpfs: "{{ systemd_defaults.tmpfs | default([]) }}"
capabilities: "{{ systemd_defaults.capabilities | default([]) }}"
published_ports: "{{ item.publish | default([]) }}"
@@ -188,77 +188,8 @@
delay: 5
until: container_info.container.State.Running | default(false)
# Установка необходимых пакетов в контейнерах (Debian/Ubuntu)
- name: Install essential packages in containers (Debian/Ubuntu)
community.docker.docker_container_exec:
container: "{{ item.name }}"
command: "sh -c 'apt-get update && apt-get install -y sudo python3 python3-pip curl wget'"
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control: { label: "{{ item.name }}" }
when: item.family is defined and images[item.family] is defined and item.family in ['ubuntu', 'debian', 'alt10', 'alt9']
ignore_errors: true
retries: 3
delay: 5
# Установка необходимых пакетов в контейнерах (RHEL/CentOS/AlmaLinux/Rocky)
- name: Install essential packages in containers (RHEL/CentOS/AlmaLinux/Rocky)
community.docker.docker_container_exec:
container: "{{ item.name }}"
command: "sh -c 'yum update -y && yum install -y sudo python3 python3-pip curl wget'"
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control: { label: "{{ item.name }}" }
when: item.family is defined and images[item.family] is defined and item.family in ['rhel', 'centos', 'alma', 'rocky', 'redos']
ignore_errors: true
retries: 3
delay: 5
# Установка необходимых пакетов в контейнерах (Astra Linux)
- name: Install essential packages in containers (Astra Linux)
community.docker.docker_container_exec:
container: "{{ item.name }}"
command: "sh -c 'apt-get update && apt-get install -y sudo python3 python3-pip curl wget'"
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control: { label: "{{ item.name }}" }
when: item.family is defined and images[item.family] is defined and item.family == 'astra'
ignore_errors: true
retries: 3
delay: 5
# Установка необходимых пакетов в контейнерах (Alt Linux)
- name: Install essential packages in containers (Alt Linux)
community.docker.docker_container_exec:
container: "{{ item.name }}"
command: "sh -c 'apt-get update && apt-get install -y sudo python3 python3-pip curl wget'"
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control: { label: "{{ item.name }}" }
when: item.family is defined and images[item.family] is defined and item.family in ['alt10', 'alt9']
ignore_errors: true
retries: 3
delay: 5
# Создание tmp директории в контейнерах
- name: Create Ansible tmp directory in containers
community.docker.docker_container_exec:
container: "{{ item.name }}"
command: "mkdir -p /tmp/.ansible-tmp && chmod 755 /tmp/.ansible-tmp"
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control: { label: "{{ item.name }}" }
when: item.family is defined and images[item.family] is defined
ignore_errors: true
retries: 5
delay: 3
# Создание vault директории в контейнерах
- name: Create vault directory in containers
community.docker.docker_container_exec:
container: "{{ item.name }}"
command: "mkdir -p /workspace/vault && chmod 755 /workspace/vault"
loop: "{{ hosts | selectattr('type','undefined') | list }}"
loop_control: { label: "{{ item.name }}" }
when: item.family is defined and images[item.family] is defined
ignore_errors: true
retries: 5
delay: 3
# Примечание: Установка пакетов и создание директорий перенесены в run.yml
# для выполнения на всех поднятых контейнерах
# =============================================================================
# DIND NODES - Создание контейнеров Docker-in-Docker
@@ -308,7 +239,7 @@
- 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([])) }}"
volumes: "{{ (systemd_defaults.volumes | default([])) + ['/var/run/docker.sock:/var/run/docker.sock'] + (item.volumes | default([])) + ['/Users/inecs/PycharmProjects/DevOpsLab/vault:/workspace/vault:ro', '/Users/inecs/PycharmProjects/DevOpsLab/files:/workspace/files:ro', '/Users/inecs/PycharmProjects/DevOpsLab/roles:/workspace/roles:ro'] }}"
tmpfs: "{{ systemd_defaults.tmpfs | default([]) }}"
capabilities: "{{ systemd_defaults.capabilities | default([]) }}"
published_ports: "{{ item.publish | default([]) }}"

View File

@@ -17,6 +17,11 @@
family: debian
groups: [test]
kind_clusters: []
# перечисли файлы/глобы, которые нужно временно расшифровать
vault_targets:
- /workspace/vault/secrets.yml
- /workspace/vault/secret.yml
tasks:
# =============================================================================
@@ -36,6 +41,63 @@
when: preset_file is file
ignore_errors: true
# =============================================================================
# VAULT CLEANUP - Перешифровка файлов перед удалением контейнеров
# =============================================================================
- name: Vault cleanup operations
debug:
msg: |
================================================================================
VAULT CLEANUP - Перешифровка файлов перед удалением контейнеров
================================================================================
Re-encrypting vault files
================================================================================
- name: Re-encrypt all vault files
community.docker.docker_container_exec:
container: ansible-controller
command: |
bash -c '
VAULT_TARGETS_JSON="{{ vault_targets | to_json }}"
VAULT_PASSWORD_FILE="/workspace/vault/.vault"
echo "=== RE-ENCRYPTING ALL VAULT FILES ==="
if [ ! -f "$VAULT_PASSWORD_FILE" ]; then
echo "Vault password file not found: $VAULT_PASSWORD_FILE"
exit 0
fi
# Парсим JSON массив и перешифровываем каждый файл
echo "$VAULT_TARGETS_JSON" | jq -r ".[]" | while read -r target; do
echo "Processing target: $target"
# Если это glob паттерн, находим файлы
if [[ "$target" == *"*"* ]]; then
for file in $target; do
if [ -f "$file" ] && ! grep -q "ANSIBLE_VAULT" "$file"; then
echo "Re-encrypting file: $file"
ansible-vault encrypt --encrypt-vault-id default --vault-password-file "$VAULT_PASSWORD_FILE" "$file"
fi
done
else
# Обычный файл
if [ -f "$target" ] && ! grep -q "ANSIBLE_VAULT" "$target"; then
echo "Re-encrypting file: $target"
ansible-vault encrypt --encrypt-vault-id default --vault-password-file "$VAULT_PASSWORD_FILE" "$target"
fi
fi
done
echo "All vault files re-encrypted successfully"
# Очистка символических ссылок в vault/
echo "Cleaning up vault symlinks..."
rm -f /workspace/vault/*.decrypted
echo "Vault symlinks cleaned up"
'
ignore_errors: true
# =============================================================================
# УДАЛЕНИЕ КОНТЕЙНЕРОВ - Остановка и удаление контейнеров
# =============================================================================
@@ -114,6 +176,18 @@
vars:
# Используем переменную hosts из загруженного пресета
hosts: "{{ hosts }}"
# =============================================================================
# ДОПОЛНИТЕЛЬНАЯ ОЧИСТКА - Удаление симлинков vault
# =============================================================================
- name: Clean up vault symlinks
file:
path: "{{ item }}"
state: absent
loop:
- /workspace/vault/secrets.yml.decrypted
- /workspace/vault/secret.yml.decrypted
ignore_errors: true
- name: Display cleanup summary
debug:
msg: |

View File

@@ -24,6 +24,18 @@
tags:
- setup
- color-reset
# Отладочная информация о vault переменных (передаются из converge.yml)
- name: Проверка vault переменных
debug:
msg: |
Vault переменные на {{ ansible_hostname }}:
- vault_devops_password: {{ vault_devops_password | default('НЕ ОПРЕДЕЛЕНА') | length }} символов
- vault_devops_ssh_public_key: {{ vault_devops_ssh_public_key | default('НЕ ОПРЕДЕЛЕНА') | length }} символов
tags:
- setup
- vault
- debug
# Создание tmp директории для Ansible
- name: Create Ansible tmp directory
file:
@@ -35,6 +47,18 @@
tags:
- setup
- tmp
# Создание vault директории
- name: Create vault directory
file:
path: /workspace/vault
state: directory
mode: '0755'
owner: root
group: root
tags:
- setup
- vault
# Обновление кеша пакетов для Debian/Ubuntu
- name: Update package cache (Debian/Ubuntu)
apt:
@@ -76,65 +100,67 @@
- setup
- update
# Установка common tools для всех ОС (ЗАКОММЕНТИРОВАНО)
# - name: Install common tools (Debian/Ubuntu)
# apt:
# name:
# - curl
# - jq
# - ca-certificates
# - iproute2
# - iputils-ping
# - procps
# - net-tools
# - vim
# - wget
# - unzip
# - git
# state: present
# update_cache: false
# when: ansible_os_family == 'Debian'
# tags:
# - setup
# - tools
# Установка common tools для всех ОС
- name: Install common tools (Debian/Ubuntu)
apt:
name:
- curl
- jq
- ca-certificates
- iproute2
- iputils-ping
- procps
- net-tools
- vim
- wget
- unzip
- git
- sudo
state: present
update_cache: false
when: ansible_os_family == 'Debian'
tags:
- setup
- tools
# - name: Install common tools (RHEL/CentOS/AlmaLinux/Rocky)
# yum:
# name:
# - curl
# - jq
# - ca-certificates
# - iproute
# - iputils
# - procps-ng
# - net-tools
# - vim
# - wget
# - unzip
# - git
# state: present
# when: ansible_os_family == 'RedHat'
# tags:
# - setup
# - tools
- name: Install common tools (RHEL/CentOS/AlmaLinux/Rocky)
yum:
name:
- curl
- jq
- ca-certificates
- iproute
- iputils
- procps-ng
- net-tools
- vim
- wget
- unzip
- git
- sudo
state: present
when: ansible_os_family == 'RedHat'
tags:
- setup
- tools
# - name: Install common tools (Alt Linux)
# command: apt-get install -y curl jq ca-certificates iproute2 iputils procps net-tools vim wget unzip git
# when: ansible_os_family == 'Altlinux'
# changed_when: false
# failed_when: false
# tags:
# - setup
# - tools
- name: Install common tools (Alt Linux)
command: apt-get install -y curl jq ca-certificates iproute2 iputils procps net-tools vim wget unzip git sudo
when: ansible_os_family == 'Altlinux'
changed_when: false
failed_when: false
tags:
- setup
- tools
# - name: Install common tools (Astra Linux)
# command: apt-get install -y curl jq ca-certificates iproute2 iputils procps net-tools vim wget unzip git
# when: ansible_os_family == 'Astra Linux'
# changed_when: false
# failed_when: false
# tags:
# - setup
# - tools
- name: Install common tools (Astra Linux)
command: apt-get install -y curl jq ca-certificates iproute2 iputils procps net-tools vim wget unzip git sudo
when: ansible_os_family == 'Astra Linux'
changed_when: false
failed_when: false
tags:
- setup
- tools
# Установка Python для Ansible (если не установлен)
- name: Install Python (Debian/Ubuntu)
@@ -149,18 +175,6 @@
- setup
- python
# Установка Python 3.8+ для RHEL/CentOS/Rocky/AlmaLinux
- name: Install Python 3.8+ (RHEL/CentOS/Rocky/AlmaLinux)
yum:
name:
- python3
- python3-pip
state: present
when: ansible_os_family == 'RedHat'
tags:
- setup
- python
- name: Install Python (RHEL/CentOS/AlmaLinux/Rocky)
yum:
name:
@@ -224,4 +238,3 @@
# - setup
# - directory
- import_playbook: ../../roles/deploy.yml

View File

@@ -15,17 +15,17 @@
tags:
- color-reset
#- name: Установка роли devops
# hosts: all
# become: true
# roles:
# - devops
- name: Установка роли python
- name: Установка роли devops
hosts: all
become: true
roles:
- python
- devops
#- name: Установка роли python
# hosts: all
# become: true
# roles:
# - python
#- name: Установка роли docker
# hosts: all

View File

@@ -149,16 +149,16 @@
```bash
# Только создание пользователя и группы
ansible-playbook -i inventory site.yml --tags "user,group"
ansible-playbook -i inventory run.yml --tags "user,group"
# Только настройка SSH
ansible-playbook -i inventory site.yml --tags "ssh,keys"
ansible-playbook -i inventory run.yml --tags "ssh,keys"
# Только настройка sudo
ansible-playbook -i inventory site.yml --tags "sudo,permissions"
ansible-playbook -i inventory run.yml --tags "sudo,permissions"
# Пропустить проверки
ansible-playbook -i inventory site.yml --skip-tags "verification"
ansible-playbook -i inventory run.yml --skip-tags "verification"
```
## Обработчики

View File

@@ -9,11 +9,11 @@ devops_group: "devops"
devops_home: "/home/{{ devops_user }}"
devops_shell: "/bin/bash"
# Настройки пароля (берется из vault/secrets.yml)
devops_password: "{{ vault_devops_password | default('') }}"
# Настройки пароля (обязательно из vault/secrets.yml)
devops_password: "{{ vault_devops_password }}"
# Настройки SSH ключа (берется из vault/secrets.yml)
devops_ssh_public_key: "{{ vault_devops_ssh_public_key | default('') }}"
# Настройки SSH ключа (обязательно из vault/secrets.yml)
devops_ssh_public_key: "{{ vault_devops_ssh_public_key }}"
# Настройки sudo
devops_sudo_nopasswd: true

View File

@@ -12,25 +12,67 @@
- name: "🔍 Проверка входных параметров"
tags: [devops, validation]
block:
- name: "Установка значений по умолчанию для тестирования"
set_fact:
devops_password: "{{ vault_devops_password | default('123123') }}"
devops_ssh_public_key: "{{ vault_devops_ssh_public_key | default('ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7vbqajDhA... devops@devops.org.ru') }}"
when: devops_password == "" or devops_ssh_public_key == ""
- name: "Проверка наличия пароля пользователя devops"
fail:
msg: "Пароль пользователя devops не найден в vault/secrets.yml. Установите переменную vault_devops_password."
when:
- vault_file_path is defined
- devops_password == ""
msg: |
❌ ОШИБКА: Пароль пользователя devops не найден в vault/secrets.yml!
Для корректной работы роли необходимо установить переменную vault_devops_password в файле vault/secrets.yml.
Пример содержимого vault/secrets.yml:
vault_devops_password: "ваш_пароль_здесь"
vault_devops_ssh_public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7vbqajDhA... devops@devops.org.ru"
Для шифрования файла используйте:
ansible-vault encrypt vault/secrets.yml
when:
- vault_devops_password is not defined
- vault_devops_password == ""
- vault_devops_password is none
- name: "Проверка наличия SSH публичного ключа"
fail:
msg: "SSH публичный ключ не найден в vault/secrets.yml. Установите переменную vault_devops_ssh_public_key."
when:
- vault_file_path is defined
- devops_ssh_public_key == ""
msg: |
❌ ОШИБКА: SSH публичный ключ не найден в vault/secrets.yml!
Для корректной работы роли необходимо установить переменную vault_devops_ssh_public_key в файле vault/secrets.yml.
Пример содержимого vault/secrets.yml:
vault_devops_password: "ваш_пароль_здесь"
vault_devops_ssh_public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7vbqajDhA... devops@devops.org.ru"
Для шифрования файла используйте:
ansible-vault encrypt vault/secrets.yml
when:
- vault_devops_ssh_public_key is not defined
- vault_devops_ssh_public_key == ""
- vault_devops_ssh_public_key is none
- name: "✅ Проверка успешна - все необходимые секреты найдены"
debug:
msg: |
Все необходимые секреты найдены в vault/secrets.yml:
- Пароль пользователя: {{ 'установлен' if vault_devops_password is defined and vault_devops_password != '' else 'НЕ УСТАНОВЛЕН' }}
- SSH публичный ключ: {{ 'установлен' if vault_devops_ssh_public_key is defined and vault_devops_ssh_public_key != '' else 'НЕ УСТАНОВЛЕН' }}
when:
- vault_devops_password is defined
- vault_devops_password != ""
- vault_devops_ssh_public_key is defined
- vault_devops_ssh_public_key != ""
- name: "🔍 Проверка что пароль не пустой"
fail:
msg: "❌ ОШИБКА: Пароль пользователя devops не может быть пустым!"
when:
- vault_devops_password is defined
- vault_devops_password == ""
- name: "🔍 Проверка что SSH ключ не пустой"
fail:
msg: "❌ ОШИБКА: SSH публичный ключ не может быть пустым!"
when:
- vault_devops_ssh_public_key is defined
- vault_devops_ssh_public_key == ""
- name: "Логирование начала выполнения роли"
debug:
@@ -51,12 +93,6 @@
name: "{{ devops_packages_to_install }}"
state: present
become: true
register: package_install_result
- name: "Логирование установки пакетов"
debug:
msg: "Установлены пакеты: {{ package_install_result.changed_packages | default('нет изменений') }}"
when: false
- name: "👤 Создание группы devops"
tags: [devops, group]

View File

@@ -235,6 +235,7 @@ devops_system_checks:
path: "{{ devops_sudoers_file }}"
register: "devops_sudoers_check"
# Настройки для логирования
devops_log_config:
level: "{{ devops_log_level }}"

View File

@@ -1,243 +0,0 @@
#!/bin/bash
# Скрипт для тестирования собственных образов DevOpsLab
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru
set -e
# Цвета для вывода
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Функция для вывода сообщений
log() {
echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}
success() {
echo -e "${GREEN}$1${NC}"
}
warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
error() {
echo -e "${RED}$1${NC}"
}
# Проверка наличия Docker
check_docker() {
log "Проверка Docker..."
if ! command -v docker &> /dev/null; then
error "Docker не установлен!"
exit 1
fi
success "Docker доступен"
}
# Проверка наличия образов
check_images() {
log "Проверка наличия собственных образов..."
local images=(
"inecs/ansible-lab:ansible-controller-latest"
"inecs/ansible-lab:alt9-latest"
"inecs/ansible-lab:astra-linux-latest"
"inecs/ansible-lab:redos-latest"
"inecs/ansible-lab:rhel-latest"
"inecs/ansible-lab:centos-latest"
"inecs/ansible-lab:alma-latest"
"inecs/ansible-lab:rocky-latest"
"inecs/ansible-lab:ubuntu-latest"
"inecs/ansible-lab:debian-latest"
)
local missing_images=()
for image in "${images[@]}"; do
if ! docker image inspect "$image" &> /dev/null; then
missing_images+=("$image")
else
success "Образ $image найден"
fi
done
if [ ${#missing_images[@]} -gt 0 ]; then
warning "Отсутствующие образы:"
for image in "${missing_images[@]}"; do
echo " - $image"
done
echo ""
echo "Для сборки образов выполните:"
echo " make docker build"
echo ""
echo "Или соберите отдельные образы:"
for image in "${missing_images[@]}"; do
# Маппинг образов на имена для сборки
case "$image" in
"inecs/ansible-lab:ansible-controller-latest")
echo " make docker build-image IMAGE=ansible-controller"
;;
"inecs/ansible-lab:alt9-latest")
echo " make docker build-image IMAGE=alt9"
;;
"inecs/ansible-lab:astra-linux-latest")
echo " make docker build-image IMAGE=astra-linux"
;;
"inecs/ansible-lab:redos-latest")
echo " make docker build-image IMAGE=redos"
;;
"inecs/ansible-lab:rhel-latest")
echo " make docker build-image IMAGE=rhel"
;;
"inecs/ansible-lab:centos-latest")
echo " make docker build-image IMAGE=centos"
;;
"inecs/ansible-lab:alma-latest")
echo " make docker build-image IMAGE=alma"
;;
"inecs/ansible-lab:rocky-latest")
echo " make docker build-image IMAGE=rocky"
;;
"inecs/ansible-lab:ubuntu-latest")
echo " make docker build-image IMAGE=ubuntu"
;;
"inecs/ansible-lab:debian-latest")
echo " make docker build-image IMAGE=debian"
;;
*)
echo " # Неизвестный образ: $image"
;;
esac
done
return 1
fi
success "Все образы найдены"
return 0
}
# Тестирование с минимальным пресетом
test_minimal() {
log "Тестирование с минимальным пресетом (custom-minimal)..."
if [ -f "molecule/presets/custom-minimal.yml" ]; then
log "Запуск molecule test с пресетом custom-minimal..."
if molecule test --scenario-name custom-minimal; then
success "Тест с custom-minimal прошел успешно"
else
error "Тест с custom-minimal завершился с ошибкой"
return 1
fi
else
error "Файл molecule/presets/custom-minimal.yml не найден"
return 1
fi
}
# Тестирование с полным пресетом
test_full() {
log "Тестирование с полным пресетом (custom-images)..."
if [ -f "molecule/presets/custom-images.yml" ]; then
log "Запуск molecule test с пресетом custom-images..."
if molecule test --scenario-name custom-images; then
success "Тест с custom-images прошел успешно"
else
error "Тест с custom-images завершился с ошибкой"
return 1
fi
else
error "Файл molecule/presets/custom-images.yml не найден"
return 1
fi
}
# Тестирование производительности
test_performance() {
log "Тестирование производительности (custom-performance)..."
if [ -f "molecule/presets/custom-performance.yml" ]; then
log "Запуск molecule test с пресетом custom-performance..."
if molecule test --scenario-name custom-performance; then
success "Тест производительности прошел успешно"
else
error "Тест производительности завершился с ошибкой"
return 1
fi
else
error "Файл molecule/presets/custom-performance.yml не найден"
return 1
fi
}
# Очистка после тестов
cleanup() {
log "Очистка после тестов..."
# Остановка и удаление контейнеров
docker ps -a --filter "name=molecule" --format "{{.Names}}" | xargs -r docker rm -f 2>/dev/null || true
# Удаление сетей
docker network ls --filter "name=ansible-lab" --format "{{.Name}}" | xargs -r docker network rm 2>/dev/null || true
success "Очистка завершена"
}
# Основная функция
main() {
log "🚀 Тестирование собственных образов DevOpsLab"
echo "=========================================="
# Проверки
check_docker
if ! check_images; then
error "Не все образы найдены. Завершение."
exit 1
fi
# Выбор типа тестирования
case "${1:-minimal}" in
"check")
success "Проверка образов завершена"
;;
"minimal")
test_minimal
;;
"full")
test_full
;;
"performance")
test_performance
;;
"all")
test_minimal && test_full && test_performance
;;
*)
echo "Использование: $0 [check|minimal|full|performance|all]"
echo ""
echo " check - проверка наличия образов"
echo " minimal - минимальный тест (4 хоста)"
echo " full - полный тест (все образы)"
echo " performance - тест производительности (8 хостов)"
echo " all - все тесты"
exit 1
;;
esac
# Очистка
cleanup
success "🎉 Тестирование завершено успешно!"
}
# Обработка сигналов
trap cleanup EXIT INT TERM
# Запуск
main "$@"

View File

@@ -12,10 +12,10 @@ ROLES=$(find roles/ -name 'main.yml' -path '*/tasks/*' | sed 's|roles/||; s|/tas
echo "📋 Найденные роли: $ROLES"
# Обновляем molecule/default/site.yml (только если файл не существует)
if [ ! -f "molecule/default/site.yml" ]; then
echo "📝 Создание molecule/default/site.yml..."
cat > molecule/default/site.yml << 'EOF'
# Обновляем molecule/default/run.yml (только если файл не существует)
if [ ! -f "molecule/default/run.yml" ]; then
echo "📝 Создание molecule/default/run.yml..."
cat > molecule/default/run.yml << 'EOF'
---
# Универсальный playbook для тестирования Ansible ролей
# Автор: Сергей Антропов
@@ -199,7 +199,7 @@ if [ ! -f "molecule/default/site.yml" ]; then
- import_playbook: ../../roles/deploy.yml
EOF
else
echo "📝 Файл molecule/default/site.yml уже существует, пропускаем создание"
echo "📝 Файл molecule/default/run.yml уже существует, пропускаем создание"
fi
# Обновляем roles/deploy.yml

View File

@@ -1,51 +1,51 @@
$ANSIBLE_VAULT;1.1;AES256
34663739653463366234613631353064393733363234323430333465393362666165373562303565
3037663539383033313563623635393536366438316433320a623361306663373332326165326633
37336136343965616234663462333165363965323362326266373566303238303033663336333331
3435343232613563630a626639343461613239643532663138303630373739623836326238646236
35346264346231353364363065393266623934323964363163623964643162306461633431616233
62663339353134616130623862383332343037363739366237383638373638366363306231663635
35373638346338386366636235616366323433636164333434313831613465343335366237366131
65626562373532623263373430383531313631613638643466636661613763316465313833643030
66346130393131383037386464353239663232636561666638333937346236613438616265313363
65373766363866386466613035373266663235656537336431643931373131333435383761663937
33626230343833656162623263363230383362393233393166346661303162353762613433376663
61346236666338646534656138363030313562346465346563613266653930623532353765326234
38373562613438653364323465363337363066313638373232643439386137623136313066306362
39386437353233366563613962653837383664343462666537323335373839383334346364306361
64366362396333643830313766373330613832323739306530333664333737343239393964643831
34373736663132383134343334353234633061303335363364333339386331663962363334316231
30663438376632326334383231363737333534633939316363366436633266323665363062343431
37616137393932626433623962636537376238326466326136396532636666643234323639316235
36306137656431626162343231616530663637323835346139323734393066623039396466346264
62656161366663303838383661623966373265393130616431663331636234626231343632333831
62313037336261313939636636626133656136366161346439663530373530383338393764366239
63626634303866636636636366323539326534363461306333663638613261313164373961633866
33656632633465663431643938313035303366376536343434333231353932303065306662393933
37643134306535303036363130356435633039616637653363303164376335393665386334353664
64366562353933633063353166666636333563613562386632616163376166626462393261376438
37306131666232633330656464613133313032303333623735326439616166323765393766393036
63336538336166633534643063353864636131353232393433313961333234386337616139613133
65303666393431623031373966396632333536613664363239616236623338306336313331313062
36346338326161653664646537656538626535613561353739396134323537666563386136343238
66396666323234316237656137306666376439633261376233366234323834383963313138666366
31653238303633353164636263643934326466636664386265383762323138333466323332643732
62313462316431383061663166363834666234386163393030643265336333316232626561353031
61353639333435303237666232643830336530353735656137333338643730343835346264306265
61373662623863323430656166376338306463373835333661353466653261633636383764363366
38323835666531633233326264323330616139313431353763343061393661333038363864383863
62323239316135643231626661663237636466653763636433613039633661386531343161613838
64383834663530636530363133396431383738636638333661636239643264623365353564653964
64376131323239663633303662333438636431313262316639363531323930396238646665343262
38393764643062343531326365393536653862653735393035623465386134633163323635356530
38303365376561666133663639376234323363356264336566666565383933373330356562643063
34663832613339376232663561323261653937333339313862613164656436323239623239613664
66383131613434366133663833663734313437376461663530366166323361643566393835626334
35383437376663326232336630386662386435663933303635616431376463333461316262666663
63393330656665356138613663333565616230366338396361333265396562306438613263363035
63626662396131623431353462376364656265373363383737303034363336313330656663626161
33396161373730303239623338323564386139333838393661323466363035616635663765316238
61636563356665616435653064316334633530643731366239383530346532336366666230613730
38613566346131303863663463656534306530383364383031653964333939353536633262636635
37643662323333356639663363636430626361343830663261623234343161643733633130613534
3039653530613936353962373738396265656264636263656333
35646637393562393632386237323463396437383465313133653161646465393066623139613931
3731306562663437326132393337313232373935613636320a393162333031623336383230353934
33323166643666323037353261663264663665333062306138346234353839383439323964643137
3762616565326465330a663932393563656532316430356266303761333230626133333363336234
63373562326330373737373265613438653135393039303665333236303533643365356464306436
38376531313765336266353037666665623535313162353061366463643964343966333035646236
64363833326266376162306132363330396565306264316233663665376630643563333234346433
39663735303837383339613732333865633333373465656164623235313938373039643636636537
35356164313534323662333062383536323961313837353632663666346537633530326566373632
35346266336536396363303262326362346436336564613635376566643235373638373636383164
64396137383231363637653235333066366462666335316433363363656337353632333665313866
38313837356538633465653539316563393965373163323166633737623963666531323532303037
39336330363338623134326163313034656265623539656565316361656437653463366165373137
32383735323430313531663139613165303865633435373664633866656631353763613338303934
34613461663665643965303833636131346462613236616162393861633465313866363831313332
65336335663735666634396135383038343436336138636137313135383961306461323831366233
66643766316339626639623036623835336361336231646161616437643733363636656433633130
32306537366462633030313036333331613066376235613835636236636564663164346263376161
39343837613134663537373461323239616236656633613637396261386335613437396164653664
38346564646432396634343430636664346435396138326236613133323930613531643730396231
34386166303031303239356565323566376565653139393265656463356631303831306136333865
36623732643463303264653735636664663130373233336162633533653338343735313932626562
64366233346237313230636263666561636462636139656461333432333036653036666132623932
65623033636333336533623437396539383932633438346132633339363532323536316338626339
38326237306661666637613064613435613931383265653761303734663832616434336430393535
33663335343937633135326530386164316631626162353138323132376538383437353862363137
38393638643066643335396566633239373338373531646334323831653832326532323464653834
39666264623033356635646433343631366335643764323465323737396262323932623634613635
65316536356662306533663839623133383263363630373766666464663063323035323834636539
63666137313935373366326565393830353837396463363330383534373331363539386463316266
35363734353262313366376530303231306133623465373133616139613031363230333432343265
38313637303336343238376466383737646135653964346564363432666462373665383662656534
34333234346133356430306232313430613739663464656336623739333330353961393866326634
62623633343439366133643534393237616138383235656237343836646464303130633637663430
33356631633363363535663139323330633533353465323234323238386132643032626664326431
34663862363830393465333662376563373932356363303432383461653464366633623538346263
32393431333931333963343363653935333662326632373463356566316537383739363064343862
37633466656364376332336434633266346465656261303736363864366237663535313566313334
34313734303137323163636636386238306335323561653166393335316563326661646566353662
39383861643264363366393434633236613564353232393631393266386463613433376561383763
30303262666630663138306237613939356138613330613431386236646338366434346330363736
62386535376164326566346365313133616265643035643861613635333730613438636430393565
66643864653634303139353434336564376562613933346138393534646532663763633363626535
38336532303338656134363665323030623064626261376237626265656332343036336638313733
35386438383561393636383536326262343931343530366339613332323066386366616165303033
64306139616432323837623466393738323865306135393064626665326139626439313332636132
63616664613732366338656236313439326336633930303133333330313761633132326362616537
62666634343937613136633962383331666361353036663839633733623533623466383432313462
34393733636432343365363862393663653163353534633136333661363363313139393330373930
6163336530313937363666636633313066333931336138643164