228 lines
7.2 KiB
Go
228 lines
7.2 KiB
Go
package main
|
||
|
||
import (
|
||
"database/sql"
|
||
"fmt"
|
||
"log"
|
||
"strings"
|
||
|
||
_ "github.com/lib/pq"
|
||
)
|
||
|
||
// connectToDB подключается к базе данных PostgreSQL
|
||
// Сначала пытается подключиться к primary, если не удалось - к secondary
|
||
func connectToDB(config Config) *sql.DB {
|
||
log.Println("Попытка подключения к первичной БД...")
|
||
|
||
connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
|
||
config.PrimaryDBHost, config.DBPort, config.DBUser, config.DBPassword, config.DBName)
|
||
|
||
db, err := sql.Open("postgres", connStr)
|
||
if err == nil {
|
||
err = db.Ping()
|
||
if err == nil {
|
||
log.Printf("Успешное подключение к первичной БД: %s", config.PrimaryDBHost)
|
||
return db
|
||
}
|
||
}
|
||
|
||
log.Printf("Не удалось подключиться к первичной БД: %v", err)
|
||
log.Println("Попытка подключения к вторичной БД...")
|
||
|
||
connStr = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
|
||
config.SecondaryDBHost, config.DBPort, config.DBUser, config.DBPassword, config.DBName)
|
||
|
||
db, err = sql.Open("postgres", connStr)
|
||
if err != nil {
|
||
log.Fatalf("Ошибка открытия соединения с вторичной БД: %v", err)
|
||
}
|
||
|
||
err = db.Ping()
|
||
if err != nil {
|
||
log.Fatalf("Ошибка подключения к вторичной БД: %v", err)
|
||
}
|
||
|
||
log.Printf("Успешное подключение к вторичной БД: %s", config.SecondaryDBHost)
|
||
return db
|
||
}
|
||
|
||
// getInstancesByHostname получает все instances для hostname из таблицы instances
|
||
// Возвращает массив instances, т.к. один hostname может быть связан с несколькими instance
|
||
func getInstancesByHostname(db *sql.DB, hostname string) ([]string, error) {
|
||
query := "SELECT instance FROM instances_new WHERE hostname = $1 ORDER BY instance"
|
||
|
||
rows, err := db.Query(query, hostname)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("ошибка выполнения запроса для hostname %s: %w", hostname, err)
|
||
}
|
||
defer rows.Close()
|
||
|
||
var instances []string
|
||
for rows.Next() {
|
||
var instance string
|
||
if err := rows.Scan(&instance); err != nil {
|
||
return nil, fmt.Errorf("ошибка чтения instance: %w", err)
|
||
}
|
||
instances = append(instances, instance)
|
||
}
|
||
|
||
if err = rows.Err(); err != nil {
|
||
return nil, fmt.Errorf("ошибка обработки результатов: %w", err)
|
||
}
|
||
|
||
if len(instances) == 0 {
|
||
return nil, fmt.Errorf("instances не найдены для hostname %s", hostname)
|
||
}
|
||
|
||
return instances, nil
|
||
}
|
||
|
||
// checkHostBelongsToInstance проверяет принадлежит ли хост к указанному instance
|
||
func checkHostBelongsToInstance(db *sql.DB, hostname, instance string) (bool, error) {
|
||
query := `
|
||
SELECT COUNT(*)
|
||
FROM instances_new
|
||
WHERE hostname = $1 AND instance = $2
|
||
`
|
||
|
||
var count int
|
||
err := db.QueryRow(query, hostname, instance).Scan(&count)
|
||
if err != nil {
|
||
return false, fmt.Errorf("ошибка проверки принадлежности хоста: %w", err)
|
||
}
|
||
|
||
return count > 0, nil
|
||
}
|
||
|
||
// getClientInfoByInstance получает всех клиентов для заданного waf_instance
|
||
func getClientInfoByInstance(db *sql.DB, instance string) ([]ClientInfo, error) {
|
||
query := `
|
||
SELECT containers_count, ptaf_config, client_title, fluent_bit_port, waf_instance
|
||
FROM client_info
|
||
WHERE waf_instance = $1
|
||
`
|
||
|
||
rows, err := db.Query(query, instance)
|
||
if err != nil {
|
||
if strings.Contains(err.Error(), "does not exist") {
|
||
return nil, fmt.Errorf("ошибка структуры таблицы client_info: %w (возможно изменилась схема БД)", err)
|
||
}
|
||
return nil, fmt.Errorf("ошибка выполнения запроса: %w", err)
|
||
}
|
||
defer rows.Close()
|
||
|
||
var clientInfoList []ClientInfo
|
||
for rows.Next() {
|
||
var ci ClientInfo
|
||
var wafInstance sql.NullString
|
||
err := rows.Scan(
|
||
&ci.ContainersCount,
|
||
&ci.PTAFConfig,
|
||
&ci.ClientTitle,
|
||
&ci.FluentBitPort,
|
||
&wafInstance,
|
||
)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("ошибка сканирования строки: %w", err)
|
||
}
|
||
|
||
if wafInstance.Valid {
|
||
ci.WAFInstance = wafInstance.String
|
||
}
|
||
|
||
clientInfoList = append(clientInfoList, ci)
|
||
}
|
||
|
||
return clientInfoList, nil
|
||
}
|
||
|
||
// getAppsSettingsByClientTitle получает apps_settings для заданного client_title
|
||
func getAppsSettingsByClientTitle(db *sql.DB, clientTitle string) ([]AppsSettings, error) {
|
||
query := `
|
||
SELECT
|
||
l7resourceid, waf_enabled, waf_vendor,
|
||
custom_input_http_ports, custom_input_https_ports,
|
||
custom_output_http_ports, custom_output_https_ports,
|
||
upstream_angie_custom, server_nginx_custom,
|
||
server_angie_custom, client_title,
|
||
upstream_nginx_custom,
|
||
location_angie_custom, location_nginx_custom,
|
||
server_directives_angie_custom, server_directives_nginx_custom,
|
||
sni,
|
||
mode,
|
||
ssl_enabled,
|
||
custom_angie_ssl,
|
||
max_fails,
|
||
fail_timeout
|
||
FROM apps_settings
|
||
WHERE client_title = $1
|
||
ORDER BY l7resourceid ASC
|
||
`
|
||
|
||
rows, err := db.Query(query, clientTitle)
|
||
if err != nil {
|
||
if strings.Contains(err.Error(), "does not exist") {
|
||
return nil, fmt.Errorf("ошибка структуры таблицы apps_settings: %w (возможно изменилась схема БД)", err)
|
||
}
|
||
return nil, fmt.Errorf("ошибка выполнения запроса: %w", err)
|
||
}
|
||
defer rows.Close()
|
||
|
||
var appsSettingsList []AppsSettings
|
||
for rows.Next() {
|
||
var a AppsSettings
|
||
err := rows.Scan(
|
||
&a.L7ResourceID, &a.WAFEnabled, &a.WAFVendor,
|
||
&a.CustomInputHTTPPorts, &a.CustomInputHTTPSPorts,
|
||
&a.CustomOutputHTTPPorts, &a.CustomOutputHTTPSPorts,
|
||
&a.UpstreamAngieCustom, &a.ServerNginxCustom,
|
||
&a.ServerAngieCustom, &a.ClientTitle,
|
||
&a.UpstreamNginxCustom,
|
||
&a.LocationAngieCustom, &a.LocationNginxCustom,
|
||
&a.ServerDirectivesAngieCustom, &a.ServerDirectivesNginxCustom,
|
||
&a.SNI,
|
||
&a.Mode,
|
||
&a.SSLEnabled,
|
||
&a.CustomAngieSSL,
|
||
&a.MaxFails,
|
||
&a.FailTimeout,
|
||
)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("ошибка сканирования строки: %w", err)
|
||
}
|
||
appsSettingsList = append(appsSettingsList, a)
|
||
}
|
||
|
||
return appsSettingsList, nil
|
||
}
|
||
|
||
// getClientInfoByClientTitle получает информацию о клиенте из таблицы client_info
|
||
func getClientInfoByClientTitle(db *sql.DB, clientTitle string) (*ClientInfo, error) {
|
||
query := `
|
||
SELECT containers_count, ptaf_config, client_title, fluent_bit_port, waf_instance
|
||
FROM client_info
|
||
WHERE client_title = $1
|
||
`
|
||
|
||
var clientInfo ClientInfo
|
||
var wafInstance sql.NullString
|
||
err := db.QueryRow(query, clientTitle).Scan(
|
||
&clientInfo.ContainersCount,
|
||
&clientInfo.PTAFConfig,
|
||
&clientInfo.ClientTitle,
|
||
&clientInfo.FluentBitPort,
|
||
&wafInstance,
|
||
)
|
||
if err != nil {
|
||
if strings.Contains(err.Error(), "does not exist") {
|
||
return nil, fmt.Errorf("ошибка структуры таблицы client_info: %w (возможно изменилась схема БД)", err)
|
||
}
|
||
return nil, fmt.Errorf("ошибка получения данных из client_info: %w", err)
|
||
}
|
||
|
||
if wafInstance.Valid {
|
||
clientInfo.WAFInstance = wafInstance.String
|
||
}
|
||
|
||
return &clientInfo, nil
|
||
}
|