feat(adr-075): 修復 Telegram 動態按鈕 4 個斷點 + 新增 7 種告警分類
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
斷點 A: decision_manager 提取 alert_category/notification_type 傳入 send_approval_card 斷點 B: send_approval_card 新增參數並傳遞至 _build_inline_keyboard 斷點 C: 互動型通知 (TYPE-3/4/4D/8M) 禁止發 SRE 群組,防 nonce 洩漏 斷點 D: _CATEGORY_BUTTONS k8s_workload → kubernetes + 新增 6 類按鈕組 classify_alert_early 新增: alertchain_health, flywheel_health, storage, devops_tool, external_site, ssl_cert, host_resource (從 infrastructure 分離) Test: 52 classify + 664 total passed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -76,17 +76,144 @@ class TestInfrastructure:
|
||||
def test_docker_prefix(self):
|
||||
ac, nt = classify_alert_early("DockerContainerOOM", "critical", {})
|
||||
assert nt == "TYPE-3"
|
||||
assert ac == "infrastructure"
|
||||
|
||||
def test_host_prefix(self):
|
||||
ac, nt = classify_alert_early("HostHighCpuLoad", "warning", {})
|
||||
assert nt == "TYPE-3"
|
||||
assert ac == "infrastructure"
|
||||
assert ac == "infrastructure" # Docker → 保留 infrastructure
|
||||
|
||||
def test_docker_restart(self):
|
||||
ac, nt = classify_alert_early("DockerContainerRestarting", "warning", {})
|
||||
assert ac == "infrastructure"
|
||||
|
||||
# ADR-075: Host* 從 infrastructure 分離為 host_resource
|
||||
def test_host_prefix_is_host_resource(self):
|
||||
ac, nt = classify_alert_early("HostHighCpuLoad", "warning", {})
|
||||
assert nt == "TYPE-3"
|
||||
assert ac == "host_resource"
|
||||
|
||||
def test_host_down(self):
|
||||
ac, nt = classify_alert_early("HostDown", "critical", {})
|
||||
assert ac == "host_resource"
|
||||
|
||||
def test_host_memory(self):
|
||||
ac, nt = classify_alert_early("HostOutOfMemory", "warning", {})
|
||||
assert ac == "host_resource"
|
||||
|
||||
def test_host_disk(self):
|
||||
ac, nt = classify_alert_early("HostOutOfDiskSpace", "warning", {})
|
||||
assert ac == "host_resource"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ADR-075: alertchain_health (TYPE-8M)
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
class TestAlertchainHealth:
|
||||
@pytest.mark.parametrize("alertname", [
|
||||
"AlertChainBroken_Alertmanager",
|
||||
"AlertChainBroken_Sentry",
|
||||
"NoAlertsReceived2Hours",
|
||||
"AlertChainUnhealthy",
|
||||
])
|
||||
def test_alertchain_alerts(self, alertname):
|
||||
ac, nt = classify_alert_early(alertname, "critical", {})
|
||||
assert ac == "alertchain_health"
|
||||
assert nt == "TYPE-8M"
|
||||
|
||||
def test_alertchain_beats_severity_info(self):
|
||||
# 即使 severity=info,AlertChainBroken 也必須是 alertchain_health
|
||||
ac, nt = classify_alert_early("AlertChainBroken_Alertmanager", "info", {})
|
||||
assert ac == "alertchain_health"
|
||||
assert nt == "TYPE-8M"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ADR-075: flywheel_health (TYPE-8M)
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
class TestFlywheelHealth:
|
||||
def test_auto_repair_low_success(self):
|
||||
ac, nt = classify_alert_early("AutoRepairLowSuccessRate", "warning", {})
|
||||
assert ac == "flywheel_health"
|
||||
assert nt == "TYPE-8M"
|
||||
|
||||
def test_permanent_fix_required(self):
|
||||
ac, nt = classify_alert_early("PermanentFixRequired", "warning", {})
|
||||
assert ac == "flywheel_health"
|
||||
assert nt == "TYPE-8M"
|
||||
|
||||
def test_flywheel_prefix(self):
|
||||
ac, nt = classify_alert_early("FlywheelPlaybookZero", "critical", {})
|
||||
assert ac == "flywheel_health"
|
||||
assert nt == "TYPE-8M"
|
||||
|
||||
def test_flywheel_beats_severity_info(self):
|
||||
ac, nt = classify_alert_early("AutoRepairLowSuccessRate", "info", {})
|
||||
assert ac == "flywheel_health"
|
||||
assert nt == "TYPE-8M"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ADR-075: storage (TYPE-3)
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
class TestStorage:
|
||||
def test_minio_down(self):
|
||||
ac, nt = classify_alert_early("MinIODown", "critical", {})
|
||||
assert ac == "storage"
|
||||
assert nt == "TYPE-3"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ADR-075: devops_tool (TYPE-3)
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
class TestDevopsTool:
|
||||
@pytest.mark.parametrize("alertname", [
|
||||
"OpenClawDown",
|
||||
"SignOzDown",
|
||||
"GiteaDown",
|
||||
"HarborDown",
|
||||
"SentryDown",
|
||||
"AlertmanagerDown",
|
||||
"KaliScannerDown",
|
||||
"GiteaCIPipelineFailed",
|
||||
])
|
||||
def test_devops_tools(self, alertname):
|
||||
ac, nt = classify_alert_early(alertname, "critical", {})
|
||||
assert ac == "devops_tool"
|
||||
assert nt == "TYPE-3"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ADR-075: external_site (TYPE-3)
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
class TestExternalSite:
|
||||
@pytest.mark.parametrize("alertname", [
|
||||
"MoWoooWorkDown",
|
||||
"TsenyangWebsiteDown",
|
||||
"StockWoooWorkDown",
|
||||
"BitanWoooWorkDown",
|
||||
])
|
||||
def test_external_sites(self, alertname):
|
||||
ac, nt = classify_alert_early(alertname, "critical", {})
|
||||
assert ac == "external_site"
|
||||
assert nt == "TYPE-3"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ADR-075: ssl_cert (TYPE-3)
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
class TestSslCert:
|
||||
def test_external_site_ssl(self):
|
||||
ac, nt = classify_alert_early("ExternalSiteSSLExpiringSoon", "warning", {})
|
||||
assert ac == "ssl_cert"
|
||||
assert nt == "TYPE-3"
|
||||
|
||||
def test_tls_cert(self):
|
||||
ac, nt = classify_alert_early("TLSCertExpiryCritical", "critical", {})
|
||||
assert ac == "ssl_cert"
|
||||
assert nt == "TYPE-3"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# TYPE-3: Kubernetes
|
||||
|
||||
Reference in New Issue
Block a user