1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
lens/docs/extensions/guides/resource-stack.md
Jim Ehrismann 143385f337 updating extension api docs for 5.0
Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>
2021-06-17 08:43:20 -04:00

224 lines
7.5 KiB
Markdown

# Resource Stack (Cluster Feature)
```typescript
import { Renderer, Common } from "@k8slens/extensions";
import * as path from "path";
const {
K8sApi: {
ResourceStack,
forCluster,
Pod,
}
} = Renderer;
type ResourceStack = Renderer.K8sApi.ResourceStack;
type Pod = Renderer.K8sApi.Pod;
type KubernetesCluster = Common.Catalog.KubernetesCluster;
export class ExampleResourceStack {
protected stack: ResourceStack;
constructor(protected cluster: KubernetesCluster) {
this.stack = new ResourceStack(cluster, "example-resource-stack");
}
get resourceFolder() {
return path.join(__dirname, "../resources/");
}
install(): Promise<string> {
console.log("installing example-pod");
return this.stack.kubectlApplyFolder(this.resourceFolder);
}
async isInstalled(): Promise<boolean> {
try {
const podApi = forCluster(this.cluster, Pod);
const examplePod = await podApi.get({name: "example-pod", namespace: "default"});
if (examplePod?.kind) {
console.log("found example-pod");
return true;
}
} catch(e) {
console.log("Error getting example-pod:", e);
}
console.log("didn't find example-pod");
return false;
}
async uninstall(): Promise<string> {
console.log("uninstalling example-pod");
return this.stack.kubectlDeleteFolder(this.resourceFolder);
}
}
```
Cluster features are Kubernetes resources that can be applied to and managed within the active cluster.
They can be installed and uninstalled by the Lens user from the cluster **Settings** page.
!!! info
To access the cluster **Settings** page, right-click the relevant cluster in the left side menu and click **Settings**.
The following example shows how to add a cluster feature as part of a `LensRendererExtension`:
```typescript
import { Renderer } from "@k8slens/extensions"
import { ExampleFeature } from "./src/example-feature"
import React from "react"
export default class ExampleFeatureExtension extends Renderer.LensExtension {
clusterFeatures = [
{
title: "Example Feature",
components: {
Description: () => {
return (
<span>
Enable an example feature.
</span>
)
}
},
feature: new ExampleFeature()
}
];
}
```
The properties of the `clusterFeatures` array objects are defined as follows:
* `title` and `components.Description` provide content that appears on the cluster settings page, in the **Features** section.
* `feature` specifies an instance which extends the abstract class `ClusterFeature.Feature`, and specifically implements the following methods:
```typescript
abstract install(cluster: Cluster): Promise<void>;
abstract upgrade(cluster: Cluster): Promise<void>;
abstract uninstall(cluster: Cluster): Promise<void>;
abstract updateStatus(cluster: Cluster): Promise<ClusterFeatureStatus>;
```
The four methods listed above are defined as follows:
* The `install()` method installs Kubernetes resources using the `applyResources()` method, or by directly accessing the [Kubernetes API](../api/README.md).
This method is typically called when a user indicates that they want to install the feature (i.e., by clicking **Install** for the feature in the cluster settings page).
* The `upgrade()` method upgrades the Kubernetes resources already installed, if they are relevant to the feature.
This method is typically called when a user indicates that they want to upgrade the feature (i.e., by clicking **Upgrade** for the feature in the cluster settings page).
* The `uninstall()` method uninstalls Kubernetes resources using the [Kubernetes API](../api/README.md).
This method is typically called when a user indicates that they want to uninstall the feature (i.e., by clicking **Uninstall** for the feature in the cluster settings page).
* The `updateStatus()` method provides the current status information in the `status` field of the `ClusterFeature.Feature` parent class.
Lens periodically calls this method to determine details about the feature's current status.
The implementation of this method should uninstall Kubernetes resources using the Kubernetes api (`K8sApi`)
Consider using the following properties with `updateStatus()`:
* `status.currentVersion` and `status.latestVersion` may be displayed by Lens in the feature's description.
* `status.installed` should be set to `true` if the feature is installed, and `false` otherwise.
* `status.canUpgrade` is set according to a rule meant to determine whether the feature can be upgraded.
This rule can involve `status.currentVersion` and `status.latestVersion`, if desired.
The following shows a very simple implementation of a `ClusterFeature`:
```typescript
import { Renderer, Common } from "@k8slens/extensions";
import * as path from "path";
const {
K8sApi: {
ResourceStack,
forCluster,
StorageClass,
Namespace,
}
} = Renderer;
type ResourceStack = Renderer.K8sApi.ResourceStack;
type Pod = Renderer.K8sApi.Pod;
type KubernetesCluster = Common.Catalog.KubernetesCluster;
export interface MetricsStatus {
installed: boolean;
canUpgrade: boolean;
}
export class ExampleFeature {
protected stack: ResourceStack;
constructor(protected cluster: KubernetesCluster) {
this.stack = new ResourceStack(cluster, this.name);
}
install(): Promise<string> {
return this.stack.kubectlApplyFolder(path.join(__dirname, "../resources/"));
}
upgrade(): Promise<string> {
return this.install(config);
}
async getStatus(): Promise<MetricsStatus> {
const status: MetricsStatus = { installed: false, canUpgrade: false};
try {
const pod = forCluster(cluster, Pod);
const examplePod = await pod.get({name: "example-pod", namespace: "default"});
if (examplePod?.kind) {
status.installed = true;
status.currentVersion = examplePod.spec.containers[0].image.split(":")[1];
status.canUpgrade = true; // a real implementation would perform a check here that is relevant to the specific feature
} else {
status.installed = false;
status.canUpgrade = false;
}
} catch(e) {
if (e?.error?.code === 404) {
status.installed = false;
status.canUpgrade = false;
}
}
return status;
}
async uninstall(): Promise<string> {
return this.stack.kubectlDeleteFolder(this.resourceFolder);
}
}
```
This example implements the `install()` method by invoking the helper `applyResources()` method.
`applyResources()` tries to apply all resources read from all files found in the folder path provided.
In this case the folder path is the `../resources` subfolder relative to the current source code's folder.
The file `../resources/example-pod.yml` could contain:
``` yaml
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: example-pod
image: nginx
```
The example above implements the four methods as follows:
* It implements `upgrade()` by invoking the `install()` method.
Depending on the feature to be supported by an extension, upgrading may require additional and/or different steps.
* It implements `uninstall()` by utilizing the [Kubernetes API](../api/README.md) which Lens provides to delete the `example-pod` applied by the `install()` method.
* It implements `updateStatus()` by using the [Kubernetes API](../api/README.md) which Lens provides to determine whether the `example-pod` is installed, what version is associated with it, and whether it can be upgraded.
The implementation determines what the status is for a specific cluster feature.