import { Minimize2 } from 'lucide-react'; import { NodeSelectorRequirement, Pod } from 'kubernetes-types/core/v1'; import { useMemo } from 'react'; import { Icon } from '@@/Icon'; import { TextTip } from '@@/Tip/TextTip'; import { Application } from '../../types'; import { applicationIsKind } from '../../utils'; type Props = { app?: Application; }; export function PlacementsTable({ app }: Props) { const formPlacements = useAppPlacements(app); return ( <>
Placement preferences and constraints
{!formPlacements.length && ( This application has no pod preference or constraint rules from the application form. See the application YAML for other placement rules. )} {formPlacements.length > 0 && ( {formPlacements.map((placement, i) => ( ))}
Key Value(s)
{placement.key} {placement.values?.join(', ')}
)} ); } // useAppPlacements is a custom hook that returns the placements that relate to the Portainer application form. function useAppPlacements(app?: Application): NodeSelectorRequirement[] { const formPlacements = useMemo(() => { if (!app) { return []; } // firstly get the pod spec const podSpec = applicationIsKind('Pod', app) ? app.spec : app.spec?.template?.spec; // secondly filter all placements to get the placements that are related to the Portainer form. They are: // - preference (s) in spec.affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution const placements = podSpec?.affinity?.nodeAffinity ?.preferredDuringSchedulingIgnoredDuringExecution; // - matchExpressions in preference const placementsWithMatchExpressions = placements?.filter( (placement) => placement?.preference?.matchExpressions ); // - only matchExpressions items with the operator: In const portainerPlacements = placementsWithMatchExpressions?.flatMap( (placement) => placement?.preference?.matchExpressions?.filter( (expression) => expression?.operator === 'In' ) || [] ) || []; return portainerPlacements; }, [app]); return formPlacements; }