software steht so weit.

jetzt build + docker build und testen
This commit is contained in:
br committed 2026-10-02 13:25:34 +02:00
1 parent 42f0c0accb
commit ca6cdcca63
90 files changed
+10298 -480

No files matched your search

+47 -9
View File
@@ -16,6 +16,8 @@ import (
"fmt"
"net/http"
"slices"
"strconv"
"strings"
"sync"
"sultan/pkg/license"
@@ -54,11 +56,22 @@ type NodeState struct {
// NodeContext ist, was die Policy über einen Knoten wissen muss.
type NodeContext struct {
Tenant policy.Tenant
License license.License
Drained bool
Tenant policy.Tenant
License license.License
Drained bool
Maintenance *policy.Maintenance // Wartung des Knotens (nil = keine)
// Disconnected: Knoten getrennt, Routen werden (noch) gehalten – sie
// zeigen die Wartungsseite.
Disconnected bool
}
// Labels, mit denen ein Workload (Container, sultan.d-Dienst) seine Services
// in Wartung schickt.
const (
LabelMaintenance = "sultan.maintenance"
LabelMaintenancePublicReason = "sultan.maintenance.public_reason"
)
// Directory liefert den NodeContext; für gelöschte/unbekannte Knoten
// ErrUnknownNode (ggf. verpackt).
type Directory interface {
@@ -207,6 +220,7 @@ func (r *Registry) evaluate(ctx context.Context, nodeID string, state NodeState)
workloads := slices.Clone(state.Workloads)
slices.SortStableFunc(workloads, func(a, b Workload) int { return cmp.Compare(a.Name, b.Name) })
merged := &traefik.Configuration{}
serviceMaint := map[string]policy.Maintenance{}
seen := map[string]bool{}
for _, w := range workloads {
if seen[w.Name] {
@@ -225,6 +239,11 @@ func (r *Registry) evaluate(ctx context.Context, nodeID string, state NodeState)
continue
}
merged = m
if maint, ok := workloadMaintenance(w.Labels); ok && c.HTTP != nil {
for svc := range c.HTTP.Services {
serviceMaint[svc] = maint
}
}
}
down := map[string]bool{}
@@ -232,12 +251,15 @@ func (r *Registry) evaluate(ctx context.Context, nodeID string, state NodeState)
down[s] = true
}
res, err := r.Policy.Apply(policy.Input{
Tenant: nc.Tenant,
License: nc.License,
NodeID: nodeID,
NodeDrained: nc.Drained,
Config: merged,
DownServices: down,
Tenant: nc.Tenant,
License: nc.License,
NodeID: nodeID,
NodeDrained: nc.Drained,
Config: merged,
DownServices: down,
Maintenance: nc.Maintenance,
ServiceMaintenance: serviceMaint,
Disconnected: nc.Disconnected,
})
if err != nil {
return nil, err
@@ -249,6 +271,22 @@ func (r *Registry) evaluate(ctx context.Context, nodeID string, state NodeState)
return entry, nil
}
// workloadMaintenance liest sultan.maintenance(=true) und den optionalen
// öffentlichen Grund; Schlüssel ohne Beachtung der Groß-/Kleinschreibung.
func workloadMaintenance(labels map[string]string) (policy.Maintenance, bool) {
var on bool
var m policy.Maintenance
for k, v := range labels {
switch strings.ToLower(k) {
case LabelMaintenance:
on, _ = strconv.ParseBool(strings.TrimSpace(v))
case LabelMaintenancePublicReason:
m.PublicReason = strings.TrimSpace(v)
}
}
return m, on
}
// store übernimmt entry und meldet nur Verstöße, die vorher nicht bestanden.
func (r *Registry) store(nodeID string, entry *nodeEntry) {
if r.nodes == nil {