diff --git a/src/lib/filter/adjudicators/adjudicators.test.ts b/src/lib/filter/adjudicators/adjudicators.test.ts index ffb6a918d..4b86db908 100644 --- a/src/lib/filter/adjudicators/adjudicators.test.ts +++ b/src/lib/filter/adjudicators/adjudicators.test.ts @@ -268,6 +268,9 @@ describe("uncarryableNamespace", () => { [[], {}, false], [[], { metadata: { namespace: "namespace" } }, false], + [["namespace"], { kind: "Namespace", metadata: { name: "namespace" } }, false], + [["namespace"], { kind: "Namespace", metadata: { name: "monitoring" } }, true], + [["namespace"], {}, false], [["namespace"], { metadata: {} }, false], [["namespace"], { metadata: { namespace: null } }, false], @@ -297,6 +300,9 @@ describe("carriesIgnoredNamespace", () => { [[], {}, false], [[], { metadata: { namespace: "whatever" } }, false], + [["ignored"], { kind: "Namespace", metadata: { name: "ignored" } }, true], + [["ignored"], { kind: "Namespace", metadata: { name: "monitoring" } }, false], + [["ignored"], {}, false], [["ignored"], { metadata: {} }, false], [["ignored"], { metadata: { namespace: null } }, false], diff --git a/src/lib/filter/adjudicators/adjudicators.ts b/src/lib/filter/adjudicators/adjudicators.ts index 58faf8c7e..89084f9de 100644 --- a/src/lib/filter/adjudicators/adjudicators.ts +++ b/src/lib/filter/adjudicators/adjudicators.ts @@ -76,9 +76,8 @@ export const missingName = complement(carriesName); export const carriedNamespace = pipe((kubernetesObject: KubernetesObject): string | undefined => { if (kubernetesObject?.kind === "Namespace") { return kubernetesObject?.metadata?.name; - } else { - return kubernetesObject?.metadata?.namespace; } + return kubernetesObject?.metadata?.namespace; }, defaultTo("")); export const carriesNamespace = pipe(carriedNamespace, equals(""), not); @@ -252,10 +251,21 @@ export const mismatchedLabels = allPass([ pipe((binding, kubernetesObject) => metasMismatch(definedLabels(binding), carriedLabels(kubernetesObject))), ]); +/* + * If the object does not have a namespace, and it is not a namespace, + * then we must return false because it cannot be uncarryable + */ export const uncarryableNamespace = allPass([ pipe(nthArg(0), length, gt(__, 0)), - pipe(nthArg(1), carriesNamespace), - pipe((namespaceSelector, kubernetesObject) => namespaceSelector.includes(carriedNamespace(kubernetesObject)), not), + pipe((namespaceSelector, kubernetesObject) => { + if (kubernetesObject?.kind === "Namespace") { + return namespaceSelector.includes(kubernetesObject?.metadata?.name); + } + if (carriesNamespace(kubernetesObject)) { + return namespaceSelector.includes(carriedNamespace(kubernetesObject)); + } + return true; + }, not), ]); export const missingCarriableNamespace = allPass([ @@ -267,10 +277,22 @@ export const missingCarriableNamespace = allPass([ ), ]); +/* + * If the object does not have a namespace, and it is not a namespace, + * then we must return false because it cannot be ignored + */ export const carriesIgnoredNamespace = allPass([ pipe(nthArg(0), length, gt(__, 0)), - pipe(nthArg(1), carriesNamespace), - pipe((namespaceSelector, kubernetesObject) => namespaceSelector.includes(carriedNamespace(kubernetesObject))), + pipe((namespaceSelector, kubernetesObject) => { + if (kubernetesObject?.kind === "Namespace") { + return namespaceSelector.includes(kubernetesObject?.metadata?.name); + } + if (carriesNamespace(kubernetesObject)) { + return namespaceSelector.includes(carriedNamespace(kubernetesObject)); + } + + return false; + }), ]); export const unbindableNamespaces = allPass([ diff --git a/src/lib/filter/filter.test.ts b/src/lib/filter/filter.test.ts index e895b86b2..8d3bd8c7d 100644 --- a/src/lib/filter/filter.test.ts +++ b/src/lib/filter/filter.test.ts @@ -1218,6 +1218,10 @@ describe("adjudicateUnbindableNamespaces", () => { }); describe("adjudicateUncarryableNamespace", () => { + it("should return uncarryableNamespace reason when the object is a namespace that is not allowed by the capability", () => { + const result = adjudicateUncarryableNamespace(["default"], { kind: "Namespace", metadata: { name: "pepr-demo" } }); + expect(result).toBe(`Object carries namespace 'pepr-demo' but namespaces allowed by Capability are '["default"]'.`); + }); it("should return uncarryableNamespace reason when the object carries a namespace that is not allowed by the capability", () => { const result = adjudicateUncarryableNamespace(["default"], { metadata: { namespace: "kube-system" } }); expect(result).toBe(