mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
228 lines
5.3 KiB
TypeScript
228 lines
5.3 KiB
TypeScript
/**
|
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
*/
|
|
|
|
import { KubeCreationError, KubeObject } from "../kube-object";
|
|
import { KubeApi } from "../kube-api";
|
|
import { crdResourcesURL } from "../../routes";
|
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
|
import type { KubeJsonApiData } from "../kube-json-api";
|
|
|
|
type AdditionalPrinterColumnsCommon = {
|
|
name: string;
|
|
type: "integer" | "number" | "string" | "boolean" | "date";
|
|
priority: number;
|
|
description: string;
|
|
};
|
|
|
|
export type AdditionalPrinterColumnsV1 = AdditionalPrinterColumnsCommon & {
|
|
jsonPath: string;
|
|
};
|
|
|
|
type AdditionalPrinterColumnsV1Beta = AdditionalPrinterColumnsCommon & {
|
|
JSONPath: string;
|
|
};
|
|
|
|
export interface CRDVersion {
|
|
name: string;
|
|
served: boolean;
|
|
storage: boolean;
|
|
schema?: object; // required in v1 but not present in v1beta
|
|
additionalPrinterColumns?: AdditionalPrinterColumnsV1[];
|
|
}
|
|
|
|
export interface CustomResourceDefinitionSpec {
|
|
group: string;
|
|
/**
|
|
* @deprecated for apiextensions.k8s.io/v1 but used in v1beta1
|
|
*/
|
|
version?: string;
|
|
names: {
|
|
plural: string;
|
|
singular: string;
|
|
kind: string;
|
|
listKind: string;
|
|
};
|
|
scope: "Namespaced" | "Cluster";
|
|
/**
|
|
* @deprecated for apiextensions.k8s.io/v1 but used in v1beta1
|
|
*/
|
|
validation?: object;
|
|
versions?: CRDVersion[];
|
|
conversion: {
|
|
strategy?: string;
|
|
webhook?: any;
|
|
};
|
|
/**
|
|
* @deprecated for apiextensions.k8s.io/v1 but used in v1beta1
|
|
*/
|
|
additionalPrinterColumns?: AdditionalPrinterColumnsV1Beta[];
|
|
}
|
|
|
|
export interface CustomResourceDefinition {
|
|
spec: CustomResourceDefinitionSpec;
|
|
status: {
|
|
conditions: {
|
|
lastTransitionTime: string;
|
|
message: string;
|
|
reason: string;
|
|
status: string;
|
|
type?: string;
|
|
}[];
|
|
acceptedNames: {
|
|
plural: string;
|
|
singular: string;
|
|
kind: string;
|
|
shortNames: string[];
|
|
listKind: string;
|
|
};
|
|
storedVersions: string[];
|
|
};
|
|
}
|
|
|
|
export interface CRDApiData extends KubeJsonApiData {
|
|
spec: object; // TODO: make better
|
|
}
|
|
|
|
export class CustomResourceDefinition extends KubeObject {
|
|
static kind = "CustomResourceDefinition";
|
|
static namespaced = false;
|
|
static apiBase = "/apis/apiextensions.k8s.io/v1/customresourcedefinitions";
|
|
|
|
constructor(data: CRDApiData) {
|
|
super(data);
|
|
|
|
if (!data.spec || typeof data.spec !== "object") {
|
|
throw new KubeCreationError("Cannot create a CustomResourceDefinition from an object without spec", data);
|
|
}
|
|
}
|
|
|
|
getResourceUrl() {
|
|
return crdResourcesURL({
|
|
params: {
|
|
group: this.getGroup(),
|
|
name: this.getPluralName(),
|
|
},
|
|
});
|
|
}
|
|
|
|
getResourceApiBase() {
|
|
const { group } = this.spec;
|
|
|
|
return `/apis/${group}/${this.getVersion()}/${this.getPluralName()}`;
|
|
}
|
|
|
|
getPluralName() {
|
|
return this.getNames().plural;
|
|
}
|
|
|
|
getResourceKind() {
|
|
return this.spec.names.kind;
|
|
}
|
|
|
|
getResourceTitle() {
|
|
const name = this.getPluralName();
|
|
|
|
return name[0].toUpperCase() + name.slice(1);
|
|
}
|
|
|
|
getGroup() {
|
|
return this.spec.group;
|
|
}
|
|
|
|
getScope() {
|
|
return this.spec.scope;
|
|
}
|
|
|
|
getPreferedVersion(): CRDVersion {
|
|
const { apiVersion } = this;
|
|
|
|
switch (apiVersion) {
|
|
case "apiextensions.k8s.io/v1":
|
|
for (const version of this.spec.versions) {
|
|
if (version.storage) {
|
|
return version;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case "apiextensions.k8s.io/v1beta1": {
|
|
const { additionalPrinterColumns: apc } = this.spec;
|
|
const additionalPrinterColumns = apc?.map(({ JSONPath, ...apc }) => ({ ...apc, jsonPath: JSONPath }));
|
|
|
|
return {
|
|
name: this.spec.version,
|
|
served: true,
|
|
storage: true,
|
|
schema: this.spec.validation,
|
|
additionalPrinterColumns,
|
|
};
|
|
}
|
|
}
|
|
|
|
throw new Error(`Unknown apiVersion=${apiVersion}: Failed to find a version for CustomResourceDefinition ${this.metadata.name}`);
|
|
}
|
|
|
|
getVersion() {
|
|
return this.getPreferedVersion().name;
|
|
}
|
|
|
|
isNamespaced() {
|
|
return this.getScope() === "Namespaced";
|
|
}
|
|
|
|
getStoredVersions() {
|
|
return this.status.storedVersions.join(", ");
|
|
}
|
|
|
|
getNames() {
|
|
return this.spec.names;
|
|
}
|
|
|
|
getConversion() {
|
|
return JSON.stringify(this.spec.conversion);
|
|
}
|
|
|
|
getPrinterColumns(ignorePriority = true): AdditionalPrinterColumnsV1[] {
|
|
const columns = this.getPreferedVersion().additionalPrinterColumns ?? [];
|
|
|
|
return columns
|
|
.filter(column => column.name.toLowerCase() != "age" && (ignorePriority || !column.priority));
|
|
}
|
|
|
|
getValidation() {
|
|
return JSON.stringify(this.getPreferedVersion().schema, null, 2);
|
|
}
|
|
|
|
getConditions() {
|
|
if (!this.status?.conditions) return [];
|
|
|
|
return this.status.conditions.map(condition => {
|
|
const { message, reason, lastTransitionTime, status } = condition;
|
|
|
|
return {
|
|
...condition,
|
|
isReady: status === "True",
|
|
tooltip: `${message || reason} (${lastTransitionTime})`,
|
|
};
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Only available within kubernetes cluster pages
|
|
*/
|
|
let crdApi: KubeApi<CustomResourceDefinition>;
|
|
|
|
if (isClusterPageContext()) {
|
|
crdApi = new KubeApi<CustomResourceDefinition>({
|
|
objectConstructor: CustomResourceDefinition,
|
|
checkPreferredVersion: true,
|
|
});
|
|
}
|
|
|
|
export {
|
|
crdApi,
|
|
};
|