Files
knowledge-governance/cmd/libraryctl/maintenance_test.go
T
姚章浩 11c52ad81b
build / build (push) Failing after 1m2s
fix(libraryctl): 封存窗口接上实例级入口闸门与后台静默
库级窗口永远拿不到在途排空证据:被代理的 WeKnora 收到 SIGTERM 就 exit(1),
写者退出码不能当作请求已排空。capture/recover 改由 librarymaintenance.Manager
装配入口闸门、后台静默检查、目标指纹与入口探针(与发布链路同一套实现),
排空证据来自闸门 drain 记录;缺 LIBRARY_TARGET_* 时在开窗口前拒绝并点名。

维护接线解析收敛到 internal/librarymaintenance/env.go,agent 与 worker 讲同一组
变量名;agent 启动如实打印接线状态;安装脚本强制 0600 agent.env。

试过:make verify 15 项全绿;新增 7 个用例(接线解析/身份绑定/缺闸门拒绝)。
2026-10-29 05:48:38 +08:00

81 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"strings"
"testing"
v071 "knowledge-governance/internal/releaseadapter/v071"
)
func maintenanceEnv() map[string]string {
return map[string]string{
"LIBRARY_TARGET_INSTANCE": "kgmaint-weknora",
"LIBRARY_TARGET_INGRESS_URL": "http://127.0.0.1:18080/health",
"LIBRARY_TARGET_INGRESS_SERVICE": "ingress",
"LIBRARY_TARGET_INGRESS_DRAIN_FILE": "/tmp/gate/drain.json",
"LIBRARY_TARGET_REDIS_ADDR": "127.0.0.1:26379",
"LIBRARY_TARGET_REDIS_PASSWORD": "secret",
"LIBRARY_TARGET_REDIS_DB": "0",
}
}
func captureSource() sourceConfig {
return sourceConfig{
DatabaseURL: "postgres://kgmaint:pw@127.0.0.1:25432/kgmaint_target?sslmode=disable",
SearchIndex: "kgmaint_1028a_chunks",
Object: v071.S3ObjectStoreConfig{Provider: "minio", Bucket: "kgmaint-1028a"},
}
}
func captureOptions() options {
return options{project: "kgmaint-weknora", writers: "app", nonWriters: "postgres=database store",
dockerSocket: "/var/run/docker.sock", journalRoot: "/tmp/kgmaint-journal"}
}
// 封存窗口必须是实例级:入口/队列来自与 worker 同一份 LIBRARY_TARGET_*,
// 库/索引/桶来自本次真实发现的源——两边混用就会"关 A 的门、读 B 的队列"。
func TestCaptureMaintenanceConfigBindsGateQueueAndSourceIdentity(t *testing.T) {
env := maintenanceEnv()
config, err := captureMaintenanceConfig(captureOptions(), captureSource(), func(name string) string { return env[name] })
if err != nil {
t.Fatalf("完整声明被拒:%v", err)
}
if config.Instance != "kgmaint-weknora" || config.Project != "kgmaint-weknora" {
t.Fatalf("实例/项目不对:%+v", config)
}
if config.IngressURL != "http://127.0.0.1:18080/health" || config.IngressService != "ingress" ||
config.IngressDrainFile != "/tmp/gate/drain.json" {
t.Fatalf("入口闸门取值不对:%+v", config)
}
if config.RedisAddr != "127.0.0.1:26379" || config.RedisPassword != "secret" || config.RedisDB != 0 {
t.Fatalf("队列取值不对:%+v", config)
}
// 口令只进结构体,不落进任何可打印身份:身份里只有 host:port/db。
if config.Database != "127.0.0.1:25432/kgmaint_target" {
t.Fatalf("数据库身份不对:%q", config.Database)
}
if strings.Contains(config.Database, "pw") {
t.Fatalf("数据库身份泄漏了口令:%q", config.Database)
}
if config.Index != "kgmaint_1028a_chunks" || config.Bucket != "kgmaint-1028a" {
t.Fatalf("索引/桶没取到源的身份:%+v", config)
}
if len(config.Writers) != 1 || config.Writers[0] != "app" || config.NonWriters["postgres"] == "" {
t.Fatalf("写入者声明没透传:%+v", config)
}
// 后台静默检查必须连"正在被封的源"。
if config.DatabaseURL != captureSource().DatabaseURL {
t.Fatalf("后台静默检查连错库")
}
}
// 没有闸门就没有排空证据:必须在开窗口之前拒绝,而不是退回"只锁库"的旧模式。
func TestCaptureMaintenanceConfigRefusesWithoutIngress(t *testing.T) {
env := maintenanceEnv()
delete(env, "LIBRARY_TARGET_INGRESS_URL")
_, err := captureMaintenanceConfig(captureOptions(), captureSource(), func(name string) string { return env[name] })
if err == nil || !strings.Contains(err.Error(), "LIBRARY_TARGET_INGRESS_URL") {
t.Fatalf("缺入口闸门没有被拒:%v", err)
}
}