1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

chore: Use new typings for pod columns

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2023-04-27 10:37:05 -04:00
parent 721c3b17ff
commit 80458170ad
12 changed files with 247 additions and 266 deletions

View File

@ -28,7 +28,7 @@ import type { ToggleKubeDetailsPane } from "../kube-detail-params/toggle-details
import kubeSelectedUrlParamInjectable from "../kube-detail-params/kube-selected-url.injectable";
import toggleKubeDetailsPaneInjectable from "../kube-detail-params/toggle-details.injectable";
import type { ClusterContext } from "../../cluster-frame-context/cluster-frame-context";
import type { KubeObjectListLayoutColumn, ItemObject } from "@k8slens/list-layout";
import type { GeneralKubeObjectListLayoutColumn, SpecificKubeListLayoutColumn } from "@k8slens/list-layout";
import { kubeObjectListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { sortBy } from "lodash";
@ -54,6 +54,7 @@ export interface KubeObjectListLayoutProps<
* If not provided, ResourceNames is used instead with a fallback to resource kind.
*/
resourceName?: string;
columns?: SpecificKubeListLayoutColumn<K>[];
}
interface Dependencies {
@ -61,9 +62,18 @@ interface Dependencies {
subscribeToStores: SubscribeStores;
kubeSelectedUrlParam: PageParam<string>;
toggleKubeDetailsPane: ToggleKubeDetailsPane;
columns: KubeObjectListLayoutColumn<ItemObject>[];
generalColumns: GeneralKubeObjectListLayoutColumn[];
}
const matchesApiFor = (api: SubscribableStore["api"]) => (column: GeneralKubeObjectListLayoutColumn) => (
column.kind === api.kind
&& (
isString(api.apiVersionWithGroup)
? [column.apiVersion].flat().includes(api.apiVersionWithGroup)
: true
)
);
const getLoadErrorMessage = (error: unknown): string => {
if (error instanceof Error) {
if (error.cause) {
@ -77,7 +87,7 @@ const getLoadErrorMessage = (error: unknown): string => {
return error.message;
}
return `${error}`;
return `${String(error)}`;
};
@observer
@ -152,11 +162,18 @@ class NonInjectedKubeObjectListLayout<
renderTableContents,
renderTableHeader,
columns,
generalColumns,
sortingCallbacks = {},
...layoutProps
} = this.props;
const resourceName = this.props.resourceName || ResourceNames[ResourceKindMap[store.api.kind]] || store.api.kind;
const targetColumns = columns.filter((col) => col.kind === store.api.kind && col.apiVersion === store.api.apiVersionWithGroup);
const targetColumns = [
...(columns ?? []),
...generalColumns.filter(matchesApiFor(store.api)),
];
void items;
void dependentStores;
targetColumns.forEach((col) => {
if (col.sortingCallBack) {
@ -202,12 +219,16 @@ class NonInjectedKubeObjectListLayout<
onDetails={onDetails ?? ((item) => toggleDetails(item.selfLink))}
sortingCallbacks={sortingCallbacks}
renderTableHeader={headers}
renderTableContents={(item) => {
return sortBy([
renderTableContents={(item) => (
sortBy(
[
...(renderTableContents(item).map((content, index) => ({ priority: (20 - index), content }))),
...targetColumns.map((col) => ({ priority: col.priority, content: col.content(item) })),
], (item) => -item.priority).map((value) => value.content);
}}
],
(item) => -item.priority,
)
.map((value) => value.content)
)}
spinnerTestId="kube-object-list-layout-spinner"
{...layoutProps}
/>
@ -225,7 +246,7 @@ export const KubeObjectListLayout = withInjectables<
subscribeToStores: di.inject(subscribeStoresInjectable),
kubeSelectedUrlParam: di.inject(kubeSelectedUrlParamInjectable),
toggleKubeDetailsPane: di.inject(toggleKubeDetailsPaneInjectable),
columns: di.injectMany(kubeObjectListLayoutColumnInjectionToken),
generalColumns: di.injectMany(kubeObjectListLayoutColumnInjectionToken),
}),
}) as <
K extends KubeObject,

View File

@ -4,27 +4,21 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import React from "react";
import type { Pod } from "../../../../common/k8s-api/endpoints";
import type { KubeObjectListLayoutColumn } from "@k8slens/list-layout";
import { kubeObjectListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { KubeObjectAge } from "../../kube-object/age";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
const columnId = "age";
export const podsAgeColumnInjectable = getInjectable({
id: "pods-age-column",
instantiate: (): KubeObjectListLayoutColumn<Pod> => {
const columnId = "age";
return {
instantiate: () => ({
id: columnId,
kind: "Pod",
apiVersion: "v1",
priority: 30,
content: (pod: Pod) => {
return <KubeObjectAge key="age" object={pod} />;
},
content: (pod) => <KubeObjectAge key="age" object={pod} />,
header: { title: "Age", className: "age", sortBy: columnId, id: columnId },
sortingCallBack: (pod: Pod) => -pod.getCreationTimestamp(),
};
},
injectionToken: kubeObjectListLayoutColumnInjectionToken,
sortingCallBack: (pod) => -pod.getCreationTimestamp(),
}),
injectionToken: podListLayoutColumnInjectionToken,
});

View File

@ -6,17 +6,12 @@ import { cssNames } from "@k8slens/utilities";
import { getInjectable } from "@ogre-tools/injectable";
import startCase from "lodash/startCase";
import React from "react";
import type { ContainerStateValues, Pod } from "../../../../common/k8s-api/endpoints";
import type { KubeObjectListLayoutColumn } from "@k8slens/list-layout";
import { kubeObjectListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import type { ContainerStateValues, Pod } from "@k8slens/kube-object";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { StatusBrick } from "../../status-brick";
function renderState(name: string, ready: boolean, key: string, data?: ContainerStateValues) {
if (!data) {
return;
}
return (
const renderState = (name: string, ready: boolean, key: string, data?: ContainerStateValues) => (
data && (
<>
<div className="title">
{name}
@ -33,12 +28,14 @@ function renderState(name: string, ready: boolean, key: string, data?: Container
</React.Fragment>
))}
</>
);
}
)
);
function renderContainersStatus(pod: Pod) {
return pod.getContainerStatuses().map(({ name, state, ready }) => {
return (
const renderContainersStatus = (pod: Pod) => (
<>
{
pod.getContainerStatuses()
.map(({ name, state, ready }) => (
<StatusBrick
key={name}
className={cssNames(state, { ready })}
@ -56,31 +53,28 @@ function renderContainersStatus(pod: Pod) {
),
}}
/>
);
});
}
))
}
</>
);
const columnId = "containers";
export const podsContainersColumnInjectable = getInjectable({
id: "pods-containers-column",
instantiate: (): KubeObjectListLayoutColumn<Pod> => {
const columnId = "containers";
return {
instantiate: () => ({
id: columnId,
kind: "Pod",
apiVersion: "v1",
priority: 80,
content: (pod: Pod) => {
return renderContainersStatus(pod);
},
content: renderContainersStatus,
header: {
title: "Containers",
className: "containers",
sortBy: columnId,
id: columnId,
},
sortingCallBack: (pod: Pod) => pod.getContainerStatuses().length,
};
},
injectionToken: kubeObjectListLayoutColumnInjectionToken,
sortingCallBack: (pod) => pod.getContainerStatuses().length,
}),
injectionToken: podListLayoutColumnInjectionToken,
});

