- Добавлена колонка 'Тип' во все таблицы истории сборок - Для push операций отображается registry вместо платформ - Сохранение пользователя при создании push лога - Исправлена ошибка с logger в push_docker_image endpoint - Улучшено отображение истории сборок с визуальными индикаторами
197 lines
7.0 KiB
HTML
197 lines
7.0 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Inventory - DevOpsLab{% endblock %}
|
||
{% block page_title %}Управление Inventory{% endblock %}
|
||
|
||
{% block header_actions %}
|
||
<a href="/deploy" class="btn btn-secondary btn-sm">
|
||
<i class="fas fa-arrow-left me-2"></i>
|
||
Назад к деплою
|
||
</a>
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="row">
|
||
<div class="col-12">
|
||
<!-- Информация -->
|
||
<div class="alert alert-info mb-3">
|
||
<i class="fas fa-info-circle me-2"></i>
|
||
<strong>Информация:</strong> Inventory файл определяет серверы для деплоя.
|
||
Используйте стандартный формат Ansible inventory (INI или YAML).
|
||
</div>
|
||
|
||
<!-- Редактор inventory -->
|
||
<div class="card mb-3">
|
||
<div class="card-header">
|
||
<h5 class="mb-0">Редактор inventory/hosts.ini</h5>
|
||
</div>
|
||
<div class="card-body">
|
||
<form
|
||
id="inventory-form"
|
||
hx-post="/api/v1/deploy/inventory"
|
||
hx-target="#result"
|
||
hx-swap="innerHTML"
|
||
>
|
||
<div class="mb-3">
|
||
<label class="form-label">Содержимое inventory</label>
|
||
<textarea
|
||
id="inventory-editor"
|
||
name="content"
|
||
class="form-control"
|
||
rows="20"
|
||
placeholder="[webservers]
|
||
web1 ansible_host=192.168.1.10 ansible_user=root
|
||
web2 ansible_host=192.168.1.11 ansible_user=root
|
||
|
||
[database]
|
||
db1 ansible_host=192.168.1.20 ansible_user=root
|
||
|
||
[all:vars]
|
||
ansible_python_interpreter=/usr/bin/python3"
|
||
>{{ inventory_content }}</textarea>
|
||
<div class="form-text">
|
||
<i class="fas fa-info-circle me-1"></i>
|
||
Поддерживается формат INI и YAML. Редактор автоматически определит формат.
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Результат -->
|
||
<div id="result" class="mb-3"></div>
|
||
|
||
<!-- Кнопки -->
|
||
<div class="d-flex gap-2">
|
||
<button type="submit" class="btn btn-primary">
|
||
<i class="fas fa-save me-2"></i>
|
||
Сохранить Inventory
|
||
</button>
|
||
<button type="button" class="btn btn-outline-secondary" onclick="validateInventory()">
|
||
<i class="fas fa-check me-2"></i>
|
||
Проверить синтаксис
|
||
</button>
|
||
<a href="/deploy" class="btn btn-secondary">
|
||
Отмена
|
||
</a>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Примеры -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h5 class="mb-0">Примеры Inventory</h5>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="row g-3">
|
||
<div class="col-12 col-md-6">
|
||
<h6 class="fw-semibold mb-2">Простой пример (INI)</h6>
|
||
<pre class="bg-dark text-light p-3 rounded"><code>[webservers]
|
||
web1 ansible_host=192.168.1.10
|
||
web2 ansible_host=192.168.1.11
|
||
|
||
[database]
|
||
db1 ansible_host=192.168.1.20
|
||
|
||
[all:vars]
|
||
ansible_user=root
|
||
ansible_python_interpreter=/usr/bin/python3</code></pre>
|
||
</div>
|
||
|
||
<div class="col-12 col-md-6">
|
||
<h6 class="fw-semibold mb-2">С SSH ключами (INI)</h6>
|
||
<pre class="bg-dark text-light p-3 rounded"><code>[webservers]
|
||
web1 ansible_host=192.168.1.10 ansible_ssh_private_key_file=~/.ssh/id_rsa
|
||
web2 ansible_host=192.168.1.11 ansible_ssh_private_key_file=~/.ssh/id_rsa
|
||
|
||
[database]
|
||
db1 ansible_host=192.168.1.20 ansible_ssh_private_key_file=~/.ssh/id_rsa
|
||
|
||
[all:vars]
|
||
ansible_user=ubuntu
|
||
ansible_python_interpreter=/usr/bin/python3</code></pre>
|
||
</div>
|
||
|
||
<div class="col-12">
|
||
<h6 class="fw-semibold mb-2">YAML формат</h6>
|
||
<pre class="bg-dark text-light p-3 rounded"><code>all:
|
||
children:
|
||
webservers:
|
||
hosts:
|
||
web1:
|
||
ansible_host: 192.168.1.10
|
||
web2:
|
||
ansible_host: 192.168.1.11
|
||
database:
|
||
hosts:
|
||
db1:
|
||
ansible_host: 192.168.1.20
|
||
vars:
|
||
ansible_user: root
|
||
ansible_python_interpreter: /usr/bin/python3</code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block scripts %}
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
if (typeof CodeMirror !== 'undefined') {
|
||
const inventoryEditor = CodeMirror.fromTextArea(
|
||
document.getElementById('inventory-editor'),
|
||
{
|
||
mode: 'yaml', // Начинаем с YAML, но можно переключить на INI
|
||
theme: 'monokai',
|
||
lineNumbers: true,
|
||
indentUnit: 2,
|
||
lineWrapping: true,
|
||
autofocus: true
|
||
}
|
||
);
|
||
|
||
// Определяем формат по содержимому
|
||
const content = inventoryEditor.getValue();
|
||
if (content.trim().startsWith('[') || content.includes('ansible_host=')) {
|
||
// Это INI формат
|
||
inventoryEditor.setOption('mode', 'ini');
|
||
}
|
||
|
||
// Обновляем textarea перед отправкой формы
|
||
document.getElementById('inventory-form').addEventListener('submit', function() {
|
||
inventoryEditor.save();
|
||
});
|
||
|
||
// Сохраняем editor в глобальной переменной для доступа из других функций
|
||
window.inventoryEditor = inventoryEditor;
|
||
}
|
||
});
|
||
|
||
function validateInventory() {
|
||
const editor = window.inventoryEditor;
|
||
if (!editor) {
|
||
alert('Редактор не инициализирован');
|
||
return;
|
||
}
|
||
|
||
const content = editor.getValue();
|
||
|
||
// Простая валидация
|
||
if (!content.trim()) {
|
||
alert('Inventory пуст');
|
||
return;
|
||
}
|
||
|
||
// Проверяем наличие групп
|
||
if (content.includes('[') && !content.match(/\[.*\]/)) {
|
||
alert('⚠️ Предупреждение: Не найдено групп в формате [group_name]');
|
||
return;
|
||
}
|
||
|
||
alert('✅ Синтаксис inventory корректен');
|
||
}
|
||
</script>
|
||
{% endblock %}
|