mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Allow extensions to define cluster features (#1125)
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
1 parent
f3a0059355
commit
62ae7771df
81 files changed
+4069
-510
No files matched your search
@@ -1,72 +1,87 @@
|
||||
import React from "react";
|
||||
import { observable, reaction, comparer } from "mobx";
|
||||
import { observer, disposeOnUnmount } from "mobx-react";
|
||||
import { clusterIpc } from "../../../../common/cluster-ipc";
|
||||
import { Cluster } from "../../../../main/cluster";
|
||||
import { Button } from "../../button";
|
||||
import { Notifications } from "../../notifications";
|
||||
import { Spinner } from "../../spinner";
|
||||
import { ClusterFeature } from "../../../../extensions/cluster-feature";
|
||||
import { interval } from "../../../utils";
|
||||
|
||||
interface Props {
|
||||
cluster: Cluster
|
||||
feature: string
|
||||
feature: ClusterFeature
|
||||
}
|
||||
|
||||
@observer
|
||||
export class InstallFeature extends React.Component<Props> {
|
||||
@observable loading = false;
|
||||
@observable message = "";
|
||||
|
||||
componentDidMount() {
|
||||
const feature = this.props.feature
|
||||
const cluster = this.props.cluster
|
||||
const statusUpdate = interval(20, () => {
|
||||
feature.updateStatus(cluster)
|
||||
})
|
||||
statusUpdate.start(true)
|
||||
|
||||
disposeOnUnmount(this, () => {
|
||||
statusUpdate.stop()
|
||||
})
|
||||
|
||||
disposeOnUnmount(this,
|
||||
reaction(() => this.props.cluster.features[this.props.feature], () => {
|
||||
reaction(() => feature.status.installed, () => {
|
||||
this.loading = false;
|
||||
this.message = ""
|
||||
}, { equals: comparer.structural })
|
||||
);
|
||||
}
|
||||
|
||||
getActionButtons() {
|
||||
const { cluster, feature } = this.props;
|
||||
const features = cluster.features[feature];
|
||||
const disabled = !cluster.isAdmin || this.loading;
|
||||
const loadingIcon = this.loading ? <Spinner/> : null;
|
||||
if (!features) return null;
|
||||
return (
|
||||
<div className="flex gaps align-center">
|
||||
{features.canUpgrade &&
|
||||
{feature.status.canUpgrade &&
|
||||
<Button
|
||||
primary
|
||||
disabled={disabled}
|
||||
onClick={this.runAction(() =>
|
||||
clusterIpc.upgradeFeature.invokeFromRenderer(cluster.id, feature))
|
||||
}
|
||||
feature.upgrade(cluster)
|
||||
)}
|
||||
>
|
||||
Upgrade
|
||||
</Button>
|
||||
}
|
||||
{features.installed &&
|
||||
{feature.status.installed &&
|
||||
<Button
|
||||
accent
|
||||
disabled={disabled}
|
||||
onClick={this.runAction(() =>
|
||||
clusterIpc.uninstallFeature.invokeFromRenderer(cluster.id, feature))
|
||||
}
|
||||
onClick={this.runAction(async () => {
|
||||
this.message = "Uninstalling feature ..."
|
||||
feature.uninstall(cluster)
|
||||
})}
|
||||
>
|
||||
Uninstall
|
||||
</Button>
|
||||
}
|
||||
{!features.installed && !features.canUpgrade &&
|
||||
{!feature.status.installed && !feature.status.canUpgrade &&
|
||||
<Button
|
||||
primary
|
||||
disabled={disabled}
|
||||
onClick={this.runAction(() =>
|
||||
clusterIpc.installFeature.invokeFromRenderer(cluster.id, feature))
|
||||
}
|
||||
onClick={this.runAction(async () =>{
|
||||
this.message = "Installing feature ..."
|
||||
feature.install(cluster)
|
||||
})}
|
||||
>
|
||||
Install
|
||||
</Button>
|
||||
}
|
||||
{loadingIcon}
|
||||
{!cluster.isAdmin && <span className='admin-note'>Actions can only be performed by admins.</span>}
|
||||
{cluster.isAdmin && this.loading && this.message !== "" && <span className='admin-note'>{this.message}</span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -90,4 +105,4 @@ export class InstallFeature extends React.Component<Props> {
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,7 @@ import React from "react";
|
||||
import { Cluster } from "../../../main/cluster";
|
||||
import { InstallFeature } from "./components/install-feature";
|
||||
import { SubTitle } from "../layout/sub-title";
|
||||
import { MetricsFeature } from "../../../features/metrics";
|
||||
import { UserModeFeature } from "../../../features/user-mode";
|
||||
import { clusterFeatureRegistry } from "../../../extensions/registries/cluster-feature-registry";
|
||||
|
||||
interface Props {
|
||||
cluster: Cluster;
|
||||
@@ -12,31 +11,20 @@ interface Props {
|
||||
export class Features extends React.Component<Props> {
|
||||
render() {
|
||||
const { cluster } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Features</h2>
|
||||
<InstallFeature cluster={cluster} feature={MetricsFeature.id}>
|
||||
<>
|
||||
<SubTitle title="Metrics"/>
|
||||
<p>
|
||||
Enable timeseries data visualization (Prometheus stack) for your cluster.
|
||||
Install this only if you don't have existing Prometheus stack installed.
|
||||
You can see preview of manifests{" "}
|
||||
<a href="https://github.com/lensapp/lens/tree/master/src/features/metrics" target="_blank">here</a>.
|
||||
</p>
|
||||
</>
|
||||
</InstallFeature>
|
||||
<InstallFeature cluster={cluster} feature={UserModeFeature.id}>
|
||||
<>
|
||||
<SubTitle title="User Mode"/>
|
||||
<p>
|
||||
User Mode feature enables non-admin users to see namespaces they have access to.{" "}
|
||||
This is achieved by configuring RBAC rules so that every authenticated user is granted to list namespaces.
|
||||
</p>
|
||||
</>
|
||||
</InstallFeature>
|
||||
{ clusterFeatureRegistry.getItems().map((f) => {
|
||||
return (
|
||||
<InstallFeature cluster={cluster} feature={f.feature}>
|
||||
<>
|
||||
<SubTitle title={f.title}/>
|
||||
<p><f.components.Description /></p>
|
||||
</>
|
||||
</InstallFeature>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user