refactor(generator): реестры исключений (данные) вместо хардкодов svc.ID==N / ServiceID==N
This commit is contained in:
@@ -476,18 +476,46 @@ func buildOutputsPage(spec types.ServiceSpec, nav string, version string) string
|
|||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
if spec.ServiceID == 90 && containsString(snapshot.OutPaths, "internalConnect.master") && containsString(snapshot.VaultFields, "adminUser") && containsString(snapshot.VaultFields, "adminPass") {
|
for _, ex := range serviceSpecificDocExamples {
|
||||||
b.WriteString("### Пример для связки с Lucee/NodeJS\n\n")
|
if spec.Name == ex.serviceName && hasAllKeys(snapshot.OutPaths, ex.outKeys) && hasAllKeys(snapshot.VaultFields, ex.vaultKeys) {
|
||||||
b.WriteString("```hcl\n")
|
b.WriteString("### Пример для связки с Lucee/NodeJS\n\n")
|
||||||
b.WriteString("testds_connectionString = \"jdbc:postgresql://${nubes_postgres.db2.state_out_flat[\"internalConnect.master\"]}:5432/postgres?sslmode=require\"\n")
|
b.WriteString("```hcl\n")
|
||||||
b.WriteString("testds_username = nubes_postgres.db2.vault_secrets[\"adminUser\"]\n")
|
b.WriteString("testds_connectionString = \"jdbc:postgresql://${nubes_postgres.db2.state_out_flat[\"internalConnect.master\"]}:5432/postgres?sslmode=require\"\n")
|
||||||
b.WriteString("testds_password = nubes_postgres.db2.vault_secrets[\"adminPass\"]\n")
|
b.WriteString("testds_username = nubes_postgres.db2.vault_secrets[\"adminUser\"]\n")
|
||||||
b.WriteString("```\n")
|
b.WriteString("testds_password = nubes_postgres.db2.vault_secrets[\"adminPass\"]\n")
|
||||||
|
b.WriteString("```\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// serviceSpecificDocExamples — реестр исключений документации (ДАННЫЕ, не логика).
|
||||||
|
//
|
||||||
|
// ЧТО: postgres → дополнительный HCL-пример связки с Lucee/NodeJS.
|
||||||
|
// ЧТО ДЕЛАЕТ: если сервис и требуемые ключи state_out_flat/vault_secrets совпали — рендерит пример.
|
||||||
|
// ПОЧЕМУ: специфичная интеграция postgres↔Lucee/NodeJS, универсальный рендер её не покрывает.
|
||||||
|
// ГДЕ: TOOLS/ARCHITECTURE.md, раздел «Реестр исключений».
|
||||||
|
//
|
||||||
|
// Добавлять только здесь. Grep-гейт TOOLS/scripts/check_hardcoded_service_ids.sh
|
||||||
|
// запрещает сравнения ServiceID == N вне этого файла.
|
||||||
|
var serviceSpecificDocExamples = []struct {
|
||||||
|
serviceName string
|
||||||
|
outKeys []string
|
||||||
|
vaultKeys []string
|
||||||
|
}{
|
||||||
|
{serviceName: "postgres", outKeys: []string{"internalConnect.master"}, vaultKeys: []string{"adminUser", "adminPass"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasAllKeys(haystack []string, needles []string) bool {
|
||||||
|
for _, n := range needles {
|
||||||
|
if !containsString(haystack, n) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func containsString(values []string, target string) bool {
|
func containsString(values []string, target string) bool {
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
if value == target {
|
if value == target {
|
||||||
|
|||||||
Executable
+29
@@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# check_hardcoded_service_ids.sh — запрет сервис-специфичных хардкодов по числовому ID.
|
||||||
|
#
|
||||||
|
# Ищет сравнения вида svc.ID == N / ServiceID == N / spec.ServiceID == N (N > 0)
|
||||||
|
# в Go-коде TOOLS/. Исключения должны жить ТОЛЬКО в именованных реестрах (данные):
|
||||||
|
# - TOOLS/yaml-generator/main.go (serviceSpecificModifiers)
|
||||||
|
# - TOOLS/docs-generator/internal/writers/writers.go (serviceSpecificDocExamples)
|
||||||
|
#
|
||||||
|
# Выход: 0 — хардкодов нет; 1 — найдены.
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
ROOT_DIR="${ROOT_DIR:-$(cd "${SCRIPT_DIR}/../.." && pwd)}"
|
||||||
|
|
||||||
|
matches="$(grep -rnE '\.(ServiceID|ID)[[:space:]]*==[[:space:]]*[1-9][0-9]*' "$ROOT_DIR/TOOLS" --include='*.go' || true)"
|
||||||
|
|
||||||
|
if [[ -n "$matches" ]]; then
|
||||||
|
echo "HARDCODED SERVICE ID FOUND (service-specific logic must live in a registry):" >&2
|
||||||
|
echo "$matches" >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "Вынеси исключение в один из реестров:" >&2
|
||||||
|
echo " - TOOLS/yaml-generator/main.go (serviceSpecificModifiers)" >&2
|
||||||
|
echo " - TOOLS/docs-generator/internal/writers/writers.go (serviceSpecificDocExamples)" >&2
|
||||||
|
echo "См. TOOLS/ARCHITECTURE.md, раздел «Реестр исключений»." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "OK: no hardcoded service IDs in TOOLS/."
|
||||||
@@ -19,6 +19,23 @@ import (
|
|||||||
"yaml-generator/internal/types"
|
"yaml-generator/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// serviceSpecificModifiers — реестр исключений (ДАННЫЕ, не логика).
|
||||||
|
// Ключ — стабильное имя сервиса (как в YAML), значение — имя modifier-ресурса,
|
||||||
|
// который генерируется для его операции modify (отложенный modify над инстансом).
|
||||||
|
//
|
||||||
|
// ЧТО: операция modify сервиса помечается kind=modifier + modifier=<имя>.
|
||||||
|
// ЧТО ДЕЛАЕТ: yaml-generator создаёт для неё отдельный ресурс nubes_<svc>_<modifier>.
|
||||||
|
// ПОЧЕМУ: эти modify — отдельный шаг цепочки (аллокация IP / SNAT), их нельзя
|
||||||
|
// выполнять в том же ресурсе инстанса (чередующаяся зависимость).
|
||||||
|
// ГДЕ: TOOLS/ARCHITECTURE.md, раздел «Реестр исключений».
|
||||||
|
//
|
||||||
|
// Добавлять только здесь. Grep-гейт TOOLS/scripts/check_hardcoded_service_ids.sh
|
||||||
|
// запрещает сравнения svc.ID == N вне этого файла.
|
||||||
|
var serviceSpecificModifiers = map[string]string{
|
||||||
|
"vc_org": "ip_space",
|
||||||
|
"vc_nsxt": "network",
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cfg, err := config.Load()
|
cfg, err := config.Load()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -72,13 +89,12 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
for idx := range ops {
|
for idx := range ops {
|
||||||
if strings.EqualFold(ops[idx].Action, "modify") && svc.ID == 19 {
|
if !strings.EqualFold(ops[idx].Action, "modify") {
|
||||||
ops[idx].Kind = "modifier"
|
continue
|
||||||
ops[idx].Modifier = "ip_space"
|
|
||||||
}
|
}
|
||||||
if strings.EqualFold(ops[idx].Action, "modify") && svc.ID == 22 {
|
if modName, ok := serviceSpecificModifiers[name]; ok {
|
||||||
ops[idx].Kind = "modifier"
|
ops[idx].Kind = "modifier"
|
||||||
ops[idx].Modifier = "network"
|
ops[idx].Modifier = modName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user