Files
pxmon/internal/cluster/policies.go
T
2026-06-16 21:52:10 +04:00

153 lines
3.7 KiB
Go

package cluster
import (
"errors"
"strings"
"time"
)
func (s *Service) GetAlertRouting(selector string) (AlertRoutingPolicy, error) {
c, err := s.Get(selector)
if err != nil {
return AlertRoutingPolicy{}, err
}
return ensureAlertRoutingPolicy(c.AlertRouting), nil
}
func (s *Service) SetAlertRouting(selector string, p AlertRoutingPolicy) (Cluster, error) {
reg, err := s.store.Load()
if err != nil {
return Cluster{}, err
}
c, idx, err := findCluster(reg, selector)
if err != nil {
return Cluster{}, err
}
c.AlertRouting = ensureAlertRoutingPolicy(p)
c.UpdatedAt = s.now().UTC()
reg.Clusters[idx] = c
if err := s.store.Save(reg); err != nil {
return Cluster{}, err
}
_ = s.AppendChange("alert.routing", c.Name, "updated")
return c, nil
}
func (s *Service) GetRunbookTrigger(selector string) (RunbookTrigger, error) {
c, err := s.Get(selector)
if err != nil {
return RunbookTrigger{}, err
}
return ensureRunbookTrigger(c.RunbookTrigger), nil
}
func (s *Service) SetRunbookTrigger(selector string, p RunbookTrigger) (Cluster, error) {
reg, err := s.store.Load()
if err != nil {
return Cluster{}, err
}
c, idx, err := findCluster(reg, selector)
if err != nil {
return Cluster{}, err
}
c.RunbookTrigger = ensureRunbookTrigger(p)
c.UpdatedAt = s.now().UTC()
reg.Clusters[idx] = c
if err := s.store.Save(reg); err != nil {
return Cluster{}, err
}
_ = s.AppendChange("runbook.trigger", c.Name, "updated")
return c, nil
}
func (s *Service) TouchRunbookTrigger(selector string, when time.Time) error {
reg, err := s.store.Load()
if err != nil {
return err
}
c, idx, err := findCluster(reg, selector)
if err != nil {
return err
}
tr := ensureRunbookTrigger(c.RunbookTrigger)
tr.LastTriggered = when.UTC()
c.RunbookTrigger = tr
c.UpdatedAt = s.now().UTC()
reg.Clusters[idx] = c
return s.store.Save(reg)
}
func (s *Service) SetDriftBaseline(selector string) (Cluster, error) {
reg, err := s.store.Load()
if err != nil {
return Cluster{}, err
}
c, idx, err := findCluster(reg, selector)
if err != nil {
return Cluster{}, err
}
d := normalizeDriftControl(c.Drift)
d.Baseline = DriftBaseline{
Enabled: true,
SetAt: s.now().UTC(),
AgentVersion: strings.TrimSpace(c.Agent.Version),
Software: strings.TrimSpace(c.Software.Summary()),
}
c.Drift = d
c.UpdatedAt = s.now().UTC()
reg.Clusters[idx] = c
if err := s.store.Save(reg); err != nil {
return Cluster{}, err
}
_ = s.AppendChange("drift.baseline", c.Name, "set")
return c, nil
}
func (s *Service) GetDriftControl(selector string) (DriftControl, error) {
c, err := s.Get(selector)
if err != nil {
return DriftControl{}, err
}
return normalizeDriftControl(c.Drift), nil
}
func (s *Service) AckDriftIssue(selector, issueKind string, until time.Time) (Cluster, error) {
kind := strings.ToLower(strings.TrimSpace(issueKind))
if kind == "" {
return Cluster{}, errors.New("issue kind is required")
}
reg, err := s.store.Load()
if err != nil {
return Cluster{}, err
}
c, idx, err := findCluster(reg, selector)
if err != nil {
return Cluster{}, err
}
d := normalizeDriftControl(c.Drift)
if d.AckUntil == nil {
d.AckUntil = map[string]time.Time{}
}
d.AckUntil[kind] = until.UTC()
c.Drift = d
c.UpdatedAt = s.now().UTC()
reg.Clusters[idx] = c
if err := s.store.Save(reg); err != nil {
return Cluster{}, err
}
_ = s.AppendChange("drift.ack", c.Name, kind+" until="+until.UTC().Format(time.RFC3339))
return c, nil
}
func (s *Service) IsDriftIssueAcked(c Cluster, kind string, now time.Time) bool {
d := normalizeDriftControl(c.Drift)
if len(d.AckUntil) == 0 {
return false
}
u, ok := d.AckUntil[strings.ToLower(strings.TrimSpace(kind))]
if !ok {
return false
}
return now.UTC().Before(u)
}