From 8867f3a9e22a907eb5df4a72853d87522b7bbb44 Mon Sep 17 00:00:00 2001 From: Juho Heikka Date: Thu, 1 Jun 2023 09:48:19 +0300 Subject: [PATCH] Show auto detect prometheus info Signed-off-by: Juho Heikka --- .../metrics.api/prometheus-details.channel.ts | 17 ++++++ .../request-prometheus-details.injectable.ts | 21 +++++++ ...eus-details-channel-listener.injectable.ts | 39 +++++++++++++ .../get-prometheus-details.injectable.ts | 27 +++++++++ .../cluster-settings/prometheus-details.tsx | 37 +++++++++++++ .../cluster-settings/prometheus-setting.tsx | 55 +++++++++++++++++++ 6 files changed, 196 insertions(+) create mode 100644 packages/core/src/common/k8s-api/endpoints/metrics.api/prometheus-details.channel.ts create mode 100644 packages/core/src/common/k8s-api/endpoints/metrics.api/request-prometheus-details.injectable.ts create mode 100644 packages/core/src/main/cluster/prometheus-handler/prometheus-details-channel-listener.injectable.ts create mode 100644 packages/core/src/renderer/components/cluster-settings/get-prometheus-details.injectable.ts create mode 100644 packages/core/src/renderer/components/cluster-settings/prometheus-details.tsx diff --git a/packages/core/src/common/k8s-api/endpoints/metrics.api/prometheus-details.channel.ts b/packages/core/src/common/k8s-api/endpoints/metrics.api/prometheus-details.channel.ts new file mode 100644 index 0000000000..9a00196d03 --- /dev/null +++ b/packages/core/src/common/k8s-api/endpoints/metrics.api/prometheus-details.channel.ts @@ -0,0 +1,17 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getRequestChannel } from "@k8slens/messaging"; +import type { PrometheusDetails } from "../../../../main/cluster/prometheus-handler/prometheus-handler"; +import type { ClusterId } from "../../../cluster-types"; +import type { PrometheusProvider } from "../../../../main/prometheus/provider"; + +type PrometheusProviderData = Pick; + +export type PrometheusDetailsData = Pick & { + provider: PrometheusProviderData; +}; + +export const prometheusDetailsChannel = getRequestChannel("prometheus-details"); diff --git a/packages/core/src/common/k8s-api/endpoints/metrics.api/request-prometheus-details.injectable.ts b/packages/core/src/common/k8s-api/endpoints/metrics.api/request-prometheus-details.injectable.ts new file mode 100644 index 0000000000..3945d4971f --- /dev/null +++ b/packages/core/src/common/k8s-api/endpoints/metrics.api/request-prometheus-details.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getInjectable } from "@ogre-tools/injectable"; +import apiBaseInjectable from "../../api-base.injectable"; +import type { PrometheusDetails } from "../../../../main/cluster/prometheus-handler/prometheus-handler"; + +export type RequestPrometheusDetails = () => Promise; + +const requestPrometheusDetailsInjectable = getInjectable({ + id: "request-prometheus-details", + instantiate: (di): RequestPrometheusDetails => { + const apiBase = di.inject(apiBaseInjectable); + + return () => apiBase.get("/prometheus/details"); + }, +}); + +export default requestPrometheusDetailsInjectable; diff --git a/packages/core/src/main/cluster/prometheus-handler/prometheus-details-channel-listener.injectable.ts b/packages/core/src/main/cluster/prometheus-handler/prometheus-details-channel-listener.injectable.ts new file mode 100644 index 0000000000..dc32875667 --- /dev/null +++ b/packages/core/src/main/cluster/prometheus-handler/prometheus-details-channel-listener.injectable.ts @@ -0,0 +1,39 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; +import { prometheusDetailsChannel } from "../../../common/k8s-api/endpoints/metrics.api/prometheus-details.channel"; +import prometheusHandlerInjectable from "./prometheus-handler.injectable"; +import clustersInjectable from "../../../features/cluster/storage/common/clusters.injectable"; + +const prometheusDetailsChannelListener = + getRequestChannelListenerInjectable({ + id: "add-helm-repository-channel-listener", + channel: prometheusDetailsChannel, + getHandler: (di) => { + return async (clusterId) => { + const clusters = di.inject(clustersInjectable); + const cluster = clusters.get().find((c) => c.id === clusterId); + + if (!cluster) { + throw new Error(`Cluster with id "${clusterId}" not found`); + } + const prometheusHandler = di.inject(prometheusHandlerInjectable, cluster); + const details = await prometheusHandler.getPrometheusDetails(); + + console.log(details); + + return { + prometheusPath: details.prometheusPath, + provider: { + kind: details.provider.kind, + name: details.provider.name, + isConfigurable: details.provider.isConfigurable, + }, + }; + }; + }, + }); + +export default prometheusDetailsChannelListener; diff --git a/packages/core/src/renderer/components/cluster-settings/get-prometheus-details.injectable.ts b/packages/core/src/renderer/components/cluster-settings/get-prometheus-details.injectable.ts new file mode 100644 index 0000000000..601ed11f12 --- /dev/null +++ b/packages/core/src/renderer/components/cluster-settings/get-prometheus-details.injectable.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { logInfoInjectionToken } from "@k8slens/logger"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; +import { prometheusDetailsChannel } from "../../../common/k8s-api/endpoints/metrics.api/prometheus-details.channel"; + + +const getPrometheusDetailsRouteInjectable = getInjectable({ + id: "get-prometheus-details-route", + + instantiate: (di) => { + const logger = di.inject(logInfoInjectionToken); + const requestFromChannel = di.inject(requestFromChannelInjectionToken); + + return (async (clusterId: string) => { + logger("requestFromChannel"); + const prometheusDetails = await requestFromChannel(prometheusDetailsChannel, clusterId); + + return prometheusDetails; + }); + }, +}); + +export default getPrometheusDetailsRouteInjectable; diff --git a/packages/core/src/renderer/components/cluster-settings/prometheus-details.tsx b/packages/core/src/renderer/components/cluster-settings/prometheus-details.tsx new file mode 100644 index 0000000000..100d1bbf0d --- /dev/null +++ b/packages/core/src/renderer/components/cluster-settings/prometheus-details.tsx @@ -0,0 +1,37 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import { SubTitle } from "../layout/sub-title"; + +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +interface PrometheusDetailsProps { + providerName: string; + path: string; +} +export const PrometheusDetails = ({ providerName, path }: PrometheusDetailsProps) => ( +
+ +
+
+ Prometheus provider name +
+
+ {providerName} +
+
+
+
+ Prometheus path +
+
+ {path} +
+
+
+); diff --git a/packages/core/src/renderer/components/cluster-settings/prometheus-setting.tsx b/packages/core/src/renderer/components/cluster-settings/prometheus-setting.tsx index 4a1d7b5b66..4207dfc2ee 100644 --- a/packages/core/src/renderer/components/cluster-settings/prometheus-setting.tsx +++ b/packages/core/src/renderer/components/cluster-settings/prometheus-setting.tsx @@ -16,6 +16,11 @@ import type { MetricProviderInfo, RequestMetricsProviders } from "../../../commo import { withInjectables } from "@ogre-tools/injectable-react"; import requestMetricsProvidersInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-providers.injectable"; import productNameInjectable from "../../../common/vars/product-name.injectable"; +import getPrometheusDetailsRouteInjectable from "./get-prometheus-details.injectable"; +import type { PrometheusDetailsData } from "../../../common/k8s-api/endpoints/metrics.api/prometheus-details.channel"; +import { loggerInjectionToken } from "@k8slens/logger"; +import type { Logger } from "@k8slens/logger"; +import { PrometheusDetails } from "./prometheus-details"; export interface ClusterPrometheusSettingProps { cluster: Cluster; @@ -28,6 +33,13 @@ type ProviderValue = typeof autoDetectPrometheus | string; interface Dependencies { productName: string; requestMetricsProviders: RequestMetricsProviders; + requestPrometheusDetails: (clusterId: string) => Promise; + logger: Logger; +} + +interface PrometheusDetailsDataResult { + type: "success" | "error"; + details?: PrometheusDetailsData; } @observer @@ -35,6 +47,7 @@ class NonInjectedClusterPrometheusSetting extends React.Component(); @computed get options(): SelectOption[] { @@ -91,6 +104,8 @@ class NonInjectedClusterPrometheusSetting extends React.Component [provider.id, provider])); }); + + this.loadPrometheusDetails(); } parsePrometheusPath = () => { @@ -118,11 +133,31 @@ class NonInjectedClusterPrometheusSetting extends React.Component { + try { + const details = await this.props.requestPrometheusDetails(this.props.cluster.id); + + this.prometheusDetails = { + type: "success", + details, + }; + this.props.logger.info(`[CLUSTER-SETTINGS]: Prometheus details loaded: ${JSON.stringify(this.prometheusDetails)}`); + } catch (error) { + this.props.logger.error(`[CLUSTER-SETTINGS]: Failed to load prometheus details: ${error}`); + this.prometheusDetails = { + type: "error", + details: undefined, + }; + } + }; + onSavePath = () => { this.props.cluster.preferences.prometheus = this.parsePrometheusPath(); }; render() { + + return ( <>
@@ -138,6 +173,12 @@ class NonInjectedClusterPrometheusSetting extends React.Component { this.selectedOption = option?.value ?? autoDetectPrometheus; this.onSaveProvider(); + + // takes a while for the prometheus details to be available + // after saving the provider + setTimeout(() => { + void this.loadPrometheusDetails(); + }, 100); }} options={this.options} themeName="lens" @@ -147,6 +188,18 @@ class NonInjectedClusterPrometheusSetting extends React.Component + {this.prometheusDetails?.details && this.prometheusDetails?.type === "success" /*&& this.selectedOption === autoDetectPrometheus */ && ( + <> +
+ + + )} + {this.prometheusDetails?.type === "error" && ( +
auto detection did not find a prometheus provider
+ )} {this.canEditPrometheusPath && ( <>
@@ -175,5 +228,7 @@ export const ClusterPrometheusSetting = withInjectables