remove ClusterFeature

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen committed 2021-05-10 09:29:10 +03:00
1 parent f550018f39
commit f47e2a8477
10 files changed
+207 -224

No files matched your search

@@ -2,3 +2,5 @@ apiVersion: v1
kind: Namespace
metadata:
name: lens-metrics
labels:
app: lens-metrics
@@ -1,4 +1,4 @@
import { ClusterFeature, Catalog, K8sApi } from "@k8slens/extensions";
import { Catalog, K8sApi } from "@k8slens/extensions";
import semver from "semver";
import * as path from "path";
@@ -27,86 +27,67 @@ export interface MetricsConfiguration {
storageClass: string;
}
export class MetricsFeature extends ClusterFeature.Feature {
export interface MetricsStatus {
installed: boolean;
canUpgrade: boolean;
}
export class MetricsFeature {
name = "metrics";
latestVersion = "v2.19.3-lens1";
templateContext: MetricsConfiguration = {
prometheus: {
enabled: false
},
persistence: {
enabled: false,
storageClass: null,
size: "20G",
},
nodeExporter: {
enabled: false,
},
retention: {
time: "2d",
size: "5GB",
},
kubeStateMetrics: {
enabled: false,
},
alertManagers: null,
replicas: 1,
storageClass: null,
};
protected stack: K8sApi.ResourceStack;
async install(cluster: Catalog.KubernetesCluster): Promise<void> {
constructor(protected cluster: Catalog.KubernetesCluster) {
this.stack = new K8sApi.ResourceStack(cluster);
}
get resourceFolder() {
return path.join(__dirname, "../resources/");
}
async install(config: MetricsConfiguration): Promise<string> {
// Check if there are storageclasses
const storageClassApi = K8sApi.forCluster(cluster, K8sApi.StorageClass);
const storageClassApi = K8sApi.forCluster(this.cluster, K8sApi.StorageClass);
const scs = await storageClassApi.list();
this.templateContext.persistence.enabled = scs.some(sc => (
config.persistence.enabled = scs.some(sc => (
sc.metadata?.annotations?.["storageclass.kubernetes.io/is-default-class"] === "true" ||
sc.metadata?.annotations?.["storageclass.beta.kubernetes.io/is-default-class"] === "true"
));
await super.applyResources(cluster, path.join(__dirname, "../resources/"));
return this.stack.kubectlApplyFolder(this.resourceFolder, config);
}
async upgrade(cluster: Catalog.KubernetesCluster): Promise<void> {
return this.install(cluster);
async upgrade(config: MetricsConfiguration): Promise<string> {
return this.install(config);
}
async updateStatus(cluster: Catalog.KubernetesCluster): Promise<ClusterFeature.FeatureStatus> {
async getStatus(): Promise<MetricsStatus> {
const status: MetricsStatus = { installed: false, canUpgrade: false};
try {
const statefulSet = K8sApi.forCluster(cluster, K8sApi.StatefulSet);
const statefulSet = K8sApi.forCluster(this.cluster, K8sApi.StatefulSet);
const prometheus = await statefulSet.get({name: "prometheus", namespace: "lens-metrics"});
if (prometheus?.kind) {
this.status.installed = true;
this.status.currentVersion = prometheus.spec.template.spec.containers[0].image.split(":")[1];
this.status.canUpgrade = semver.lt(this.status.currentVersion, this.latestVersion, true);
const currentVersion = prometheus.spec.template.spec.containers[0].image.split(":")[1];
const pvcTemplate = prometheus.spec.volumeClaimTemplates[0];
if (pvcTemplate) {
this.templateContext.persistence.enabled = true;
this.templateContext.persistence.size = pvcTemplate.spec.resources.requests.storage;
}
status.installed = true;
status.canUpgrade = semver.lt(currentVersion, this.latestVersion, true);
} else {
this.status.installed = false;
status.installed = false;
}
} catch(e) {
if (e?.error?.code === 404) {
this.status.installed = false;
status.installed = false;
}
}
return this.status;
return status;
}
async uninstall(cluster: Catalog.KubernetesCluster): Promise<void> {
const namespaceApi = K8sApi.forCluster(cluster, K8sApi.Namespace);
const clusterRoleBindingApi = K8sApi.forCluster(cluster, K8sApi.ClusterRoleBinding);
const clusterRoleApi = K8sApi.forCluster(cluster, K8sApi.ClusterRole);
await namespaceApi.delete({name: "lens-metrics"});
await clusterRoleBindingApi.delete({name: "lens-prometheus"});
await clusterRoleApi.delete({name: "lens-prometheus"});
async uninstall(config: MetricsConfiguration): Promise<string> {
return this.stack.kubectlDeleteFolder(this.resourceFolder, config);
}
}
@@ -2,7 +2,8 @@ import React from "react";
import { Component, Catalog, K8sApi } from "@k8slens/extensions";
import { observer } from "mobx-react";
import { observable } from "mobx";
import { MetricsFeature } from "./metrics-feature";
import { MetricsFeature, MetricsConfiguration } from "./metrics-feature";
interface Props {
cluster: Catalog.KubernetesCluster;
}
@@ -17,28 +18,42 @@ export class MetricsSettings extends React.Component<Props> {
@observable canUpgrade = false;
@observable upgrading = false;
pvcOptions = [
{ value: "", label: "Use EmptyDir (no PVC)" },
{ value: "5GB", label: "5GB" },
{ value: "10GB", label: "10GB" },
{ value: "20GB", label: "20GB" },
{ value: "40GB", label: "40GB" },
{ value: "80GB", label: "80GB" },
];
featureSet: MetricsFeature;
config: MetricsConfiguration = {
prometheus: {
enabled: false
},
persistence: {
enabled: false,
storageClass: null,
size: "20G",
},
nodeExporter: {
enabled: false,
},
retention: {
time: "2d",
size: "5GB",
},
kubeStateMetrics: {
enabled: false,
},
alertManagers: null,
replicas: 1,
storageClass: null,
};
feature: MetricsFeature;
async componentDidMount() {
this.featureSet = new MetricsFeature();
this.feature = new MetricsFeature(this.props.cluster);
await this.updateFeatureStates();
}
async updateFeatureStates() {
await this.featureSet.updateStatus(this.props.cluster);
this.canUpgrade = this.featureSet.status.canUpgrade;
const status = await this.feature.getStatus();
this.featureStates.prometheus = this.featureSet.status.installed;
this.canUpgrade = status.canUpgrade;
this.featureStates.prometheus = status.installed;
const deployment = K8sApi.forCluster(this.props.cluster, K8sApi.Deployment);
@@ -68,24 +83,22 @@ export class MetricsSettings extends React.Component<Props> {
}
async save() {
const ctx = this.featureSet.templateContext;
this.config.prometheus.enabled = !!this.featureStates.prometheus;
this.config.kubeStateMetrics.enabled = !!this.featureStates.kubeStateMetrics;
this.config.nodeExporter.enabled = !!this.featureStates.nodeExporter;
ctx.prometheus.enabled = !!this.featureStates.prometheus;
ctx.kubeStateMetrics.enabled = !!this.featureStates.kubeStateMetrics;
ctx.nodeExporter.enabled = !!this.featureStates.nodeExporter;
console.log(this.config);
if (!ctx.prometheus.enabled && !ctx.kubeStateMetrics.enabled && !ctx.nodeExporter.enabled) {
await this.featureSet.uninstall(this.props.cluster);
if (!this.config.prometheus.enabled && !this.config.kubeStateMetrics.enabled && !this.config.nodeExporter.enabled) {
await this.feature.uninstall(this.config);
} else {
await this.featureSet.install(this.props.cluster);
await this.feature.install(this.config);
}
}
async togglePrometheus(enabled: boolean) {
this.featureStates.prometheus = enabled;
this.featureSet.templateContext.prometheus.enabled = this.featureStates.prometheus;
try {
await this.save();
} catch(error) {
@@ -97,8 +110,6 @@ export class MetricsSettings extends React.Component<Props> {
async toggleKubeStateMetrics(enabled: boolean) {
this.featureStates.kubeStateMetrics = enabled;
this.featureSet.templateContext.kubeStateMetrics.enabled = this.featureStates.kubeStateMetrics;
try {
await this.save();
} catch(error) {
@@ -110,8 +121,6 @@ export class MetricsSettings extends React.Component<Props> {
async toggleNodeExporter(enabled: boolean) {
this.featureStates.nodeExporter = enabled;
this.featureSet.templateContext.nodeExporter.enabled = this.featureStates.nodeExporter;
try {
await this.save();
} catch(error) {