layer1: add namespace manager model step 7

This commit is contained in:
Naeel
2026-04-26 09:54:23 +03:00
parent 97b13a13c2
commit ac2638f17d
3 changed files with 198 additions and 0 deletions
+95
View File
@@ -0,0 +1,95 @@
package utils
import "time"
type NamespacePhase string
const (
NamespacePhaseDiscovered NamespacePhase = "discovered"
NamespacePhaseRegistering NamespacePhase = "registering"
NamespacePhaseActive NamespacePhase = "active"
NamespacePhaseDeregistering NamespacePhase = "deregistering"
NamespacePhaseRemoved NamespacePhase = "removed"
NamespacePhaseFailed NamespacePhase = "failed"
)
type NamespaceSource string
const (
NamespaceSourceEnv NamespaceSource = "env"
NamespaceSourceWatcher NamespaceSource = "watcher"
NamespaceSourceBackfill NamespaceSource = "backfill"
)
type NamespaceEventType string
const (
NamespaceEventAdd NamespaceEventType = "add"
NamespaceEventUpdate NamespaceEventType = "update"
NamespaceEventRemove NamespaceEventType = "remove"
NamespaceEventResync NamespaceEventType = "resync"
)
type NamespacePartState struct {
State string
LastError string
UpdatedAt time.Time
}
type NamespaceRecord struct {
Name string
Source NamespaceSource
Labels map[string]string
Phase NamespacePhase
LastError string
Generation int64
UpdatedAt time.Time
RegisteredParts map[string]NamespacePartState
}
type NamespaceEvent struct {
Type NamespaceEventType
Name string
Labels map[string]string
Source NamespaceSource
ObservedAt time.Time
}
func (nr NamespaceRecord) Clone() NamespaceRecord {
clone := nr
clone.Labels = cloneStringMap(nr.Labels)
clone.RegisteredParts = cloneNamespacePartStates(nr.RegisteredParts)
return clone
}
func (nr NamespaceRecord) IsActive() bool {
return nr.Phase == NamespacePhaseActive
}
func (nr NamespaceRecord) IsTerminal() bool {
return nr.Phase == NamespacePhaseRemoved || nr.Phase == NamespacePhaseFailed
}
func cloneStringMap(input map[string]string) map[string]string {
if input == nil {
return nil
}
clone := make(map[string]string, len(input))
for key, value := range input {
clone[key] = value
}
return clone
}
func cloneNamespacePartStates(input map[string]NamespacePartState) map[string]NamespacePartState {
if input == nil {
return nil
}
clone := make(map[string]NamespacePartState, len(input))
for key, value := range input {
clone[key] = value
}
return clone
}
+67
View File
@@ -0,0 +1,67 @@
package utils
import (
"testing"
"time"
)
func TestNamespaceRecordClone(t *testing.T) {
now := time.Now().UTC()
record := NamespaceRecord{
Name: "tenant-a",
Source: NamespaceSourceWatcher,
Phase: NamespacePhaseRegistering,
Generation: 7,
UpdatedAt: now,
Labels: map[string]string{
"fission.io/managed": "true",
},
RegisteredParts: map[string]NamespacePartState{
"router": {
State: "active",
UpdatedAt: now,
},
},
}
clone := record.Clone()
clone.Labels["fission.io/managed"] = "false"
clone.RegisteredParts["router"] = NamespacePartState{State: "failed", LastError: "boom"}
if record.Labels["fission.io/managed"] != "true" {
t.Fatalf("expected labels to be deep copied")
}
if record.RegisteredParts["router"].State != "active" {
t.Fatalf("expected registered parts to be deep copied")
}
}
func TestNamespaceRecordIsActive(t *testing.T) {
record := NamespaceRecord{Phase: NamespacePhaseActive}
if !record.IsActive() {
t.Fatalf("expected active phase to be reported as active")
}
record.Phase = NamespacePhaseRegistering
if record.IsActive() {
t.Fatalf("expected non-active phase to be reported as inactive")
}
}
func TestNamespaceRecordIsTerminal(t *testing.T) {
for _, test := range []struct {
phase NamespacePhase
expected bool
}{
{phase: NamespacePhaseRemoved, expected: true},
{phase: NamespacePhaseFailed, expected: true},
{phase: NamespacePhaseActive, expected: false},
{phase: NamespacePhaseRegistering, expected: false},
} {
record := NamespaceRecord{Phase: test.phase}
if record.IsTerminal() != test.expected {
t.Fatalf("expected terminal=%v for phase %s", test.expected, test.phase)
}
}
}