package utils import ( "os" "reflect" "testing" ) func TestNamespaceResolver(t *testing.T) { t.Run("GetBuilderNS", func(t *testing.T) { for _, test := range []struct { name string namespaceResolver *NamespaceResolver namespace string expected string }{ { name: "should return fission-builder namespace", namespaceResolver: getFissionNamespaces("fission-builder", "fission-function", "default"), namespace: "default", expected: "fission-builder", }, { name: "should return testns2 namespace", namespaceResolver: getFissionNamespaces("fission-builder", "fission-function", "default"), namespace: "testns2", expected: "testns2", }, { name: "should return fission-builder namespace", namespaceResolver: getFissionNamespaces("fission-builder", "", "default"), namespace: "default", expected: "fission-builder", }, { name: "should return testns3 namespace", namespaceResolver: getFissionNamespaces("fission-builder", "", "testns"), namespace: "testns3", expected: "testns3", }, { name: "should return testns4 namespace", namespaceResolver: getFissionNamespaces("", "fission-function", "default"), namespace: "testns4", expected: "testns4", }, { name: "should return testns5 namespace", namespaceResolver: getFissionNamespaces("", "fission-function", "testns"), namespace: "testns5", expected: "testns5", }, { name: "should return default namespace", namespaceResolver: getFissionNamespaces("", "", "default"), namespace: "default", expected: "default", }, { name: "should return testns6 namespace", namespaceResolver: getFissionNamespaces("", "", "default"), namespace: "testns6", expected: "testns6", }, { name: "should return testns7 namespace", namespaceResolver: getFissionNamespaces("", "", ""), namespace: "testns7", expected: "testns7", }, } { t.Run(test.name, func(t *testing.T) { ns := test.namespaceResolver.GetBuilderNS(test.namespace) if ns != test.expected { t.Errorf("expected builder namespace %s, got %s", test.expected, ns) } }) } }) t.Run("GetFunctionNS", func(t *testing.T) { for _, test := range []struct { name string namespaceResolver *NamespaceResolver namespace string expected string }{ { name: "should return fission-function namespace", namespaceResolver: getFissionNamespaces("fission-builder", "fission-function", "default"), namespace: "default", expected: "fission-function", }, { name: "should return testns2 namespace", namespaceResolver: getFissionNamespaces("fission-builder", "fission-function", "default"), namespace: "testns2", expected: "testns2", }, { name: "should return fission-function namespace", namespaceResolver: getFissionNamespaces("", "fission-function", "default"), namespace: "default", expected: "fission-function", }, { name: "should return testns3 namespace", namespaceResolver: getFissionNamespaces("", "fission-function", "testns"), namespace: "testns3", expected: "testns3", }, { name: "should return testns4 namespace", namespaceResolver: getFissionNamespaces("fission-builder", "", "default"), namespace: "testns4", expected: "testns4", }, { name: "should return testns5 namespace", namespaceResolver: getFissionNamespaces("fission-builder", "", "testns"), namespace: "testns5", expected: "testns5", }, { name: "should return default namespace", namespaceResolver: getFissionNamespaces("", "", "default"), namespace: "default", expected: "default", }, { name: "should return testns6 namespace", namespaceResolver: getFissionNamespaces("", "", "default"), namespace: "testns6", expected: "testns6", }, { name: "should return testns7 namespace", namespaceResolver: getFissionNamespaces("", "", ""), namespace: "testns7", expected: "testns7", }, } { t.Run(test.name, func(t *testing.T) { ns := test.namespaceResolver.GetFunctionNS(test.namespace) if ns != test.expected { t.Errorf("expected function namespace %s, got %s", test.expected, ns) } }) } }) t.Run("ResolveNamespace", func(t *testing.T) { for _, test := range []struct { name string namespaceResolver *NamespaceResolver namespace string expected string }{ { name: "should return testns namespace", namespaceResolver: getFissionNamespaces("fission-builder", "fission-function", "default"), namespace: "testns", expected: "testns", }, { name: "should return default namespace", namespaceResolver: getFissionNamespaces("fission-builder", "", "default"), namespace: "testns", expected: "default", }, } { t.Run(test.name, func(t *testing.T) { ns := test.namespaceResolver.ResolveNamespace(test.namespace) if ns != test.expected { t.Errorf("expected function namespace %s, got %s", test.expected, ns) } }) } }) t.Run("Snapshot returns stable copy", func(t *testing.T) { nsr := &NamespaceResolver{ FissionResourceNS: map[string]string{ "ns-b": "ns-b", "ns-a": "ns-a", }, } snapshot := nsr.Snapshot() expected := []string{"ns-a", "ns-b"} if !reflect.DeepEqual(expected, snapshot) { t.Fatalf("expected snapshot %v, got %v", expected, snapshot) } snapshot[0] = "mutated" if nsr.FissionResourceNS["ns-a"] != "ns-a" { t.Fatalf("snapshot mutated internal namespace map") } }) t.Run("SnapshotWithOptions includes expanded namespaces once", func(t *testing.T) { nsr := &NamespaceResolver{ FunctionNamespace: "fn-ns", BuilderNamespace: "builder-ns", DefaultNamespace: "default", FissionResourceNS: map[string]string{ "default": "default", "user-ns": "user-ns", }, } snapshot := nsr.SnapshotWithOptions(WithBuilderNs(), WithFunctionNs(), WithDefaultNs()) expected := []string{"builder-ns", "default", "fn-ns", "user-ns"} if !reflect.DeepEqual(expected, snapshot) { t.Fatalf("expected snapshot with options %v, got %v", expected, snapshot) } }) t.Run("managed namespace label helpers", func(t *testing.T) { if ManagedNamespaceLabelSelector() != "fission.io/managed=true" { t.Fatalf("unexpected managed namespace selector: %s", ManagedNamespaceLabelSelector()) } if !IsManagedNamespace(map[string]string{ManagedNamespaceLabelKey: ManagedNamespaceLabelValue}) { t.Fatalf("expected managed namespace to be detected") } if IsManagedNamespace(map[string]string{ManagedNamespaceLabelKey: "false"}) { t.Fatalf("expected non-managed namespace to be rejected") } }) t.Run("getNamespace", func(t *testing.T) { for _, test := range []struct { name string defaultNamespace string additionalNamespace string expected int }{ { name: "length of namespaces should be 1", defaultNamespace: "", additionalNamespace: "", expected: 1, }, { name: "length of namespaces should be 1", defaultNamespace: "default", additionalNamespace: "", expected: 1, }, { name: "length of namespaces should be 1", defaultNamespace: "default", additionalNamespace: "default", expected: 1, }, { name: "length of namespaces should be 3", defaultNamespace: "default", additionalNamespace: "testns1,testns2", expected: 3, }, } { t.Run(test.name, func(t *testing.T) { err := setNamespace(test.defaultNamespace, test.additionalNamespace) if err != nil { t.Fatalf("error setting environment Variable %s", err.Error()) } ns := GetNamespaces() if test.expected != len(ns) { t.Errorf("expected length of namespace %d, got %d", test.expected, len(ns)) } }) } }) } func TestServiceAccountResolveSANamespace(t *testing.T) { sa := &ServiceAccount{ nsResolver: &NamespaceResolver{ FunctionNamespace: "fission-function", BuilderNamespace: "fission-builder", DefaultNamespace: "default", }, } t.Run("fetcher uses function namespace for default ns", func(t *testing.T) { resolvedNS := sa.resolveSANamespace("default", FetcherSAName) if resolvedNS != "fission-function" { t.Fatalf("expected function namespace, got %s", resolvedNS) } }) t.Run("builder uses builder namespace for default ns", func(t *testing.T) { resolvedNS := sa.resolveSANamespace("default", BuilderSAName) if resolvedNS != "fission-builder" { t.Fatalf("expected builder namespace, got %s", resolvedNS) } }) t.Run("builder keeps tenant namespace unchanged", func(t *testing.T) { resolvedNS := sa.resolveSANamespace("tenant-a", BuilderSAName) if resolvedNS != "tenant-a" { t.Fatalf("expected tenant namespace, got %s", resolvedNS) } }) } func getFissionNamespaces(builderNS, functionNS, defaultNS string) *NamespaceResolver { return &NamespaceResolver{ FunctionNamespace: functionNS, BuilderNamespace: builderNS, DefaultNamespace: defaultNS, } } func setNamespace(defaultNamespace string, additionalNamespace string) error { err := os.Setenv(ENV_DEFAULT_NAMESPACE, defaultNamespace) if err != nil { return err } err = os.Setenv(ENV_ADDITIONAL_NAMESPACE, additionalNamespace) if err != nil { return err } return nil }