mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix custom resources not having a fallback details component (#3542)
This commit is contained in:
parent
a6e91fc34a
commit
77077ef72c
@ -86,6 +86,16 @@ export class KubeStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface KubeObjectStatus {
|
||||||
|
conditions?: {
|
||||||
|
lastTransitionTime: string;
|
||||||
|
message: string;
|
||||||
|
reason: string;
|
||||||
|
status: string;
|
||||||
|
type?: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
export type KubeMetaField = keyof KubeObjectMetadata;
|
export type KubeMetaField = keyof KubeObjectMetadata;
|
||||||
|
|
||||||
export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata, Status = any, Spec = any> implements ItemObject {
|
export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata, Status = any, Spec = any> implements ItemObject {
|
||||||
|
|||||||
@ -24,18 +24,18 @@ import "./crd-resource-details.scss";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import jsonPath from "jsonpath";
|
import jsonPath from "jsonpath";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { computed, makeObservable } from "mobx";
|
|
||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
import { Badge } from "../badge";
|
import { Badge } from "../badge";
|
||||||
import { DrawerItem } from "../drawer";
|
import { DrawerItem } from "../drawer";
|
||||||
import type { KubeObjectDetailsProps } from "../kube-object";
|
import type { KubeObjectDetailsProps } from "../kube-object";
|
||||||
import { crdStore } from "./crd.store";
|
|
||||||
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||||
import { Input } from "../input";
|
import { Input } from "../input";
|
||||||
import type { AdditionalPrinterColumnsV1, CustomResourceDefinition } from "../../api/endpoints/crd.api";
|
import type { AdditionalPrinterColumnsV1, CustomResourceDefinition } from "../../api/endpoints/crd.api";
|
||||||
import { parseJsonPath } from "../../utils/jsonPath";
|
import { parseJsonPath } from "../../utils/jsonPath";
|
||||||
|
import type { KubeObject, KubeObjectMetadata, KubeObjectStatus } from "../../api/kube-object";
|
||||||
|
|
||||||
interface Props extends KubeObjectDetailsProps<CustomResourceDefinition> {
|
interface Props extends KubeObjectDetailsProps<KubeObject> {
|
||||||
|
crd: CustomResourceDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertSpecValue(value: any): any {
|
function convertSpecValue(value: any): any {
|
||||||
@ -60,31 +60,22 @@ function convertSpecValue(value: any): any {
|
|||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class CrdResourceDetails extends React.Component<Props> {
|
export class CrdResourceDetails extends React.Component<Props> {
|
||||||
constructor(props: Props) {
|
renderAdditionalColumns(resource: KubeObject, columns: AdditionalPrinterColumnsV1[]) {
|
||||||
super(props);
|
|
||||||
makeObservable(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get crd() {
|
|
||||||
return crdStore.getByObject(this.props.object);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderAdditionalColumns(crd: CustomResourceDefinition, columns: AdditionalPrinterColumnsV1[]) {
|
|
||||||
return columns.map(({ name, jsonPath: jp }) => (
|
return columns.map(({ name, jsonPath: jp }) => (
|
||||||
<DrawerItem key={name} name={name} renderBoolean>
|
<DrawerItem key={name} name={name} renderBoolean>
|
||||||
{convertSpecValue(jsonPath.value(crd, parseJsonPath(jp.slice(1))))}
|
{convertSpecValue(jsonPath.value(resource, parseJsonPath(jp.slice(1))))}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
renderStatus(crd: CustomResourceDefinition, columns: AdditionalPrinterColumnsV1[]) {
|
renderStatus(customResource: KubeObject<KubeObjectMetadata, KubeObjectStatus, any>, columns: AdditionalPrinterColumnsV1[]) {
|
||||||
const showStatus = !columns.find(column => column.name == "Status") && crd.status?.conditions;
|
const showStatus = !columns.find(column => column.name == "Status") && Array.isArray(customResource.status?.conditions);
|
||||||
|
|
||||||
if (!showStatus) {
|
if (!showStatus) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const conditions = crd.status.conditions
|
const conditions = customResource.status.conditions
|
||||||
.filter(({ type, reason }) => type || reason)
|
.filter(({ type, reason }) => type || reason)
|
||||||
.map(({ type, reason, message, status }) => ({ kind: type || reason, message, status }))
|
.map(({ type, reason, message, status }) => ({ kind: type || reason, message, status }))
|
||||||
.map(({ kind, message, status }, index) => (
|
.map(({ kind, message, status }, index) => (
|
||||||
@ -104,17 +95,16 @@ export class CrdResourceDetails extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { props: { object }, crd } = this;
|
const { props: { object, crd } } = this;
|
||||||
|
|
||||||
if (!object || !crd) {
|
if (!object || !crd) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const className = cssNames("CrdResourceDetails", crd.getResourceKind());
|
|
||||||
const extraColumns = crd.getPrinterColumns();
|
const extraColumns = crd.getPrinterColumns();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={cssNames("CrdResourceDetails", crd.getResourceKind())}>
|
||||||
<KubeObjectMeta object={object} />
|
<KubeObjectMeta object={object} />
|
||||||
{this.renderAdditionalColumns(object, extraColumns)}
|
{this.renderAdditionalColumns(object, extraColumns)}
|
||||||
{this.renderStatus(object, extraColumns)}
|
{this.renderStatus(object, extraColumns)}
|
||||||
|
|||||||
@ -33,6 +33,8 @@ import { crdStore } from "../+custom-resources/crd.store";
|
|||||||
import { KubeObjectMenu } from "./kube-object-menu";
|
import { KubeObjectMenu } from "./kube-object-menu";
|
||||||
import { KubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
|
import { KubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
|
||||||
import logger from "../../../main/logger";
|
import logger from "../../../main/logger";
|
||||||
|
import { CrdResourceDetails } from "../+custom-resources";
|
||||||
|
import { KubeObjectMeta } from "./kube-object-meta";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to store `object.selfLink` to show more info about resource in the details panel.
|
* Used to store `object.selfLink` to show more info about resource in the details panel.
|
||||||
@ -111,10 +113,6 @@ export class KubeObjectDetails extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get isCrdInstance() {
|
|
||||||
return !!crdStore.getByObject(this.object);
|
|
||||||
}
|
|
||||||
|
|
||||||
@disposeOnUnmount
|
@disposeOnUnmount
|
||||||
loader = reaction(() => [
|
loader = reaction(() => [
|
||||||
this.path,
|
this.path,
|
||||||
@ -169,6 +167,23 @@ export class KubeObjectDetails extends React.Component {
|
|||||||
<item.components.Details object={object} key={`object-details-${index}`} />
|
<item.components.Details object={object} key={`object-details-${index}`} />
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if (details.length === 0) {
|
||||||
|
const crd = crdStore.getByObject(object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a fallback so that if a custom resource object doesn't have
|
||||||
|
* any defined details we should try and display at least some details
|
||||||
|
*/
|
||||||
|
if (crd) {
|
||||||
|
details.push(<CrdResourceDetails key={object.getId()} object={object} crd={crd} />);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (details.length === 0) {
|
||||||
|
// if we still don't have any details to show, just show the standard object metadata
|
||||||
|
details.push(<KubeObjectMeta key={object.getId()} object={object} />);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer
|
<Drawer
|
||||||
className="KubeObjectDetails flex column"
|
className="KubeObjectDetails flex column"
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import { ConfigMapDetails } from "../components/+config-maps";
|
|||||||
import { PodDisruptionBudgetDetails } from "../components/+config-pod-disruption-budgets";
|
import { PodDisruptionBudgetDetails } from "../components/+config-pod-disruption-budgets";
|
||||||
import { ResourceQuotaDetails } from "../components/+config-resource-quotas";
|
import { ResourceQuotaDetails } from "../components/+config-resource-quotas";
|
||||||
import { SecretDetails } from "../components/+config-secrets";
|
import { SecretDetails } from "../components/+config-secrets";
|
||||||
import { CRDDetails, CrdResourceDetails } from "../components/+custom-resources";
|
import { CRDDetails } from "../components/+custom-resources";
|
||||||
import { EventDetails } from "../components/+events";
|
import { EventDetails } from "../components/+events";
|
||||||
import { KubeEventDetails } from "../components/+events/kube-event-details";
|
import { KubeEventDetails } from "../components/+events/kube-event-details";
|
||||||
import { NamespaceDetails } from "../components/+namespaces";
|
import { NamespaceDetails } from "../components/+namespaces";
|
||||||
@ -445,12 +445,5 @@ export function intiKubeObjectDetailRegistry() {
|
|||||||
Details: KubeEventDetails,
|
Details: KubeEventDetails,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
kind: "CustomResourceDefinition",
|
|
||||||
apiVersions: ["apiextensions.k8s.io/v1"],
|
|
||||||
components: {
|
|
||||||
Details: CrdResourceDetails,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user