diff --git a/src/renderer/components/+network-policies/__tests__/network-policy-details.test.tsx b/src/renderer/components/+network-policies/__tests__/network-policy-details.test.tsx
index ff6adb8cefa27..2b6684300f687 100644
--- a/src/renderer/components/+network-policies/__tests__/network-policy-details.test.tsx
+++ b/src/renderer/components/+network-policies/__tests__/network-policy-details.test.tsx
@@ -53,4 +53,19 @@ describe("NetworkPolicyDetails", () => {
expect(await findByTestId(container, "egress-0")).toBeInstanceOf(HTMLElement);
expect(await findByText(container, "foo: bar")).toBeInstanceOf(HTMLElement);
});
+
+ it("should not crash if egress nodeSelector doesn't have matchLabels", async () => {
+ const spec: NetworkPolicySpec = {
+ egress: [{
+ to: [{
+ namespaceSelector: {},
+ }],
+ }],
+ podSelector: {},
+ };
+ const policy = new NetworkPolicy({ metadata: {} as any, spec } as any);
+ const { container } = render();
+
+ expect(container).toBeInstanceOf(HTMLElement);
+ });
});
diff --git a/src/renderer/components/+network-policies/network-policy-details.module.css b/src/renderer/components/+network-policies/network-policy-details.module.css
index 50be1a602466c..a3c06f8616a90 100644
--- a/src/renderer/components/+network-policies/network-policy-details.module.css
+++ b/src/renderer/components/+network-policies/network-policy-details.module.css
@@ -29,4 +29,13 @@
padding-bottom: 16px;
}
}
+
+ ul.policySelectorList {
+ list-style: disc;
+ }
+
+ .policySelectorList ul {
+ list-style: circle;
+ list-style-position: inside;
+ }
}
diff --git a/src/renderer/components/+network-policies/network-policy-details.tsx b/src/renderer/components/+network-policies/network-policy-details.tsx
index e5632ec30d075..ff870bc2cccb7 100644
--- a/src/renderer/components/+network-policies/network-policy-details.tsx
+++ b/src/renderer/components/+network-policies/network-policy-details.tsx
@@ -23,13 +23,15 @@ import styles from "./network-policy-details.module.css";
import React from "react";
import { DrawerItem, DrawerTitle } from "../drawer";
-import { IPolicyIpBlock, IPolicySelector, NetworkPolicy, NetworkPolicyPeer, NetworkPolicyPort } from "../../../common/k8s-api/endpoints/network-policy.api";
+import { IPolicyIpBlock, NetworkPolicy, NetworkPolicyPeer, NetworkPolicyPort } from "../../../common/k8s-api/endpoints/network-policy.api";
import { Badge } from "../badge";
import { SubTitle } from "../layout/sub-title";
import { observer } from "mobx-react";
import type { KubeObjectDetailsProps } from "../kube-object-details";
import { KubeObjectMeta } from "../kube-object-meta";
import logger from "../../../common/logger";
+import type { LabelMatchExpression, LabelSelector } from "../../../common/k8s-api/kube-object";
+import { isEmpty } from "lodash";
interface Props extends KubeObjectDetailsProps {
}
@@ -60,20 +62,57 @@ export class NetworkPolicyDetails extends React.Component {
);
}
- renderIPolicySelector(name: string, selector: IPolicySelector | undefined) {
+ renderMatchLabels(matchLabels: Record | undefined) {
+ if (!matchLabels) {
+ return null;
+ }
+
+ return Object.entries(matchLabels)
+ .map(([key, value]) => {key}: {value});
+ }
+
+ renderMatchExpressions(matchExpressions: LabelMatchExpression[] | undefined) {
+ if (!matchExpressions) {
+ return null;
+ }
+
+ return matchExpressions.map(expr => {
+ switch (expr.operator) {
+ case "DoesNotExist":
+ case "Exists":
+ return {expr.key} ({expr.operator});
+ case "In":
+ case "NotIn":
+ return (
+
+ {expr.key}({expr.operator})
+
+ {expr.values.map((value, index) => - {value}
)}
+
+
+ );
+ }
+ });
+ }
+
+ renderIPolicySelector(name: string, selector: LabelSelector | undefined) {
if (!selector) {
return null;
}
+ const { matchLabels, matchExpressions } = selector;
+
return (
- {
- Object
- .entries(selector.matchLabels)
- .map(data => data.join(": "))
- .join(", ")
- || "(empty)"
- }
+
+ {this.renderMatchLabels(matchLabels)}
+ {this.renderMatchExpressions(matchExpressions)}
+ {
+ (isEmpty(matchLabels) && isEmpty(matchExpressions)) && (
+ - (empty)
+ )
+ }
+
);
}