Check different sids and update docs
This commit is contained in:
parent
80571bf47f
commit
1e0690b061
2 changed files with 104 additions and 1 deletions
|
|
@ -44,7 +44,7 @@ SECONDARY_DB_HOST=10.100.13.5
|
||||||
|
|
||||||
### Назначение
|
### Назначение
|
||||||
|
|
||||||
Хранит информацию о хостах/серверах в кластере WAF.
|
Хранит информацию о хостах/серверах в кластере WAF. Таблица `instances` (старая) переименована в `instances_old` и не используется — все запросы идут к `instances_new`.
|
||||||
|
|
||||||
### Структура
|
### Структура
|
||||||
|
|
||||||
|
|
@ -89,7 +89,9 @@ WHERE hostname = $1 AND instance = $2;
|
||||||
|
|
||||||
| Поле | Тип | Описание | Пример |
|
| Поле | Тип | Описание | Пример |
|
||||||
|------|-----|----------|--------|
|
|------|-----|----------|--------|
|
||||||
|
| `id` | SERIAL | Первичный ключ (автоинкремент) | `1` |
|
||||||
| `client_title` | TEXT | Идентификатор клиента | `CLIENT001` |
|
| `client_title` | TEXT | Идентификатор клиента | `CLIENT001` |
|
||||||
|
| `parent_client_title` | TEXT | Родительский клиент (для grafana_gen) | `NULL` |
|
||||||
| `containers_count` | INTEGER | Количество контейнеров (0 = drain всех) | `3` |
|
| `containers_count` | INTEGER | Количество контейнеров (0 = drain всех) | `3` |
|
||||||
| `ptaf_config` | TEXT | Строка подключения к PTAF-серверу | `{...}` |
|
| `ptaf_config` | TEXT | Строка подключения к PTAF-серверу | `{...}` |
|
||||||
| `fluent_bit_port` | INTEGER | Порт Fluent Bit | `24224` |
|
| `fluent_bit_port` | INTEGER | Порт Fluent Bit | `24224` |
|
||||||
|
|
@ -160,6 +162,14 @@ WHERE client_title = $1;
|
||||||
### Миграции
|
### Миграции
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
|
-- Переименование PK (таблица была переименована из nodes в client_info)
|
||||||
|
ALTER TABLE client_info DROP CONSTRAINT nodes_pkey;
|
||||||
|
ALTER TABLE client_info ADD COLUMN id SERIAL PRIMARY KEY;
|
||||||
|
|
||||||
|
-- Добавление parent_client_title для grafana_gen
|
||||||
|
ALTER TABLE client_info
|
||||||
|
ADD COLUMN IF NOT EXISTS parent_client_title TEXT DEFAULT NULL;
|
||||||
|
|
||||||
ALTER TABLE client_info
|
ALTER TABLE client_info
|
||||||
ADD COLUMN IF NOT EXISTS docker_image TEXT DEFAULT NULL;
|
ADD COLUMN IF NOT EXISTS docker_image TEXT DEFAULT NULL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -83,9 +84,14 @@ func processPTAFClient(
|
||||||
|
|
||||||
// Если one_container = false — разбиваем SID по блокам и обрабатываем каждый блок отдельно
|
// Если one_container = false — разбиваем SID по блокам и обрабатываем каждый блок отдельно
|
||||||
if !clientInfo.OneContainer && clientInfo.SidBlock.Valid && clientInfo.SidBlock.String != "" {
|
if !clientInfo.OneContainer && clientInfo.SidBlock.Valid && clientInfo.SidBlock.String != "" {
|
||||||
|
// Переход true → false: дренируем обычные контейнеры
|
||||||
|
cleanupOneContainerContainers(clientInfo.ClientTitle, hostname)
|
||||||
return processPTAFClientBlocks(db, config, hostname, instanceName, clientInfo, resourcesData, portAllocator)
|
return processPTAFClientBlocks(db, config, hostname, instanceName, clientInfo, resourcesData, portAllocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Переход false → true: дренируем блочные контейнеры
|
||||||
|
cleanupBlockContainers(clientInfo.ClientTitle, hostname)
|
||||||
|
|
||||||
// Выделение портов
|
// Выделение портов
|
||||||
resourcePortMap, err := resolvePortsForClient(clientInfo, resourcesData, portAllocator)
|
resourcePortMap, err := resolvePortsForClient(clientInfo, resourcesData, portAllocator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -324,9 +330,12 @@ func processPTAFClientBlocks(
|
||||||
}
|
}
|
||||||
|
|
||||||
success := true
|
success := true
|
||||||
|
activeBlocks := make(map[string]bool)
|
||||||
|
|
||||||
for blockIdx, sidList := range blocks {
|
for blockIdx, sidList := range blocks {
|
||||||
blockNum := blockIdx + 1
|
blockNum := blockIdx + 1
|
||||||
blockName := fmt.Sprintf("block%d", blockNum)
|
blockName := fmt.Sprintf("block%d", blockNum)
|
||||||
|
activeBlocks[blockName] = true
|
||||||
log.Printf(" → Обработка блока %d: SID %v", blockNum, sidList)
|
log.Printf(" → Обработка блока %d: SID %v", blockNum, sidList)
|
||||||
|
|
||||||
// Собираем ресурсы для этого блока
|
// Собираем ресурсы для этого блока
|
||||||
|
|
@ -404,5 +413,89 @@ func processPTAFClientBlocks(
|
||||||
log.Printf(" ✓ Блок %d обработан успешно", blockNum)
|
log.Printf(" ✓ Блок %d обработан успешно", blockNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Очистка лишних блоков — drain контейнеров и удаление Angie конфигов
|
||||||
|
// которые больше не входят в sid_block
|
||||||
|
cleanupStaleBlocks(clientInfo.ClientTitle, activeBlocks, hostname)
|
||||||
|
|
||||||
return success
|
return success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cleanupStaleBlocks дренирует контейнеры и удаляет Angie конфиги
|
||||||
|
// для блоков которые больше не входят в sid_block
|
||||||
|
func cleanupStaleBlocks(clientTitle string, activeBlocks map[string]bool, hostname string) {
|
||||||
|
// Ищем существующие блочные Angie конфиги
|
||||||
|
pattern := fmt.Sprintf("/etc/angie/http.d/angie-ptaf-%s_block*.conf", clientTitle)
|
||||||
|
matches, _ := filepath.Glob(pattern)
|
||||||
|
for _, confFile := range matches {
|
||||||
|
// Извлекаем blockName из имени файла: angie-ptaf-{clientTitle}_{blockName}.conf
|
||||||
|
base := filepath.Base(confFile)
|
||||||
|
base = strings.TrimSuffix(base, ".conf")
|
||||||
|
base = strings.TrimPrefix(base, fmt.Sprintf("angie-ptaf-%s_", clientTitle))
|
||||||
|
blockName := base // например "block1"
|
||||||
|
|
||||||
|
if activeBlocks[blockName] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Блок устарел — дренируем контейнеры
|
||||||
|
log.Printf(" → Удаление устаревшего блока %s для %s", blockName, clientTitle)
|
||||||
|
blockClientTitle := fmt.Sprintf("%s_%s", clientTitle, blockName)
|
||||||
|
|
||||||
|
// Помечаем контейнеры на drain
|
||||||
|
actualCount := getActualContainerCount(blockClientTitle)
|
||||||
|
for containerNum := 1; containerNum <= actualCount; containerNum++ {
|
||||||
|
containerFullName := buildContainerFullName(blockClientTitle, containerNum, hostname)
|
||||||
|
exists, _ := checkContainerStatus(containerFullName)
|
||||||
|
if exists {
|
||||||
|
if err := markContainerForDrain(containerFullName, false); err != nil {
|
||||||
|
log.Printf(" ⚠ Ошибка пометки контейнера %s: %v", containerFullName, err)
|
||||||
|
} else {
|
||||||
|
log.Printf(" ✓ Контейнер %s помечен для drain", containerFullName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Помечаем Angie конфиг для drain
|
||||||
|
if err := markAngieConfigForDrain(blockClientTitle, false); err != nil {
|
||||||
|
log.Printf(" ⚠ Ошибка пометки Angie конфига для %s: %v", blockClientTitle, err)
|
||||||
|
} else {
|
||||||
|
log.Printf(" ✓ Angie конфиг для блока %s помечен для drain", blockName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanupBlockContainers дренирует все блочные контейнеры клиента
|
||||||
|
// Используется при переходе one_container: false → true
|
||||||
|
func cleanupBlockContainers(clientTitle string, hostname string) {
|
||||||
|
pattern := fmt.Sprintf("/etc/angie/http.d/angie-ptaf-%s_block*.conf", clientTitle)
|
||||||
|
matches, _ := filepath.Glob(pattern)
|
||||||
|
if len(matches) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf(" → Обнаружены блочные конфиги при one_container=true, инициируем drain")
|
||||||
|
cleanupStaleBlocks(clientTitle, map[string]bool{}, hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanupOneContainerContainers дренирует обычный (не блочный) контейнер клиента
|
||||||
|
// Используется при переходе one_container: true → false
|
||||||
|
func cleanupOneContainerContainers(clientTitle string, hostname string) {
|
||||||
|
actualCount := getActualContainerCount(clientTitle)
|
||||||
|
hasNonBlock := false
|
||||||
|
for containerNum := 1; containerNum <= actualCount; containerNum++ {
|
||||||
|
containerFullName := buildContainerFullName(clientTitle, containerNum, hostname)
|
||||||
|
exists, _ := checkContainerStatus(containerFullName)
|
||||||
|
if exists {
|
||||||
|
hasNonBlock = true
|
||||||
|
if err := markContainerForDrain(containerFullName, false); err != nil {
|
||||||
|
log.Printf(" ⚠ Ошибка пометки контейнера %s: %v", containerFullName, err)
|
||||||
|
} else {
|
||||||
|
log.Printf(" ✓ Контейнер %s помечен для drain (переход в блочный режим)", containerFullName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hasNonBlock {
|
||||||
|
if err := markAngieConfigForDrain(clientTitle, false); err != nil {
|
||||||
|
log.Printf(" ⚠ Ошибка пометки Angie конфига: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue