/** * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ import styles from "./network-policy-details.module.scss"; import React from "react"; import { DrawerItem, DrawerTitle } from "../drawer"; 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"; export interface NetworkPolicyDetailsProps extends KubeObjectDetailsProps { } @observer export class NetworkPolicyDetails extends React.Component { renderIPolicyIpBlock(ipBlock: IPolicyIpBlock | undefined) { if (!ipBlock) { return null; } const { cidr, except = [] } = ipBlock; if (!cidr) { return null; } const items = [`cidr: ${cidr}`]; if (except.length > 0) { items.push(`except: ${except.join(", ")}`); } return ( {items.join(", ")} ); } 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 (
      {this.renderMatchLabels(matchLabels)} {this.renderMatchExpressions(matchExpressions)} { (isEmpty(matchLabels) && isEmpty(matchExpressions)) && (
    • (empty)
    • ) }
    ); } renderNetworkPolicyPeers(name: string, peers: NetworkPolicyPeer[] | undefined) { if (!peers) { return null; } return ( <> { peers.map((peer, index) => (
    {this.renderIPolicyIpBlock(peer.ipBlock)} {this.renderIPolicySelector("namespaceSelector", peer.namespaceSelector)} {this.renderIPolicySelector("podSelector", peer.podSelector)}
    )) } ); } renderNetworkPolicyPorts(ports: NetworkPolicyPort[] | undefined) { if (!ports) { return null; } return (
      {ports.map(({ protocol = "TCP", port = "", endPort }, index) => (
    • {protocol}:{port}{typeof endPort === "number" && `:${endPort}`}
    • ))}
    ); } render() { const { object: policy } = this.props; if (!policy) { return null; } if (!(policy instanceof NetworkPolicy)) { logger.error("[NetworkPolicyDetails]: passed object that is not an instanceof NetworkPolicy", policy); return null; } const { ingress, egress } = policy.spec; const selector = policy.getMatchLabels(); return (
    0}> { selector.length > 0 ? policy.getMatchLabels().map(label => ) : `(empty) (Allowing the specific traffic to all pods in this namespace)` } {ingress && ( <> {ingress.map((ingress, i) => (
    {this.renderNetworkPolicyPorts(ingress.ports)} {this.renderNetworkPolicyPeers("From", ingress.from)}
    ))} )} {egress && ( <> {egress.map((egress, i) => (
    {this.renderNetworkPolicyPorts(egress.ports)} {this.renderNetworkPolicyPeers("To", egress.to)}
    ))} )}
    ); } }