package agent import ( "net" "testing" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func ptrBool(b bool) *bool { return &b } func mkPod(name string, owner *metav1.OwnerReference, labels map[string]string, image string) *corev1.Pod { p := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{Name: name, Labels: labels}, } if owner != nil { p.OwnerReferences = []metav1.OwnerReference{*owner} } if image != "" { p.Spec.Containers = []corev1.Container{{Image: image}} } return p } func TestDeriveAppName_DeploymentReplicaSet(t *testing.T) { owner := &metav1.OwnerReference{ Kind: "ReplicaSet", Name: "traefik-789df685f", Controller: ptrBool(true), } pod := mkPod("traefik-789df685f-hqvfl", owner, map[string]string{podTemplateHashLabel: "789df685f"}, "") if got := deriveAppName(pod); got != "traefik" { t.Fatalf("got %q, want %q", got, "traefik") } } func TestDeriveAppName_StatefulSet(t *testing.T) { owner := &metav1.OwnerReference{ Kind: "StatefulSet", Name: "gitea", Controller: ptrBool(true), } pod := mkPod("gitea-0", owner, nil, "") if got := deriveAppName(pod); got != "gitea" { t.Fatalf("got %q, want %q", got, "gitea") } } func TestDeriveAppName_DaemonSet(t *testing.T) { owner := &metav1.OwnerReference{ Kind: "DaemonSet", Name: "flock-agent", Controller: ptrBool(true), } pod := mkPod("flock-agent-abcde", owner, nil, "") if got := deriveAppName(pod); got != "flock-agent" { t.Fatalf("got %q, want %q", got, "flock-agent") } } func TestDeriveAppName_BarePod(t *testing.T) { pod := mkPod("standalone", nil, nil, "") if got := deriveAppName(pod); got != "standalone" { t.Fatalf("got %q, want %q", got, "standalone") } } // TestDeriveAppName_RSWithoutTemplateHash — ReplicaSet owners that don't // follow the standard "-" naming convention (e.g. a custom // controller) keep the RS name as-is. All replicas of that RS still align, // which is the second-best correctness offer. func TestDeriveAppName_RSWithoutTemplateHash(t *testing.T) { owner := &metav1.OwnerReference{ Kind: "ReplicaSet", Name: "weird-rs-name", Controller: ptrBool(true), } pod := mkPod("weird-rs-name-xyz", owner, nil, "") if got := deriveAppName(pod); got != "weird-rs-name" { t.Fatalf("got %q, want %q", got, "weird-rs-name") } } func TestDeriveAppName_NonControllerOwnerIgnored(t *testing.T) { // OwnerReference without Controller=true must be ignored — only the // controller owner is the canonical workload. owner := &metav1.OwnerReference{ Kind: "Foo", Name: "irrelevant", // Controller pointer left nil. } pod := mkPod("solo", owner, nil, "") if got := deriveAppName(pod); got != "solo" { t.Fatalf("got %q, want %q", got, "solo") } } func TestPodImageRef(t *testing.T) { pod := mkPod("p", nil, nil, "traefik:v3.5") if got := podImageRef(pod); got != "traefik:v3.5" { t.Fatalf("got %q, want %q", got, "traefik:v3.5") } empty := mkPod("p", nil, nil, "") if got := podImageRef(empty); got != "" { t.Fatalf("got %q, want \"\"", got) } } func TestSplitAddressesPrimary_BothFamilies(t *testing.T) { // Plex pattern: one v6 + one v4 → both peel out, no extras. ips := []net.IP{ net.ParseIP("2602:817:3000:c606::166"), net.ParseIP("142.202.202.166"), } v6, v4, extras := splitAddressesPrimary(ips) if v6 == nil || v6.String() != "2602:817:3000:c606::166" { t.Fatalf("v6 = %v", v6) } if v4 == nil || v4.String() != "142.202.202.166" { t.Fatalf("v4 = %v", v4) } if len(extras) != 0 { t.Fatalf("extras = %v, want empty", extras) } } func TestSplitAddressesPrimary_OnlyV4(t *testing.T) { v6, v4, extras := splitAddressesPrimary([]net.IP{net.ParseIP("142.202.202.166")}) if v6 != nil { t.Fatalf("v6 should be nil, got %v", v6) } if v4 == nil || v4.String() != "142.202.202.166" { t.Fatalf("v4 = %v", v4) } if len(extras) != 0 { t.Fatalf("extras = %v", extras) } } func TestSplitAddressesPrimary_OnlyV6(t *testing.T) { v6, v4, extras := splitAddressesPrimary([]net.IP{net.ParseIP("2602:817:3000:c606::166")}) if v4 != nil { t.Fatalf("v4 should be nil, got %v", v4) } if v6 == nil || v6.String() != "2602:817:3000:c606::166" { t.Fatalf("v6 = %v", v6) } if len(extras) != 0 { t.Fatalf("extras = %v", extras) } } func TestSplitAddressesPrimary_Empty(t *testing.T) { v6, v4, extras := splitAddressesPrimary(nil) if v6 != nil || v4 != nil || extras != nil { t.Fatalf("nil input should yield nil outputs, got v6=%v v4=%v extras=%v", v6, v4, extras) } } func TestSplitAddressesPrimary_Extras(t *testing.T) { // Multiple v4s — only the first peels into the primary slot; the rest // stay in extras for layered-eth0 binding via the AnycastReconciler. // (Not a current production use case, but the code should handle it // without dropping IPs.) ips := []net.IP{ net.ParseIP("142.202.202.166"), net.ParseIP("2602:817:3000:c606::166"), net.ParseIP("142.202.202.167"), net.ParseIP("2602:817:3000:c606::167"), } v6, v4, extras := splitAddressesPrimary(ips) if v4.String() != "142.202.202.166" { t.Fatalf("v4 primary = %v, want 142.202.202.166", v4) } if v6.String() != "2602:817:3000:c606::166" { t.Fatalf("v6 primary = %v, want 2602:817:3000:c606::166", v6) } if len(extras) != 2 { t.Fatalf("extras len = %d, want 2", len(extras)) } if extras[0].String() != "142.202.202.167" || extras[1].String() != "2602:817:3000:c606::167" { t.Fatalf("extras order/content wrong: %v", extras) } }