1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

dedicated action button

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen 2021-05-17 17:06:49 +03:00
parent b3da20c425
commit 4b983ae5bd
3 changed files with 72 additions and 54 deletions

View File

@ -2,3 +2,5 @@ apiVersion: v1
kind: Namespace kind: Namespace
metadata: metadata:
name: lens-metrics name: lens-metrics
annotations:
extensionVersion: "{{ version }}"

View File

@ -46,6 +46,7 @@ export interface MetricsConfiguration {
alertManagers: string[]; alertManagers: string[];
replicas: number; replicas: number;
storageClass: string; storageClass: string;
version?: string;
} }
export interface MetricsStatus { export interface MetricsStatus {
@ -77,6 +78,8 @@ export class MetricsFeature {
sc.metadata?.annotations?.["storageclass.beta.kubernetes.io/is-default-class"] === "true" sc.metadata?.annotations?.["storageclass.beta.kubernetes.io/is-default-class"] === "true"
)); ));
config.version = this.latestVersion;
return this.stack.kubectlApplyFolder(this.resourceFolder, config, ["--prune"]); return this.stack.kubectlApplyFolder(this.resourceFolder, config, ["--prune"]);
} }
@ -88,11 +91,11 @@ export class MetricsFeature {
const status: MetricsStatus = { installed: false, canUpgrade: false}; const status: MetricsStatus = { installed: false, canUpgrade: false};
try { try {
const statefulSet = K8sApi.forCluster(this.cluster, K8sApi.StatefulSet); const namespaceApi = K8sApi.forCluster(this.cluster, K8sApi.Namespace);
const prometheus = await statefulSet.get({name: "prometheus", namespace: "lens-metrics"}); const namespace = await namespaceApi.get({name: "lens-metrics"});
if (prometheus?.kind) { if (namespace?.kind) {
const currentVersion = prometheus.spec.template.spec.containers[0].image.split(":")[1]; const currentVersion = namespace.metadata.annotations?.extensionVersion || "0.0.0";
status.installed = true; status.installed = true;
status.canUpgrade = semver.lt(currentVersion, this.latestVersion, true); status.canUpgrade = semver.lt(currentVersion, this.latestVersion, true);

View File

@ -17,6 +17,8 @@ export class MetricsSettings extends React.Component<Props> {
}; };
@observable canUpgrade = false; @observable canUpgrade = false;
@observable upgrading = false; @observable upgrading = false;
@observable changed = false;
@observable inProgress = false;
config: MetricsConfiguration = { config: MetricsConfiguration = {
prometheus: { prometheus: {
@ -44,6 +46,7 @@ export class MetricsSettings extends React.Component<Props> {
feature: MetricsFeature; feature: MetricsFeature;
@computed get isTogglable() { @computed get isTogglable() {
if (this.inProgress) return false;
if (!this.props.cluster.status.active) return false; if (!this.props.cluster.status.active) return false;
if (this.canUpgrade) return false; if (this.canUpgrade) return false;
if (!this.isActiveMetricsProvider) return false; if (!this.isActiveMetricsProvider) return false;
@ -69,7 +72,23 @@ export class MetricsSettings extends React.Component<Props> {
const status = await this.feature.getStatus(); const status = await this.feature.getStatus();
this.canUpgrade = status.canUpgrade; this.canUpgrade = status.canUpgrade;
this.featureStates.prometheus = status.installed;
if (this.canUpgrade) {
this.changed = true;
}
const statefulSet = K8sApi.forCluster(this.props.cluster, K8sApi.StatefulSet);
try {
await statefulSet.get({name: "prometheus", namespace: "lens-metrics"});
this.featureStates.prometheus = true;
} catch(e) {
if (e?.error?.code === 404) {
this.featureStates.prometheus = false;
} else {
this.featureStates.prometheus = undefined;
}
}
const deployment = K8sApi.forCluster(this.props.cluster, K8sApi.Deployment); const deployment = K8sApi.forCluster(this.props.cluster, K8sApi.Deployment);
@ -103,55 +122,47 @@ export class MetricsSettings extends React.Component<Props> {
this.config.kubeStateMetrics.enabled = !!this.featureStates.kubeStateMetrics; this.config.kubeStateMetrics.enabled = !!this.featureStates.kubeStateMetrics;
this.config.nodeExporter.enabled = !!this.featureStates.nodeExporter; this.config.nodeExporter.enabled = !!this.featureStates.nodeExporter;
this.inProgress = true;
try {
if (!this.config.prometheus.enabled && !this.config.kubeStateMetrics.enabled && !this.config.nodeExporter.enabled) { if (!this.config.prometheus.enabled && !this.config.kubeStateMetrics.enabled && !this.config.nodeExporter.enabled) {
await this.feature.uninstall(this.config); await this.feature.uninstall(this.config);
} else { } else {
await this.feature.install(this.config); await this.feature.install(this.config);
} }
} finally {
this.inProgress = false;
this.changed = false;
await this.updateFeatureStates();
}
} }
async togglePrometheus(enabled: boolean) { async togglePrometheus(enabled: boolean) {
this.featureStates.prometheus = enabled; this.featureStates.prometheus = enabled;
this.changed = true;
try {
await this.save();
} catch(error) {
this.featureStates.prometheus = !enabled;
Component.Notifications.error(`Failed to ${enabled ? "enable" : "disable"} Prometheus: ${error}`);
}
} }
async toggleKubeStateMetrics(enabled: boolean) { async toggleKubeStateMetrics(enabled: boolean) {
this.featureStates.kubeStateMetrics = enabled; this.featureStates.kubeStateMetrics = enabled;
this.changed = true;
try {
await this.save();
} catch(error) {
this.featureStates.kubeStateMetrics = !enabled;
Component.Notifications.error(`Failed to ${enabled ? "enable" : "disable"} kube-state-metrics: ${error}`);
}
} }
async toggleNodeExporter(enabled: boolean) { async toggleNodeExporter(enabled: boolean) {
this.featureStates.nodeExporter = enabled; this.featureStates.nodeExporter = enabled;
this.changed = true;
try {
await this.save();
} catch(error) {
this.featureStates.nodeExporter = !enabled;
Component.Notifications.error(`Failed to ${enabled ? "enable" : "disable"} node-exporter: ${error}`);
}
} }
async updateStack() { @computed get buttonLabel() {
this.upgrading = true; if (this.inProgress && this.canUpgrade) return "Upgrading ...";
if (this.inProgress) return "Applying ...";
if (this.canUpgrade) return "Upgrade";
await this.save(); if (this.changed && !this.featureStates.kubeStateMetrics && !this.featureStates.nodeExporter && !this.featureStates.prometheus) {
setTimeout(() => { return "Uninstall";
Component.Notifications.info("Lens Metrics stack updated!", {timeout: 5_000}); }
this.upgrading = false;
this.canUpgrade = false; return "Apply";
}, 1000);
} }
render() { render() {
@ -171,17 +182,6 @@ export class MetricsSettings extends React.Component<Props> {
</p> </p>
</section> </section>
)} )}
{ this.canUpgrade && (
<section>
<Component.SubTitle title="Software Update" />
<Component.Button label={this.upgrading ? "Updating ..." : "Update Now"} primary onClick={() => this.updateStack() } waiting={this.upgrading} />
<small className="hint">
An update is available for enabled metrics components.
</small>
</section>
)}
<section> <section>
<Component.SubTitle title="Prometheus" /> <Component.SubTitle title="Prometheus" />
<Component.FormSwitch <Component.FormSwitch
@ -193,7 +193,7 @@ export class MetricsSettings extends React.Component<Props> {
name="prometheus" name="prometheus"
/> />
} }
label="Install bundled Prometheus metrics stack" label="Enable bundled Prometheus metrics stack"
/> />
<small className="hint"> <small className="hint">
Enable timeseries data visualization (Prometheus stack) for your cluster. Enable timeseries data visualization (Prometheus stack) for your cluster.
@ -211,11 +211,11 @@ export class MetricsSettings extends React.Component<Props> {
name="node-exporter" name="node-exporter"
/> />
} }
label="Install bundled kube-state-metrics stack" label="Enable bundled kube-state-metrics stack"
/> />
<small className="hint"> <small className="hint">
Enable Kubernetes API object metrics for your cluster. Enable Kubernetes API object metrics for your cluster.
Install this only if you don&apos;t have existing kube-state-metrics stack installed. Enable this only if you don&apos;t have existing kube-state-metrics stack installed.
</small> </small>
</section> </section>
@ -230,13 +230,26 @@ export class MetricsSettings extends React.Component<Props> {
name="node-exporter" name="node-exporter"
/> />
} }
label="Install bundled node-exporter stack" label="Enable bundled node-exporter stack"
/> />
<small className="hint"> <small className="hint">
Enable node level metrics for your cluster. Enable node level metrics for your cluster.
Install this only if you don&apos;t have existing node-exporter stack installed. Enable this only if you don&apos;t have existing node-exporter stack installed.
</small> </small>
</section> </section>
<section>
<Component.Button
label={this.buttonLabel}
waiting={this.inProgress}
onClick={() => this.save()}
primary
disabled={!this.changed} />
{this.canUpgrade && (<small className="hint">
An update is available for enabled metrics components.
</small>)}
</section>
</> </>
); );
} }