6. Kubernetes API
Renderer.K8sApi (and its main-side twin Main.K8sApi) is how an extension
models and talks to Kubernetes resources. The list of built-in resources,
stores, and APIs is large; this page covers the parts you actually build with:
- Defining a custom CRD (the three-class pattern).
- Using built-in resource stores/APIs.
- Cluster query functions (
Renderer.K8s/Main.K8s). - Metrics.
6.1 Defining a custom CRD — the three-class pattern
For a custom resource you export three classes from one model file: the
KubeObject, its KubeApi, and its KubeObjectStore.
import { Renderer } from "@freelensapp/extensions";
export interface ExampleSpec {
title?: string;
active?: boolean;
description?: string;
}
export type ExampleStatus = {};
export class Example extends Renderer.K8sApi.LensExtensionKubeObject<
Renderer.K8sApi.KubeObjectMetadata,
ExampleStatus,
ExampleSpec
> {
static readonly kind = "Example";
static readonly namespaced = true;
static readonly apiBase = "/apis/example.freelens.app/v1alpha1/examples";
static readonly crd: ExampleKubeObjectCRD = {
apiVersions: ["example.freelens.app/v1alpha1"],
plural: "examples",
singular: "example",
shortNames: ["ex"],
title: "Examples",
};
// Accessors are STATIC and take the object as a parameter (see the rule below):
static getTitle(object: Example): string | undefined {
return object.spec.title;
}
}
export class ExampleApi extends Renderer.K8sApi.KubeApi<Example> {}
export class ExampleStore extends Renderer.K8sApi.KubeObjectStore<Example, ExampleApi> {}
KubeApiauto-registers withapiManager(unless you passautoRegister: false).KubeObjectStoreauto-wires the cluster-frame context.LensExtensionKubeObjectprovides staticsgetApi<K,Api>()andgetStore<K,Store>()to resolve the singleton api/store by kind, e.g.Example.getStore<Example>().
LensExtensionKubeObjectCRD shape:
interface LensExtensionKubeObjectCRD {
apiVersions: string[];
plural: string;
singular: string; // required
shortNames?: string[];
}
title is not part of the base type — the example extension extends it with
its own title: string (via ExampleKubeObjectCRD extends
LensExtensionKubeObjectCRD). Do the same if you want extra CRD metadata.
CRITICAL rule: static readonly metadata, no instance methods
The host reads class metadata statically and, at runtime, hands your components plain object copies of the resource data — not instances of your class. Therefore:
- Allowed:
object.spec?.field,object.status?.conditions, host base-class instance methods (object.getName(),object.getNs(),object.getCreationTimestamp(),object.getSearchFields()), and static helpers you write that take the object as a parameter (Example.getTitle(object)). - Forbidden: instance methods you define on the subclass
(
object.getTitle()) — they will not exist at runtime. - Forbidden:
typeof (object as any).method === "function" ? …— always falls through. - Forbidden:
as any— the typedSpec/Statusinterfaces already exist; use them.
Multiple CRD versions live in separate model files (e.g.
example-v1alpha1.ts, example-v1alpha2.ts), each with its own apiBase and
crd.apiVersions. To pick whichever version's CRD is installed at runtime,
try each version's getStore() in order and render the first that resolves.
Registering the CRD's UI
In src/renderer/index.tsx:
kubeObjectDetailItems = [{
kind: Example.kind,
apiVersions: Example.crd.apiVersions,
priority: 10,
components: { Details: (p) => <ExampleDetails {...p} extension={this} /> },
}];
clusterPages = [{ id: "example", components: { Page: ExamplesPage } }];
clusterPageMenus = [{ title: Example.crd.title, target: { pageId: "example" }, components: { Icon: ExampleIcon } }];
6.2 Built-in resources
Renderer.K8sApi re-exports the standard resource model classes, pre-built
API singletons, and pre-built stores, so you can read core resources without
defining your own:
- KubeObject classes:
ConfigMap,PersistentVolume,PersistentVolumeClaim,StorageClass,ResourceQuota,LimitRange,HorizontalPodAutoscaler,PriorityClass,PodDisruptionBudget,RoleBinding,ClusterRole,ClusterRoleBinding,ServiceAccount,DaemonSet,StatefulSet,ReplicaSet,CronJob,NetworkPolicy,EndpointSlice,CustomResourceDefinition,KubeEvent, … (plusPod,Node,Deployment,Ingress,Service,Secret,Namespace,Job). - API singletons:
podsApi,nodesApi,deploymentApi,secretsApi,serviceApi,serviceAccountsApi,roleBindingApi,statefulSetApi,storageClassApi,vpaApi, … (*Apitype-only exports also available). - Stores:
PodStore/podsStore,NodeStore,DeploymentStore,ConfigMapStore,SecretStore,EventStore,NamespaceStore,IngressStore,ServiceStore,CustomResourceStore/CRDResourceStore,CustomResourceDefinitionStore/CRDStore, and many more.
Core classes: KubeObject, KubeApi<Object,Data>, KubeObjectStore<K,A,D>,
KubeJsonApi, apiManager. Metadata types: KubeObjectMetadata,
KubeJsonApiData, KubeJsonApiDataFor, OwnerReference,
ClusterScopedMetadata, NamespaceScopedMetadata, KubeStatus. Patch/loading
types: JsonPatch, KubeObjectStoreLoadAllParams,
KubeObjectStoreLoadingParams.
Mutating through a store (from the example's menu action):
const store = Example.getStore<Example>();
await store.patch(object, { spec: { active } }, "merge");
6.3 Clusters: cluster query functions
Renderer.K8s (renderer, over IPC) and Main.K8s (main, direct) expose the
same function set for CRUD against arbitrary clusters:
| Function | Signature |
|---|---|
queryCluster<T> |
(clusterId, query: ResourceQuery) => Promise<T[]> |
queryClusters<T> |
(clusterIds[], query) => Promise<Map<ClusterId, T[] \| Error>> |
queryAllClusters<T> |
(query) => Promise<Map<ClusterId, T[] \| Error>> (connected only) |
getResource<T> |
(clusterId, query & { name }) => Promise<T \| null> (404 → null) |
applyOnCluster<T extends KubeJsonApiData> |
(clusterId, manifest) => Promise<T> (create-or-update) |
deleteOnCluster |
(clusterId, resource & { name }) => Promise<void> (404 ignored) |
patchOnCluster<T> |
(clusterId, resource & { name }, patch, patchType?) => Promise<T> |
Types: ClusterId, ResourceQuery,
KubeApiPatchType = "strategic" | "merge" | "json" (default "strategic").
To enumerate clusters or find the active one, use
Renderer.Catalog(getAllClusters,getActiveCluster,activeCluster), notK8s— see Catalog.
6.4 Metrics
Types: RequestMetrics, RequestMetricsParams, MetricData, MetricResult.
Feed results into the chart/metrics components in
UI components.
6.5 Object status indicators
KubeObjectStatus / KubeObjectStatusLevel let you surface status badges on
objects. (Note: there is no kubeObjectStatusTexts registration in this
version — see renderer registrations.)