mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
clarify ui
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
parent
c4e501f329
commit
331a617c5b
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { Component, Catalog, K8sApi } from "@k8slens/extensions";
|
||||
import { observer } from "mobx-react";
|
||||
import { observable } from "mobx";
|
||||
import { computed, observable } from "mobx";
|
||||
import { MetricsFeature, MetricsConfiguration } from "./metrics-feature";
|
||||
|
||||
interface Props {
|
||||
@ -43,6 +43,22 @@ export class MetricsSettings extends React.Component<Props> {
|
||||
};
|
||||
feature: MetricsFeature;
|
||||
|
||||
@computed get isTogglable() {
|
||||
if (!this.props.cluster.status.active) return false;
|
||||
if (this.canUpgrade) return false;
|
||||
if (!this.isActiveMetricsProvider) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
get metricsProvider() {
|
||||
return this.props.cluster.spec?.metrics?.prometheus?.type || "";
|
||||
}
|
||||
|
||||
get isActiveMetricsProvider() {
|
||||
return (!this.metricsProvider || this.metricsProvider === "lens");
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
this.feature = new MetricsFeature(this.props.cluster);
|
||||
|
||||
@ -148,6 +164,13 @@ export class MetricsSettings extends React.Component<Props> {
|
||||
</p>
|
||||
</section>
|
||||
)}
|
||||
{ !this.isActiveMetricsProvider && (
|
||||
<section>
|
||||
<p style={ {color: "var(--colorError)"} }>
|
||||
Other metrics provider is currently active. See "Metrics" tab for details.
|
||||
</p>
|
||||
</section>
|
||||
)}
|
||||
{ this.canUpgrade && (
|
||||
<section>
|
||||
<Component.SubTitle title="Software Update" />
|
||||
@ -155,7 +178,7 @@ export class MetricsSettings extends React.Component<Props> {
|
||||
<Component.Button label={this.upgrading ? "Updating ..." : "Update Now"} primary onClick={() => this.updateStack() } waiting={this.upgrading} />
|
||||
|
||||
<small className="hint">
|
||||
An update is available for installed metrics components.
|
||||
An update is available for enabled metrics components.
|
||||
</small>
|
||||
</section>
|
||||
)}
|
||||
@ -164,7 +187,7 @@ export class MetricsSettings extends React.Component<Props> {
|
||||
<Component.FormSwitch
|
||||
control={
|
||||
<Component.Switcher
|
||||
disabled={this.featureStates.kubeStateMetrics === undefined || !this.props.cluster.status.active}
|
||||
disabled={this.featureStates.kubeStateMetrics === undefined || !this.isTogglable}
|
||||
checked={!!this.featureStates.prometheus && this.props.cluster.status.active}
|
||||
onChange={v => this.togglePrometheus(v.target.checked)}
|
||||
name="prometheus"
|
||||
@ -182,7 +205,7 @@ export class MetricsSettings extends React.Component<Props> {
|
||||
<Component.FormSwitch
|
||||
control={
|
||||
<Component.Switcher
|
||||
disabled={this.featureStates.kubeStateMetrics === undefined || !this.props.cluster.status.active}
|
||||
disabled={this.featureStates.kubeStateMetrics === undefined || !this.isTogglable}
|
||||
checked={!!this.featureStates.kubeStateMetrics && this.props.cluster.status.active}
|
||||
onChange={v => this.toggleKubeStateMetrics(v.target.checked)}
|
||||
name="node-exporter"
|
||||
@ -201,7 +224,7 @@ export class MetricsSettings extends React.Component<Props> {
|
||||
<Component.FormSwitch
|
||||
control={
|
||||
<Component.Switcher
|
||||
disabled={this.featureStates.nodeExporter === undefined || !this.props.cluster.status.active}
|
||||
disabled={this.featureStates.nodeExporter === undefined || !this.isTogglable}
|
||||
checked={!!this.featureStates.nodeExporter && this.props.cluster.status.active}
|
||||
onChange={v => this.toggleNodeExporter(v.target.checked)}
|
||||
name="node-exporter"
|
||||
|
||||
@ -6,9 +6,24 @@ import { requestMain } from "../ipc";
|
||||
import { productName } from "../vars";
|
||||
import { CatalogCategory, CatalogCategorySpec } from "../catalog";
|
||||
|
||||
|
||||
export type KubernetesClusterPrometheusMetrics = {
|
||||
address?: {
|
||||
namespace: string;
|
||||
service: string;
|
||||
port: number;
|
||||
prefix: string;
|
||||
};
|
||||
type?: string;
|
||||
};
|
||||
|
||||
export type KubernetesClusterSpec = {
|
||||
kubeconfigPath: string;
|
||||
kubeconfigContext: string;
|
||||
metrics?: {
|
||||
source: string;
|
||||
prometheus?: KubernetesClusterPrometheusMetrics;
|
||||
}
|
||||
};
|
||||
|
||||
export interface KubernetesClusterStatus extends CatalogEntityStatus {
|
||||
|
||||
@ -11,13 +11,14 @@ export interface EntitySettingComponents {
|
||||
}
|
||||
|
||||
export interface EntitySettingRegistration {
|
||||
title: string;
|
||||
kind: string;
|
||||
apiVersions: string[];
|
||||
source?: string;
|
||||
kind: string;
|
||||
title: string;
|
||||
components: EntitySettingComponents;
|
||||
source?: string;
|
||||
id?: string;
|
||||
priority?: number;
|
||||
group?: string;
|
||||
}
|
||||
|
||||
export interface RegisteredEntitySetting extends EntitySettingRegistration {
|
||||
|
||||
@ -8,7 +8,7 @@ import logger from "./logger";
|
||||
import { apiKubePrefix } from "../common/vars";
|
||||
import { Singleton } from "../common/utils";
|
||||
import { catalogEntityRegistry } from "../common/catalog";
|
||||
import { KubernetesCluster } from "../common/catalog-entities/kubernetes-cluster";
|
||||
import { KubernetesCluster, KubernetesClusterPrometheusMetrics } from "../common/catalog-entities/kubernetes-cluster";
|
||||
|
||||
export class ClusterManager extends Singleton {
|
||||
constructor() {
|
||||
@ -47,7 +47,7 @@ export class ClusterManager extends Singleton {
|
||||
const index = catalogEntityRegistry.items.findIndex((entity) => entity.metadata.uid === cluster.id);
|
||||
|
||||
if (index !== -1) {
|
||||
const entity = catalogEntityRegistry.items[index];
|
||||
const entity = catalogEntityRegistry.items[index] as KubernetesCluster;
|
||||
|
||||
entity.status.phase = cluster.disconnected ? "disconnected" : "connected";
|
||||
entity.status.active = !cluster.disconnected;
|
||||
@ -55,6 +55,17 @@ export class ClusterManager extends Singleton {
|
||||
if (cluster.preferences?.clusterName) {
|
||||
entity.metadata.name = cluster.preferences.clusterName;
|
||||
}
|
||||
|
||||
entity.spec.metrics ||= { source: "local" };
|
||||
|
||||
if (entity.spec.metrics.source === "local") {
|
||||
const prometheus: KubernetesClusterPrometheusMetrics = entity.spec?.metrics?.prometheus || {};
|
||||
|
||||
prometheus.type = cluster.preferences.prometheusProvider?.type;
|
||||
prometheus.address = cluster.preferences.prometheus;
|
||||
entity.spec.metrics.prometheus = prometheus;
|
||||
}
|
||||
|
||||
catalogEntityRegistry.items.splice(index, 1, entity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import { CatalogEntity } from "../../api/catalog-entity";
|
||||
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
|
||||
import { entitySettingRegistry } from "../../../extensions/registries";
|
||||
import { EntitySettingsRouteParams } from "./entity-settings.route";
|
||||
import { groupBy } from "lodash";
|
||||
|
||||
interface Props extends RouteComponentProps<EntitySettingsRouteParams> {
|
||||
}
|
||||
@ -52,18 +53,24 @@ export class EntitySettings extends React.Component<Props> {
|
||||
};
|
||||
|
||||
renderNavigation() {
|
||||
const groups = Object.entries(groupBy(this.menuItems, (item) => item.group || "Extensions"));
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2>{this.entity.metadata.name}</h2>
|
||||
<Tabs className="flex column" scrollable={false} onChange={this.onTabChange} value={this.activeTab}>
|
||||
<div className="header">Settings</div>
|
||||
{ this.menuItems.map((setting) => (
|
||||
<Tab
|
||||
key={setting.id}
|
||||
value={setting.id}
|
||||
label={setting.title}
|
||||
data-testid={`${setting.id}-tab`}
|
||||
/>
|
||||
{ groups.map((group) => (
|
||||
<>
|
||||
<div className="header">{group[0]}</div>
|
||||
{ group[1].map((setting) => (
|
||||
<Tab
|
||||
key={setting.id}
|
||||
value={setting.id}
|
||||
label={setting.title}
|
||||
data-testid={`${setting.id}-tab`}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
))}
|
||||
</Tabs>
|
||||
</>
|
||||
|
||||
@ -22,6 +22,7 @@ entitySettingRegistry.add([
|
||||
kind: "KubernetesCluster",
|
||||
source: "local",
|
||||
title: "General",
|
||||
group: "Settings",
|
||||
components: {
|
||||
View: (props: { entity: CatalogEntity }) => {
|
||||
const cluster = getClusterForEntity(props.entity);
|
||||
@ -47,6 +48,7 @@ entitySettingRegistry.add([
|
||||
apiVersions: ["entity.k8slens.dev/v1alpha1"],
|
||||
kind: "KubernetesCluster",
|
||||
title: "Proxy",
|
||||
group: "Settings",
|
||||
components: {
|
||||
View: (props: { entity: CatalogEntity }) => {
|
||||
const cluster = getClusterForEntity(props.entity);
|
||||
@ -67,6 +69,7 @@ entitySettingRegistry.add([
|
||||
apiVersions: ["entity.k8slens.dev/v1alpha1"],
|
||||
kind: "KubernetesCluster",
|
||||
title: "Terminal",
|
||||
group: "Settings",
|
||||
components: {
|
||||
View: (props: { entity: CatalogEntity }) => {
|
||||
const cluster = getClusterForEntity(props.entity);
|
||||
@ -87,6 +90,7 @@ entitySettingRegistry.add([
|
||||
apiVersions: ["entity.k8slens.dev/v1alpha1"],
|
||||
kind: "KubernetesCluster",
|
||||
title: "Namespaces",
|
||||
group: "Settings",
|
||||
components: {
|
||||
View: (props: { entity: CatalogEntity }) => {
|
||||
const cluster = getClusterForEntity(props.entity);
|
||||
@ -107,6 +111,7 @@ entitySettingRegistry.add([
|
||||
apiVersions: ["entity.k8slens.dev/v1alpha1"],
|
||||
kind: "KubernetesCluster",
|
||||
title: "Metrics",
|
||||
group: "Settings",
|
||||
components: {
|
||||
View: (props: { entity: CatalogEntity }) => {
|
||||
const cluster = getClusterForEntity(props.entity);
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
.MetricsSelect {
|
||||
$spacing: $padding;
|
||||
--flex-gap: #{$spacing};
|
||||
|
||||
.Badge {
|
||||
margin-top: $spacing;
|
||||
}
|
||||
|
||||
.Button {
|
||||
margin-top: $spacing;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,3 @@
|
||||
import "./cluster-metrics-setting.scss";
|
||||
|
||||
import React from "react";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { Select, SelectOption } from "../../select/select";
|
||||
|
||||
@ -6,6 +6,7 @@ import { SubTitle } from "../../layout/sub-title";
|
||||
import { Select, SelectOption } from "../../select";
|
||||
import { Input } from "../../input";
|
||||
import { observable, computed, autorun } from "mobx";
|
||||
import { productName } from "../../../../common/vars";
|
||||
|
||||
const options: SelectOption<string>[] = [
|
||||
{ value: "", label: "Auto detect" },
|
||||
@ -81,23 +82,20 @@ export class ClusterPrometheusSetting extends React.Component<Props> {
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<SubTitle title="Prometheus installation method"/>
|
||||
<p>
|
||||
Use pre-installed Prometheus service for metrics. Please refer to the{" "}
|
||||
<a href="https://github.com/lensapp/lens/blob/master/troubleshooting/custom-prometheus.md" target="_blank" rel="noreferrer">guide</a>{" "}
|
||||
for possible configuration changes.
|
||||
</p>
|
||||
<Select
|
||||
value={this.provider}
|
||||
onChange={({value}) => {
|
||||
this.provider = value;
|
||||
this.onSaveProvider();
|
||||
}}
|
||||
options={options}
|
||||
/>
|
||||
<small className="hint">What query format is used to fetch metrics from Prometheus</small>
|
||||
<section>
|
||||
<SubTitle title="Prometheus"/>
|
||||
<Select
|
||||
value={this.provider}
|
||||
onChange={({value}) => {
|
||||
this.provider = value;
|
||||
this.onSaveProvider();
|
||||
}}
|
||||
options={options}
|
||||
/>
|
||||
<small className="hint">What query format is used to fetch metrics from Prometheus</small>
|
||||
</section>
|
||||
{this.canEditPrometheusPath && (
|
||||
<>
|
||||
<section>
|
||||
<p>Prometheus service address.</p>
|
||||
<Input
|
||||
theme="round-black"
|
||||
@ -108,9 +106,9 @@ export class ClusterPrometheusSetting extends React.Component<Props> {
|
||||
/>
|
||||
<small className="hint">
|
||||
An address to an existing Prometheus installation{" "}
|
||||
({"<namespace>/<service>:<port>"}). Lens tries to auto-detect address if left empty.
|
||||
({"<namespace>/<service>:<port>"}). {productName} tries to auto-detect address if left empty.
|
||||
</small>
|
||||
</>
|
||||
</section>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import "./cluster-metrics-setting.scss";
|
||||
|
||||
import React from "react";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { Cluster } from "../../../../main/cluster";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user