View File

@ -5,23 +5,20 @@
import { getConvertedParts } from "@k8slens/utilities";
import { getInjectable } from "@ogre-tools/injectable";
import React from "react";
import type { Pod } from "../../../../common/k8s-api/endpoints";
import type { KubeObjectListLayoutColumn } from "@k8slens/list-layout";
import { kubeObjectListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import type { Pod } from "@k8slens/kube-object";
import { Tooltip } from "@k8slens/tooltip";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
const columnId = "name";
export const podsNameColumnInjectable = getInjectable({
id: "pods-name-column",
instantiate: (): KubeObjectListLayoutColumn<Pod> => {
const columnId = "name";
return {
instantiate: () => ({
id: columnId,
kind: "Pod",
apiVersion: "v1",
priority: 100,
content: (pod: Pod) => {
return (
content: (pod: Pod) => (
<>
<span id={`list-pod-name-${pod.getId()}`} data-testid={`list-pod-name-${pod.getId()}`}>
{pod.getName()}
@ -30,13 +27,11 @@ export const podsNameColumnInjectable = getInjectable({
{pod.getName()}
</Tooltip>
</>
);
},
),
header: { title: "Name", className: "name", sortBy: columnId, id: columnId },
sortingCallBack: (pod: Pod) => getConvertedParts(pod.getName()),
searchFilter: (pod: Pod) => pod.getSearchFields(),
};
},
injectionToken: kubeObjectListLayoutColumnInjectionToken,
sortingCallBack: (pod) => getConvertedParts(pod.getName()),
searchFilter: (pod) => pod.getSearchFields(),
}),
injectionToken: podListLayoutColumnInjectionToken,
});

View File

@ -5,27 +5,21 @@
import { getInjectable } from "@ogre-tools/injectable";
import React from "react";
import { NamespaceSelectBadge } from "../../namespaces/namespace-select-badge";
import type { Pod } from "../../../../common/k8s-api/endpoints";
import type { KubeObjectListLayoutColumn } from "@k8slens/list-layout";
import { kubeObjectListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
const columnId = "namespace";
export const podsNamespaceColumnInjectable = getInjectable({
id: "pods-namespace-column",
instantiate: (): KubeObjectListLayoutColumn<Pod> => {
const columnId = "namespace";
return {
instantiate: () => ({
id: columnId,
kind: "Pod",
apiVersion: "v1",
priority: 90,
content: (pod: Pod) => {
return (<NamespaceSelectBadge key="namespace" namespace={pod.getNs()} />);
},
content: (pod) => <NamespaceSelectBadge key="namespace" namespace={pod.getNs()} />,
header: { title: "Namespace", className: "namespace", sortBy: columnId, id: columnId },
sortingCallBack: (pod: Pod) => pod.getNs(),
};
},
injectionToken: kubeObjectListLayoutColumnInjectionToken,
sortingCallBack: (pod) => pod.getNs(),
}),
injectionToken: podListLayoutColumnInjectionToken,
});

View File

@ -6,16 +6,14 @@ import { getInjectable } from "@ogre-tools/injectable";
import React from "react";
import { Link } from "react-router-dom";
import nodeApiInjectable from "../../../../common/k8s-api/endpoints/node.api.injectable";
import type { Pod } from "../../../../common/k8s-api/endpoints";
import { Badge } from "../../badge";
import getDetailsUrlInjectable from "../../kube-detail-params/get-details-url.injectable";
import type { KubeObjectListLayoutColumn } from "@k8slens/list-layout";
import { kubeObjectListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { stopPropagation } from "@k8slens/utilities";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
export const podsNodeColumnInjectable = getInjectable({
id: "pods-node-column",
instantiate: (di): KubeObjectListLayoutColumn<Pod> => {
instantiate: (di) => {
const getDetailsUrl = di.inject(getDetailsUrlInjectable);
const nodeApi = di.inject(nodeApiInjectable);
const columnId = "node";
@ -25,8 +23,9 @@ export const podsNodeColumnInjectable = getInjectable({
kind: "Pod",
apiVersion: "v1",
priority: 50,
content: (pod: Pod) => {
return pod.getNodeName() ? (
content: (pod) => (
pod.getNodeName()
? (
<Badge
flat
key="node"
@ -35,17 +34,17 @@ export const podsNodeColumnInjectable = getInjectable({
expandable={false}
>
<Link
to={getDetailsUrl(nodeApi.getUrl({ name: pod.getNodeName() }))}
to={getDetailsUrl(nodeApi.formatUrlForNotListing({ name: pod.getNodeName() }))}
onClick={stopPropagation}>
{pod.getNodeName()}
</Link>
</Badge>
)
: "";
},
: ""
),
header: { title: "Node", className: "node", sortBy: columnId, id: columnId },
sortingCallBack: (pod: Pod) => pod.getNodeName(),
sortingCallBack: (pod) => pod.getNodeName(),
};
},
injectionToken: kubeObjectListLayoutColumnInjectionToken,
injectionToken: podListLayoutColumnInjectionToken,
});

View File

@ -7,15 +7,13 @@ import { getInjectable } from "@ogre-tools/injectable";
import React from "react";
import { Link } from "react-router-dom";
import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable";
import type { Pod } from "../../../../common/k8s-api/endpoints";
import { Badge } from "../../badge";
import getDetailsUrlInjectable from "../../kube-detail-params/get-details-url.injectable";
import type { KubeObjectListLayoutColumn } from "@k8slens/list-layout";
import { kubeObjectListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
export const podsOwnersColumnInjectable = getInjectable({
id: "pods-owners-column",
instantiate: (di): KubeObjectListLayoutColumn<Pod> => {
instantiate: (di) => {
const getDetailsUrl = di.inject(getDetailsUrlInjectable);
const apiManager = di.inject(apiManagerInjectable);
const columnId = "owners";
@ -25,8 +23,8 @@ export const podsOwnersColumnInjectable = getInjectable({
kind: "Pod",
apiVersion: "v1",
priority: 60,
content: (pod: Pod) => {
return pod.getOwnerRefs().map(ref => {
content: (pod) => (
pod.getOwnerRefs().map(ref => {
const { kind, name } = ref;
const detailsLink = getDetailsUrl(apiManager.lookupApiLink(ref, pod));
@ -42,12 +40,12 @@ export const podsOwnersColumnInjectable = getInjectable({
</Link>
</Badge>
);
});
},
})
),
header: { title: "Controlled By", className: "owners", sortBy: columnId, id: columnId },
sortingCallBack: (pod: Pod) => pod.getOwnerRefs().map(ref => ref.kind),
sortingCallBack: (pod) => pod.getOwnerRefs().map(ref => ref.kind),
};
},
injectionToken: kubeObjectListLayoutColumnInjectionToken,
injectionToken: podListLayoutColumnInjectionToken,
});

View File

@ -3,27 +3,21 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { Pod } from "../../../../common/k8s-api/endpoints";
import type { KubeObjectListLayoutColumn } from "@k8slens/list-layout";
import { kubeObjectListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
const columnId = "qos";
export const podsQosColumnInjectable = getInjectable({
id: "pods-qos-column",
instantiate: (): KubeObjectListLayoutColumn<Pod> => {
const columnId = "qos";
return {
instantiate: () => ({
id: columnId,
kind: "Pod",
apiVersion: "v1",
priority: 40,
content: (pod: Pod) => {
return pod.getQosClass();
},
content: (pod) => pod.getQosClass(),
header: { title: "QoS", className: "qos", sortBy: columnId, id: columnId },
sortingCallBack: (pod: Pod) => pod.getQosClass(),
};
},
injectionToken: kubeObjectListLayoutColumnInjectionToken,
sortingCallBack: (pod) => pod.getQosClass(),
}),
injectionToken: podListLayoutColumnInjectionToken,
});

View File

@ -3,27 +3,21 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { Pod } from "../../../../common/k8s-api/endpoints";
import type { KubeObjectListLayoutColumn } from "@k8slens/list-layout";
import { kubeObjectListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
const columnId = "restarts";
export const podsRestartsColumnInjectable = getInjectable({
id: "pods-restarts-column",
instantiate: (): KubeObjectListLayoutColumn<Pod> => {
const columnId = "restarts";
return {
instantiate: () => ({
id: columnId,
kind: "Pod",
apiVersion: "v1",
priority: 70,
content: (pod: Pod) => {
return pod.getRestartsCount();
},
content: (pod) => pod.getRestartsCount(),
header: { title: "Restarts", className: "restarts", sortBy: columnId, id: columnId },
sortingCallBack: (pod: Pod) => pod.getRestartsCount(),
};
},
injectionToken: kubeObjectListLayoutColumnInjectionToken,
sortingCallBack: (pod) => pod.getRestartsCount(),
}),
injectionToken: podListLayoutColumnInjectionToken,
});

View File

@ -4,27 +4,24 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { kebabCase } from "lodash";
import type { Pod } from "../../../../common/k8s-api/endpoints";
import type { KubeObjectListLayoutColumn } from "@k8slens/list-layout";
import { kubeObjectListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
const columnId = "status";
export const podsStatusColumnInjectable = getInjectable({
id: "pods-status-column",
instantiate: (): KubeObjectListLayoutColumn<Pod> => {
const columnId = "status";
return {
instantiate: () => ({
id: columnId,
kind: "Pod",
apiVersion: "v1",
priority: 0,
content: (pod: Pod) => {
return { title: pod.getStatusMessage(), className: kebabCase(pod.getStatusMessage()) };
},
content: (pod) => ({
title: pod.getStatusMessage(),
className: kebabCase(pod.getStatusMessage()),
}),
header: { title: "Status", className: "status", sortBy: columnId, id: columnId },
sortingCallBack: (pod: Pod) => pod.getStatusMessage(),
searchFilter: (pod: Pod) => pod.getStatusMessage(),
};
},
injectionToken: kubeObjectListLayoutColumnInjectionToken,
sortingCallBack: (pod) => pod.getStatusMessage(),
searchFilter: (pod) => pod.getStatusMessage(),
}),
injectionToken: podListLayoutColumnInjectionToken,
});

View File

@ -4,28 +4,22 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import React from "react";
import type { Pod } from "../../../../common/k8s-api/endpoints";
import type { KubeObjectListLayoutColumn } from "@k8slens/list-layout";
import { kubeObjectListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { KubeObjectStatusIcon } from "../../kube-object-status-icon";
const columnId = "qos";
export const podsQosColumnInjectable = getInjectable({
id: "pods-status-icon-column",
instantiate: (): KubeObjectListLayoutColumn<Pod> => {
const columnId = "qos";
return {
instantiate: () => ({
id: columnId,
kind: "Pod",
apiVersion: "v1",
priority: 99,
content: (pod: Pod) => {
return <KubeObjectStatusIcon key="icon" object={pod} />;
},
content: (pod) => <KubeObjectStatusIcon key="icon" object={pod} />,
header: { className: "warning", showWithColumn: "name" },
sortingCallBack: (pod: Pod) => pod.getQosClass(),
};
},
injectionToken: kubeObjectListLayoutColumnInjectionToken,
sortingCallBack: (pod) => pod.getQosClass(),
}),
injectionToken: podListLayoutColumnInjectionToken,
});

View File

@ -14,16 +14,22 @@ import type { EventStore } from "../events/store";
import type { PodStore } from "./store";
import eventStoreInjectable from "../events/store.injectable";
import podStoreInjectable from "./store.injectable";
import type { SpecificKubeListLayoutColumn } from "@k8slens/list-layout";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import type { Pod } from "@k8slens/kube-object";
interface Dependencies {
eventStore: EventStore;
podStore: PodStore;
columns: SpecificKubeListLayoutColumn<Pod>[];
}
@observer
class NonInjectedPods extends React.Component<Dependencies> {
render() {
const { podStore, eventStore } = this.props;
const NonInjectedPods = observer((props: Dependencies) => {
const {
columns,
eventStore,
podStore,
} = props;
return (
<SiblingsInTabLayout>
@ -39,16 +45,17 @@ class NonInjectedPods extends React.Component<Dependencies> {
renderHeaderTitle="Pods"
renderTableHeader={[]}
renderTableContents={() => []}
columns={columns}
/>
</SiblingsInTabLayout>
);
}
}
});
export const Pods = withInjectables<Dependencies>(NonInjectedPods, {
getProps: (di, props) => ({
...props,
eventStore: di.inject(eventStoreInjectable),
podStore: di.inject(podStoreInjectable),
columns: di.injectMany(podListLayoutColumnInjectionToken),
}),
});