mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
updated cluster features docs
Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>
This commit is contained in:
parent
ee76d81d15
commit
0e9a2d5d18
@ -189,36 +189,6 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Cluster Features
|
|
||||||
|
|
||||||
This extension can register installable features for a cluster.
|
|
||||||
These features are visible in the "Cluster Settings" page.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import React from "react"
|
|
||||||
import { Renderer } from "@k8slens/extensions"
|
|
||||||
import { MyCustomFeature } from "./src/my-custom-feature"
|
|
||||||
|
|
||||||
export default class ExampleExtension extends Renderer.LensExtension {
|
|
||||||
clusterFeatures = [
|
|
||||||
{
|
|
||||||
title: "My Custom Feature",
|
|
||||||
components: {
|
|
||||||
Description: () => {
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
Just an example.
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
feature: new MyCustomFeature()
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### Top Bar Items
|
### Top Bar Items
|
||||||
|
|
||||||
This extension can register custom components to a top bar area.
|
This extension can register custom components to a top bar area.
|
||||||
|
|||||||
BIN
docs/extensions/guides/images/clusterfeature.png
Normal file
BIN
docs/extensions/guides/images/clusterfeature.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 131 KiB |
@ -1,14 +1,31 @@
|
|||||||
# Resource Stack (Cluster Feature) (WIP)
|
# Resource Stack (Cluster Feature)
|
||||||
|
|
||||||
Cluster features are Kubernetes resources that can be applied to and managed within the active cluster.
|
A cluster feature is a set of Kubernetes resources that can be applied to and managed within the active cluster.
|
||||||
The `Renderer.K8sApi.ResourceStack` class provides the functionality to input and apply kubernetes resources to a cluster.
|
The `Renderer.K8sApi.ResourceStack` class provides the functionality to input and apply kubernetes resources to a cluster.
|
||||||
It is up to the extension developer to manage the life cycle of the resource stack.
|
It is up to the extension developer to manage the life cycle of the resource stack.
|
||||||
It could be applied automatically to a cluster by the extension or the end-user could be required to install it, etc. from the cluster **Settings** page.
|
It could be applied automatically to a cluster by the extension, or the end-user could be required to install it.
|
||||||
|
|
||||||
|
The code examples in this section show how to create a resource stack, and define a cluster feature that is configurable from the cluster **Settings** page.
|
||||||
|
|
||||||
!!! info
|
!!! info
|
||||||
To access the cluster **Settings** page, right-click the relevant cluster in the left side menu and click **Settings**.
|
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 using a resource stack as part of a `Renderer.LensExtension`:
|
The resource stack in this example consists of a single kubernetes resource:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: example-pod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: example-pod
|
||||||
|
image: nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
It is simply a pod named `example-pod`, running nginx. Assume this content is in the file `../resources/example-pod.yml`.
|
||||||
|
|
||||||
|
The following code sample shows how to use the `Renderer.K8sApi.ResourceStack` to manage installing and uninstalling this resource stack:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer, Common } from "@k8slens/extensions";
|
import { Renderer, Common } from "@k8slens/extensions";
|
||||||
@ -26,7 +43,7 @@ type ResourceStack = Renderer.K8sApi.ResourceStack;
|
|||||||
type Pod = Renderer.K8sApi.Pod;
|
type Pod = Renderer.K8sApi.Pod;
|
||||||
type KubernetesCluster = Common.Catalog.KubernetesCluster;
|
type KubernetesCluster = Common.Catalog.KubernetesCluster;
|
||||||
|
|
||||||
export class ExampleResourceStack {
|
export class ExampleClusterFeature {
|
||||||
protected stack: ResourceStack;
|
protected stack: ResourceStack;
|
||||||
|
|
||||||
constructor(protected cluster: KubernetesCluster) {
|
constructor(protected cluster: KubernetesCluster) {
|
||||||
@ -66,19 +83,27 @@ export class ExampleResourceStack {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `ExampleResourceStack` cluster feature can be managed by the end-user on the cluster **Settings** page via a `Renderer.LensExtension.entitySettings` entry.
|
The `ExampleClusterFeature` class constructor takes a `Common.Catalog.KubernetesCluster` argument.
|
||||||
|
This is the cluster that the resource stack will be applied to, and the constructor instantiates a `Renderer.K8sApi.ResourceStack` as such.
|
||||||
|
`ExampleClusterFeature` implements an `install()` method which simply invokes the `kubectlApplyFolder()` method of the `Renderer.K8sApi.ResourceStack` class.
|
||||||
|
`kubectlApplyFolder()` applies to the cluster all kubernetes resources found in the folder passed to it, in this case `../resources`.
|
||||||
|
Similarly, `ExampleClusterFeature` implements an `uninstall()` method which simply invokes the `kubectlDeleteFolder()` method of the `Renderer.K8sApi.ResourceStack` class.
|
||||||
|
`kubectlDeleteFolder()` tries to delete from the cluster all kubernetes resources found in the folder passed to it, again in this case `../resources`.
|
||||||
|
|
||||||
|
`ExampleClusterFeature` also implements an `isInstalled()` method, which demonstrates how you can utiliize the kubernetes api to inspect the resource stack status.
|
||||||
|
`isInstalled()` simply tries to find a pod named `example-pod`, as a way to determine if the pod is already installed.
|
||||||
|
This method can be useful in creating a context-sensitive UI for installing/uninstalling the feature, as demonstrated in the next sample code.
|
||||||
|
|
||||||
|
To allow the end-user to control the life cycle of this cluster feature the following code sample shows how to implement a user interface based on React and custom Lens UI components:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Common, Renderer } from "@k8slens/extensions";
|
import { Common, Renderer } from "@k8slens/extensions";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { computed, observable, makeObservable } from "mobx";
|
import { computed, observable, makeObservable } from "mobx";
|
||||||
import { ExampleResourceStack } from "./example-resource-stack";
|
import { ExampleClusterFeature } from "./example-cluster-feature";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
K8sApi: {
|
|
||||||
forCluster, StatefulSet, DaemonSet, Deployment,
|
|
||||||
},
|
|
||||||
Component: {
|
Component: {
|
||||||
SubTitle, Button,
|
SubTitle, Button,
|
||||||
}
|
}
|
||||||
@ -89,7 +114,7 @@ The `ExampleResourceStack` cluster feature can be managed by the end-user on the
|
|||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class ExampleResourceStackSettings extends React.Component<Props> {
|
export class ExampleClusterFeatureSettings extends React.Component<Props> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
@ -98,10 +123,10 @@ The `ExampleResourceStack` cluster feature can be managed by the end-user on the
|
|||||||
@observable installed = false;
|
@observable installed = false;
|
||||||
@observable inProgress = false;
|
@observable inProgress = false;
|
||||||
|
|
||||||
feature: ExampleResourceStack;
|
feature: ExampleClusterFeature;
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
this.feature = new ExampleResourceStack(this.props.cluster);
|
this.feature = new ExampleClusterFeature(this.props.cluster);
|
||||||
|
|
||||||
await this.updateFeatureState();
|
await this.updateFeatureState();
|
||||||
}
|
}
|
||||||
@ -141,7 +166,7 @@ The `ExampleResourceStack` cluster feature can be managed by the end-user on the
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section>
|
<section>
|
||||||
<SubTitle title="Example Resource Stack" />
|
<SubTitle title="Example Cluster Feature using a Resource Stack" />
|
||||||
<Button
|
<Button
|
||||||
label={this.buttonLabel}
|
label={this.buttonLabel}
|
||||||
waiting={this.inProgress}
|
waiting={this.inProgress}
|
||||||
@ -153,3 +178,61 @@ The `ExampleResourceStack` cluster feature can be managed by the end-user on the
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The `ExampleClusterFeatureSettings` class extends `React.Component` and simply renders a subtitle and a button.
|
||||||
|
`ExampleClusterFeatureSettings` takes the cluster as a prop and when the React component has mounted the `ExampleClusterFeature` is instantiated using this cluster (in `componentDidMount()`).
|
||||||
|
The rest of the logic concerns the button appearance and action, based on the `ExampleClusterFeatureSettings` fields `installed` and `inProgress`.
|
||||||
|
The `installed` value is of course determined using the aforementioned `ExampleClusterFeature` method `isInstalled()`.
|
||||||
|
The `inProgress` value is true while waiting for the feature to be installed (or uninstalled).
|
||||||
|
|
||||||
|
Note that the button is a `Renderer.Component.Button` element and this example takes advantage of its `waiting` prop to show a "waiting" animation while the install (or uninstall) is in progress.
|
||||||
|
Using elements from `Renderer.Component` is encouraged, to take advantage of their built-in properties, and to ensure a common look and feel.
|
||||||
|
|
||||||
|
Also note that [MobX 6](https://mobx.js.org/README.html) is used for state management, ensuring that the UI is rerendered when state has changed.
|
||||||
|
The `ExampleClusterFeatureSettings` class is marked as an `@observer`, and its constructor must call `makeObservable()`.
|
||||||
|
As well, the `installed` and `inProgress` fields are marked as `@observable`, ensuring that the button gets rerendered any time these fields change.
|
||||||
|
|
||||||
|
Finally, `ExampleClusterFeatureSettings` needs to be connected to the extension, and would typically appear on the cluster **Settings** page via a `Renderer.LensExtension.entitySettings` entry.
|
||||||
|
The `ExampleExtension` would look like this:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Common, Renderer } from "@k8slens/extensions";
|
||||||
|
import { ExampleClusterFeatureSettings } from "./src/example-cluster-feature-settings"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
export default class ExampleExtension extends Renderer.LensExtension {
|
||||||
|
entitySettings = [
|
||||||
|
{
|
||||||
|
apiVersions: ["entity.k8slens.dev/v1alpha1"],
|
||||||
|
kind: "KubernetesCluster",
|
||||||
|
title: "Example Cluster Feature",
|
||||||
|
priority: 5,
|
||||||
|
components: {
|
||||||
|
View: ({ entity = null }: { entity: Common.Catalog.KubernetesCluster}) => {
|
||||||
|
return (
|
||||||
|
<ExampleClusterFeatureSettings cluster={entity} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
An entity setting is added to the `entitySettings` array field of the `Renderer.LensExtension` class.
|
||||||
|
Because Lens's catalog can contain different kinds of entities, the kind must be identified.
|
||||||
|
For more details about the catalog see the [Catalog Guide](catalog.md).
|
||||||
|
Clusters are a built-in kind, so the `apiVersions` and `kind` fields should be set as above.
|
||||||
|
The `title` is shown as a navigation item on the cluster **Settings** page and the `components.View` is displayed when the navigation item is clicked on.
|
||||||
|
The `components.View` definition above shows how the `ExampleClusterFeatureSettings` element is included, and how its `cluster` prop is set.
|
||||||
|
`priority` determines the order of the entity settings, the higher the number the higher in the navigation panel the setting is placed. The default value is 50.
|
||||||
|
|
||||||
|
The final result looks like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
`ExampleClusterFeature` and `ExampleClusterFeatureSettings` demonstrate a cluster feature for a simple resource stack.
|
||||||
|
In practice a resource stack can include many resources, and require more sophisticated life cycle management (upgrades, partial installations, etc.)
|
||||||
|
Using `Renderer.K8sApi.ResourceStack` and `entitySettings` it is possible to implement solutions for more complex cluster features.
|
||||||
|
The **Lens Metrics** setting (on the cluster **Settings** page) is a good example of an advanced solution.
|
||||||
Loading…
Reference in New Issue
Block a user