62 lines
2.1 KiB
Go
62 lines
2.1 KiB
Go
package store
|
||
|
||
import (
|
||
"context"
|
||
"strings"
|
||
"time"
|
||
"unicode"
|
||
"unicode/utf8"
|
||
)
|
||
|
||
// Maintenance ist eine angemeldete Wartung eines Knotens.
|
||
type Maintenance struct {
|
||
Since time.Time
|
||
Until time.Time // Nullwert = unbefristet
|
||
Reason string // intern (Log, Monitoring) – nie öffentlich
|
||
PublicReason string // optional, ersetzt den Standardtext der Wartungsseite
|
||
}
|
||
|
||
// Active meldet, ob die Wartung zum Zeitpunkt now gilt (nil = keine).
|
||
func (m *Maintenance) Active(now time.Time) bool {
|
||
return m != nil && (m.Until.IsZero() || now.Before(m.Until))
|
||
}
|
||
|
||
const (
|
||
maxPublicReason = 300
|
||
maxReason = 500
|
||
)
|
||
|
||
// validText: einzeilig, ohne Steuerzeichen, höchstens max Zeichen.
|
||
func validText(s string, max int) bool {
|
||
return utf8.RuneCountInString(s) <= max && !strings.ContainsFunc(s, unicode.IsControl)
|
||
}
|
||
|
||
// SetNodeMaintenance meldet eine Wartung an (Since = jetzt). m.Until muss
|
||
// in der Zukunft liegen oder Nullwert (unbefristet) sein.
|
||
func (s *Store) SetNodeMaintenance(ctx context.Context, nodeID string, m Maintenance) error {
|
||
now := s.now()
|
||
switch {
|
||
case !m.Until.IsZero() && !m.Until.After(now):
|
||
return invalid("Wartungsende liegt nicht in der Zukunft")
|
||
case !validText(m.PublicReason, maxPublicReason):
|
||
return invalid("öffentlicher Grund: einzeilig, höchstens %d Zeichen", maxPublicReason)
|
||
case !validText(m.Reason, maxReason):
|
||
return invalid("Grund: einzeilig, höchstens %d Zeichen", maxReason)
|
||
}
|
||
var until any
|
||
if !m.Until.IsZero() {
|
||
until = formatTime(m.Until)
|
||
}
|
||
res, err := s.db.ExecContext(ctx, `UPDATE nodes SET maintenance_since = ?, maintenance_until = ?,
|
||
maintenance_reason = ?, maintenance_public_reason = ? WHERE id = ?`,
|
||
formatTime(now), until, m.Reason, m.PublicReason, nodeID)
|
||
return requireAffected(res, err, "Knoten "+nodeID)
|
||
}
|
||
|
||
// ClearNodeMaintenance beendet die Wartung eines Knotens.
|
||
func (s *Store) ClearNodeMaintenance(ctx context.Context, nodeID string) error {
|
||
res, err := s.db.ExecContext(ctx, `UPDATE nodes SET maintenance_since = NULL, maintenance_until = NULL,
|
||
maintenance_reason = '', maintenance_public_reason = '' WHERE id = ?`, nodeID)
|
||
return requireAffected(res, err, "Knoten "+nodeID)
|
||
}
|