From 3efacce00266b061ca60e3917fe733c3cbe24f2d Mon Sep 17 00:00:00 2001 From: Nawaz Dhandala Date: Thu, 19 Mar 2026 09:25:52 +0000 Subject: [PATCH] Refactor and clean up code across multiple components - Simplified error handling in KubernetesEventsTab and KubernetesLogsTab by removing unnecessary line breaks. - Consolidated import statements in KubernetesMetricsTab for better readability. - Improved JSX formatting in KubernetesOverviewTab, KubernetesClusterContainerDetail, and other components for consistency. - Enhanced code clarity in KubernetesObjectFetcher and KubernetesObjectParser by removing redundant line breaks and comments. - Streamlined API response handling in IPWhitelistAPI for better readability. - Updated PageSEO configuration for improved formatting. --- .../Kubernetes/KubernetesContainersTab.tsx | 111 +++++++++------ .../Kubernetes/KubernetesEventsTab.tsx | 20 ++- .../Kubernetes/KubernetesLogsTab.tsx | 8 +- .../Kubernetes/KubernetesMetricsTab.tsx | 6 +- .../Kubernetes/KubernetesOverviewTab.tsx | 26 ++-- .../src/Components/Logs/LogsViewer.tsx | 23 ++- .../Utils/KubernetesObjectFetcher.ts | 6 +- .../Utils/KubernetesObjectParser.ts | 131 +++++++----------- .../Utils/KubernetesResourceUtils.ts | 96 +++++++------ .../Pages/Kubernetes/View/ContainerDetail.tsx | 14 +- .../Pages/Kubernetes/View/CronJobDetail.tsx | 40 +++--- .../Pages/Kubernetes/View/DaemonSetDetail.tsx | 4 +- .../Kubernetes/View/DeploymentDetail.tsx | 4 +- .../src/Pages/Kubernetes/View/Deployments.tsx | 4 +- .../src/Pages/Kubernetes/View/Events.tsx | 31 ++--- .../src/Pages/Kubernetes/View/JobDetail.tsx | 9 +- .../Pages/Kubernetes/View/NamespaceDetail.tsx | 9 +- .../src/Pages/Kubernetes/View/NodeDetail.tsx | 14 +- .../src/Pages/Kubernetes/View/PodDetail.tsx | 10 +- .../Kubernetes/View/StatefulSetDetail.tsx | 9 +- .../Pages/Kubernetes/View/StatefulSets.tsx | 4 +- App/FeatureSet/Docs/Index.ts | 5 +- Common/Server/API/IPWhitelistAPI.ts | 31 ++--- Home/Utils/PageSEO.ts | 3 +- 24 files changed, 303 insertions(+), 315 deletions(-) diff --git a/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesContainersTab.tsx b/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesContainersTab.tsx index 222da2021f..cea19f3ea8 100644 --- a/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesContainersTab.tsx +++ b/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesContainersTab.tsx @@ -2,6 +2,7 @@ import React, { FunctionComponent, ReactElement, useState } from "react"; import Card from "Common/UI/Components/Card/Card"; import DictionaryOfStringsViewer from "Common/UI/Components/Dictionary/DictionaryOfStingsViewer"; import { + KubernetesContainerPort, KubernetesContainerSpec, KubernetesContainerStatus, } from "../../Pages/Kubernetes/Utils/KubernetesObjectParser"; @@ -104,15 +105,19 @@ const ContainerCard: FunctionComponent = ( {props.container.ports.length > 0 && (
Ports:{" "} - {props.container.ports.map((port, idx) => ( - - {port.name ? `${port.name}: ` : ""} - {port.containerPort}/{port.protocol} - - ))} + {props.container.ports.map( + (port: KubernetesContainerPort, idx: number) => { + return ( + + {port.name ? `${port.name}: ` : ""} + {port.containerPort}/{port.protocol} + + ); + }, + )}
)} @@ -176,20 +181,33 @@ const ContainerCard: FunctionComponent = ( {showMounts && (
- {props.container.volumeMounts.map((mount, idx) => ( -
- - {mount.name} - - - - {mount.mountPath} - - {mount.readOnly && ( - (read-only) - )} -
- ))} + {props.container.volumeMounts.map( + ( + mount: { + name: string; + mountPath: string; + readOnly: boolean; + }, + idx: number, + ) => { + return ( +
+ + {mount.name} + + + + {mount.mountPath} + + {mount.readOnly && ( + + (read-only) + + )} +
+ ); + }, + )}
)} @@ -202,10 +220,7 @@ const ContainerCard: FunctionComponent = ( const KubernetesContainersTab: FunctionComponent = ( props: ComponentProps, ): ReactElement => { - if ( - props.containers.length === 0 && - props.initContainers.length === 0 - ) { + if (props.containers.length === 0 && props.initContainers.length === 0) { return (
No container information available. @@ -223,32 +238,36 @@ const KubernetesContainersTab: FunctionComponent = ( const statuses: Array | undefined = isInit ? props.initContainerStatuses : props.containerStatuses; - return statuses?.find( - (s: KubernetesContainerStatus) => s.name === name, - ); + return statuses?.find((s: KubernetesContainerStatus) => { + return s.name === name; + }); }; return (
{props.initContainers.map( - (container: KubernetesContainerSpec, index: number) => ( - - ), + (container: KubernetesContainerSpec, index: number) => { + return ( + + ); + }, )} {props.containers.map( - (container: KubernetesContainerSpec, index: number) => ( - - ), + (container: KubernetesContainerSpec, index: number) => { + return ( + + ); + }, )}
); diff --git a/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesEventsTab.tsx b/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesEventsTab.tsx index 22d6c3f139..680220ed7d 100644 --- a/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesEventsTab.tsx +++ b/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesEventsTab.tsx @@ -29,18 +29,15 @@ const KubernetesEventsTab: FunctionComponent = ( const fetchEvents: () => Promise = async (): Promise => { setIsLoading(true); try { - const result: Array = - await fetchK8sEventsForResource({ - clusterIdentifier: props.clusterIdentifier, - resourceKind: props.resourceKind, - resourceName: props.resourceName, - namespace: props.namespace, - }); + const result: Array = await fetchK8sEventsForResource({ + clusterIdentifier: props.clusterIdentifier, + resourceKind: props.resourceKind, + resourceName: props.resourceName, + namespace: props.namespace, + }); setEvents(result); } catch (err) { - setError( - err instanceof Error ? err.message : "Failed to fetch events", - ); + setError(err instanceof Error ? err.message : "Failed to fetch events"); } setIsLoading(false); }; @@ -91,8 +88,7 @@ const KubernetesEventsTab: FunctionComponent = ( {events.map((event: KubernetesEvent, index: number) => { - const isWarning: boolean = - event.type.toLowerCase() === "warning"; + const isWarning: boolean = event.type.toLowerCase() === "warning"; return ( diff --git a/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesLogsTab.tsx b/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesLogsTab.tsx index 965790884e..c677540c98 100644 --- a/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesLogsTab.tsx +++ b/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesLogsTab.tsx @@ -38,9 +38,7 @@ const KubernetesLogsTab: FunctionComponent = ( }); setLogs(result); } catch (err) { - setError( - err instanceof Error ? err.message : "Failed to fetch logs", - ); + setError(err instanceof Error ? err.message : "Failed to fetch logs"); } setIsLoading(false); }; @@ -65,8 +63,8 @@ const KubernetesLogsTab: FunctionComponent = ( return (
No application logs found for this pod in the last 6 hours. Logs will - appear here once the kubernetes-agent's filelog receiver is collecting - data. + appear here once the kubernetes-agent's filelog receiver is + collecting data.
); } diff --git a/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesMetricsTab.tsx b/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesMetricsTab.tsx index 5e84c12272..d1ef5073d4 100644 --- a/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesMetricsTab.tsx +++ b/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesMetricsTab.tsx @@ -1,8 +1,4 @@ -import React, { - FunctionComponent, - ReactElement, - useState, -} from "react"; +import React, { FunctionComponent, ReactElement, useState } from "react"; import MetricView from "../../Components/Metrics/MetricView"; import MetricViewData from "Common/Types/Metrics/MetricViewData"; import MetricQueryConfigData from "Common/Types/Metrics/MetricQueryConfigData"; diff --git a/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesOverviewTab.tsx b/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesOverviewTab.tsx index a0f310b20c..3dc3eff1ce 100644 --- a/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesOverviewTab.tsx +++ b/App/FeatureSet/Dashboard/src/Components/Kubernetes/KubernetesOverviewTab.tsx @@ -44,23 +44,20 @@ const KubernetesOverviewTab: FunctionComponent = ( {/* Summary Info Cards */} {props.summaryFields.length > 0 && (
- {props.summaryFields.map( - (field: SummaryField, index: number) => { - return ( - - ); - }, - )} + {props.summaryFields.map((field: SummaryField, index: number) => { + return ( + + ); + })}
)} {/* Owner References */} {props.ownerReferences && props.ownerReferences.length > 0 && ( - +
{props.ownerReferences.map( (ref: { kind: string; name: string }, index: number) => { @@ -147,7 +144,10 @@ const KubernetesOverviewTab: FunctionComponent = ( {/* Labels */} {Object.keys(props.labels).length > 0 && ( - + )} diff --git a/App/FeatureSet/Dashboard/src/Components/Logs/LogsViewer.tsx b/App/FeatureSet/Dashboard/src/Components/Logs/LogsViewer.tsx index 0446688a38..a5ae442ff4 100644 --- a/App/FeatureSet/Dashboard/src/Components/Logs/LogsViewer.tsx +++ b/App/FeatureSet/Dashboard/src/Components/Logs/LogsViewer.tsx @@ -413,11 +413,17 @@ const DashboardLogsViewer: FunctionComponent = ( } try { - // When live polling, recompute the time range so the query window - // slides forward to "now" and new logs become visible. + /* + * When live polling, recompute the time range so the query window + * slides forward to "now" and new logs become visible. + */ let query: Query = filterOptions; - if (skipLoadingState && isLiveEnabled && timeRange.range !== TimeRange.CUSTOM) { + if ( + skipLoadingState && + isLiveEnabled && + timeRange.range !== TimeRange.CUSTOM + ) { const freshRange: InBetween = RangeStartAndEndDateTimeUtil.getStartAndEndDate(timeRange); query = { @@ -468,7 +474,16 @@ const DashboardLogsViewer: FunctionComponent = ( } } }, - [filterOptions, isLiveEnabled, page, pageSize, select, sortField, sortOrder, timeRange], + [ + filterOptions, + isLiveEnabled, + page, + pageSize, + select, + sortField, + sortOrder, + timeRange, + ], ); // --- Fetch histogram --- diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesObjectFetcher.ts b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesObjectFetcher.ts index e76d0494cc..d4665cb566 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesObjectFetcher.ts +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesObjectFetcher.ts @@ -263,8 +263,7 @@ export async function fetchK8sEventsForResource(options: { const objectKvList: JSONObject = objectVal; // Get event details - const eventType: string = - getKvStringValue(objectKvList, "type") || ""; + const eventType: string = getKvStringValue(objectKvList, "type") || ""; const reason: string = getKvStringValue(objectKvList, "reason") || ""; const note: string = getKvStringValue(objectKvList, "note") || ""; @@ -400,8 +399,7 @@ export async function fetchPodLogs(options: { : "", body: typeof log.body === "string" ? log.body : "", severity: log.severityText || "INFO", - containerName: - (attrs["resource.k8s.container.name"] as string) || "", + containerName: (attrs["resource.k8s.container.name"] as string) || "", }; }); } catch { diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesObjectParser.ts b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesObjectParser.ts index 30e885237e..42d8e52b17 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesObjectParser.ts +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesObjectParser.ts @@ -1,8 +1,10 @@ import { JSONObject } from "Common/Types/JSON"; -// ============================================================ -// OTLP kvlistValue parsing helpers -// ============================================================ +/* + * ============================================================ + * OTLP kvlistValue parsing helpers + * ============================================================ + */ /** * Extract a value from an OTLP kvlistValue by key. @@ -141,9 +143,11 @@ export function getArrayValues( .filter(Boolean) as Array; } -// ============================================================ -// TypeScript interfaces for parsed K8s objects -// ============================================================ +/* + * ============================================================ + * TypeScript interfaces for parsed K8s objects + * ============================================================ + */ export interface KubernetesObjectMetadata { name: string; @@ -336,15 +340,14 @@ export interface KubernetesNamespaceObject { }; } -// ============================================================ -// Parsers -// ============================================================ +/* + * ============================================================ + * Parsers + * ============================================================ + */ function parseMetadata(kvList: JSONObject): KubernetesObjectMetadata { - const labelsKvList: string | JSONObject | null = getKvValue( - kvList, - "labels", - ); + const labelsKvList: string | JSONObject | null = getKvValue(kvList, "labels"); const annotationsKvList: string | JSONObject | null = getKvValue( kvList, "annotations", @@ -503,10 +506,7 @@ function parseContainerSpec(kvList: JSONObject): KubernetesContainerSpec { resourcesKv, "requests", ); - const limKv: string | JSONObject | null = getKvValue( - resourcesKv, - "limits", - ); + const limKv: string | JSONObject | null = getKvValue(resourcesKv, "limits"); if (reqKv && typeof reqKv !== "string") { requests = getKvListAsRecord(reqKv); } @@ -521,7 +521,8 @@ function parseContainerSpec(kvList: JSONObject): KubernetesContainerSpec { ); const command: Array = []; if (commandArray && typeof commandArray !== "string") { - const cmdValues: Array = (commandArray["values"] as Array) || []; + const cmdValues: Array = + (commandArray["values"] as Array) || []; for (const v of cmdValues) { if (v["stringValue"]) { command.push(v["stringValue"] as string); @@ -532,7 +533,8 @@ function parseContainerSpec(kvList: JSONObject): KubernetesContainerSpec { const argsArray: string | JSONObject | null = getKvValue(kvList, "args"); const args: Array = []; if (argsArray && typeof argsArray !== "string") { - const argValues: Array = (argsArray["values"] as Array) || []; + const argValues: Array = + (argsArray["values"] as Array) || []; for (const v of argValues) { if (v["stringValue"]) { args.push(v["stringValue"] as string); @@ -593,8 +595,7 @@ function parseContainerStatuses( return { name: getKvStringValue(kvList, "name"), ready: getKvStringValue(kvList, "ready") === "true", - restartCount: - parseInt(getKvStringValue(kvList, "restartCount")) || 0, + restartCount: parseInt(getKvStringValue(kvList, "restartCount")) || 0, state, image: getKvStringValue(kvList, "image"), }; @@ -618,10 +619,7 @@ export function parsePodObject( } const metadata: KubernetesObjectMetadata = parseMetadata(metadataKv); - const specKv: string | JSONObject | null = getKvValue( - objectKvList, - "spec", - ); + const specKv: string | JSONObject | null = getKvValue(objectKvList, "spec"); const statusKv: string | JSONObject | null = getKvValue( objectKvList, "status", @@ -683,8 +681,9 @@ export function parsePodObject( | JSONObject | undefined; if (innerVal && innerVal["kvlistValue"]) { - const innerKv: JSONObject = - innerVal["kvlistValue"] as JSONObject; + const innerKv: JSONObject = innerVal[ + "kvlistValue" + ] as JSONObject; volSource = getKvStringValue(innerKv, "name") || getKvStringValue(innerKv, "path") || @@ -877,10 +876,12 @@ export function parseNodeObject( ); if (addrArray && typeof addrArray !== "string") { const addrItems: Array = getArrayValues(addrArray); - addresses = addrItems.map((a: JSONObject) => ({ - type: getKvStringValue(a, "type"), - address: getKvStringValue(a, "address"), - })); + addresses = addrItems.map((a: JSONObject) => { + return { + type: getKvStringValue(a, "type"), + address: getKvStringValue(a, "address"), + }; + }); } } @@ -911,10 +912,7 @@ export function parseDeploymentObject( return null; } - const specKv: string | JSONObject | null = getKvValue( - objectKvList, - "spec", - ); + const specKv: string | JSONObject | null = getKvValue(objectKvList, "spec"); const statusKv: string | JSONObject | null = getKvValue( objectKvList, "status", @@ -953,8 +951,7 @@ export function parseDeploymentObject( let unavailableReplicas: number = 0; let conditions: Array = []; if (statusKv && typeof statusKv !== "string") { - statusReplicas = - parseInt(getKvStringValue(statusKv, "replicas")) || 0; + statusReplicas = parseInt(getKvStringValue(statusKv, "replicas")) || 0; readyReplicas = parseInt(getKvStringValue(statusKv, "readyReplicas")) || 0; availableReplicas = @@ -996,10 +993,7 @@ export function parseStatefulSetObject( return null; } - const specKv: string | JSONObject | null = getKvValue( - objectKvList, - "spec", - ); + const specKv: string | JSONObject | null = getKvValue(objectKvList, "spec"); const statusKv: string | JSONObject | null = getKvValue( objectKvList, "status", @@ -1058,10 +1052,7 @@ export function parseDaemonSetObject( return null; } - const specKv: string | JSONObject | null = getKvValue( - objectKvList, - "spec", - ); + const specKv: string | JSONObject | null = getKvValue(objectKvList, "spec"); const statusKv: string | JSONObject | null = getKvValue( objectKvList, "status", @@ -1099,9 +1090,8 @@ export function parseDaemonSetObject( ) || 0 : 0, numberReady: statusKv - ? parseInt( - getKvStringValue(statusKv as JSONObject, "numberReady"), - ) || 0 + ? parseInt(getKvStringValue(statusKv as JSONObject, "numberReady")) || + 0 : 0, numberMisscheduled: statusKv ? parseInt( @@ -1132,10 +1122,7 @@ export function parseJobObject( return null; } - const specKv: string | JSONObject | null = getKvValue( - objectKvList, - "spec", - ); + const specKv: string | JSONObject | null = getKvValue(objectKvList, "spec"); const statusKv: string | JSONObject | null = getKvValue( objectKvList, "status", @@ -1145,19 +1132,14 @@ export function parseJobObject( metadata: parseMetadata(metadataKv), spec: { completions: specKv - ? parseInt( - getKvStringValue(specKv as JSONObject, "completions"), - ) || 0 + ? parseInt(getKvStringValue(specKv as JSONObject, "completions")) || 0 : 0, parallelism: specKv - ? parseInt( - getKvStringValue(specKv as JSONObject, "parallelism"), - ) || 0 + ? parseInt(getKvStringValue(specKv as JSONObject, "parallelism")) || 0 : 0, backoffLimit: specKv - ? parseInt( - getKvStringValue(specKv as JSONObject, "backoffLimit"), - ) || 0 + ? parseInt(getKvStringValue(specKv as JSONObject, "backoffLimit")) || + 0 : 0, }, status: { @@ -1165,9 +1147,7 @@ export function parseJobObject( ? parseInt(getKvStringValue(statusKv as JSONObject, "active")) || 0 : 0, succeeded: statusKv - ? parseInt( - getKvStringValue(statusKv as JSONObject, "succeeded"), - ) || 0 + ? parseInt(getKvStringValue(statusKv as JSONObject, "succeeded")) || 0 : 0, failed: statusKv ? parseInt(getKvStringValue(statusKv as JSONObject, "failed")) || 0 @@ -1205,10 +1185,7 @@ export function parseCronJobObject( return null; } - const specKv: string | JSONObject | null = getKvValue( - objectKvList, - "spec", - ); + const specKv: string | JSONObject | null = getKvValue(objectKvList, "spec"); const statusKv: string | JSONObject | null = getKvValue( objectKvList, "status", @@ -1220,10 +1197,9 @@ export function parseCronJobObject( schedule: specKv ? getKvStringValue(specKv as JSONObject, "schedule") : "", - suspend: - specKv - ? getKvStringValue(specKv as JSONObject, "suspend") === "true" - : false, + suspend: specKv + ? getKvStringValue(specKv as JSONObject, "suspend") === "true" + : false, concurrencyPolicy: specKv ? getKvStringValue(specKv as JSONObject, "concurrencyPolicy") : "", @@ -1237,10 +1213,7 @@ export function parseCronJobObject( : 0, failedJobsHistoryLimit: specKv ? parseInt( - getKvStringValue( - specKv as JSONObject, - "failedJobsHistoryLimit", - ), + getKvStringValue(specKv as JSONObject, "failedJobsHistoryLimit"), ) || 0 : 0, }, @@ -1315,8 +1288,10 @@ export function extractObjectFromLogBody( return objectVal; } - // If no "object" key, the kvlist might BE the object (pull mode) - // Check if it has typical K8s fields + /* + * If no "object" key, the kvlist might BE the object (pull mode) + * Check if it has typical K8s fields + */ const kind: string | JSONObject | null = getKvValue(topKvList, "kind"); if (kind) { return topKvList; diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesResourceUtils.ts b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesResourceUtils.ts index 13cb238408..fa6f626742 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesResourceUtils.ts +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/Utils/KubernetesResourceUtils.ts @@ -43,31 +43,30 @@ export default class KubernetesResourceUtils { const endDate: Date = OneUptimeDate.getCurrentDate(); const startDate: Date = OneUptimeDate.addRemoveHours(endDate, -hoursBack); - const cpuResult: AggregatedResult = - await AnalyticsModelAPI.aggregate({ - modelType: Metric, - aggregateBy: { - query: { - projectId: ProjectUtil.getCurrentProjectId()!, - time: new InBetween(startDate, endDate), - name: metricName, - attributes: { - "resource.k8s.cluster.name": clusterIdentifier, - ...filterAttributes, - } as Dictionary, - }, - aggregationType: MetricsAggregationType.Avg, - aggregateColumnName: "value", - aggregationTimestampColumnName: "time", - startTimestamp: startDate, - endTimestamp: endDate, - limit: LIMIT_PER_PROJECT, - skip: 0, - groupBy: { - attributes: true, - }, + const cpuResult: AggregatedResult = await AnalyticsModelAPI.aggregate({ + modelType: Metric, + aggregateBy: { + query: { + projectId: ProjectUtil.getCurrentProjectId()!, + time: new InBetween(startDate, endDate), + name: metricName, + attributes: { + "resource.k8s.cluster.name": clusterIdentifier, + ...filterAttributes, + } as Dictionary, }, - }); + aggregationType: MetricsAggregationType.Avg, + aggregateColumnName: "value", + aggregationTimestampColumnName: "time", + startTimestamp: startDate, + endTimestamp: endDate, + limit: LIMIT_PER_PROJECT, + skip: 0, + groupBy: { + attributes: true, + }, + }, + }); const resourceMap: Map = new Map(); @@ -128,31 +127,30 @@ export default class KubernetesResourceUtils { ); try { - const memoryResult: AggregatedResult = - await AnalyticsModelAPI.aggregate({ - modelType: Metric, - aggregateBy: { - query: { - projectId: ProjectUtil.getCurrentProjectId()!, - time: new InBetween(startDate, endDate), - name: options.memoryMetricName, - attributes: { - "resource.k8s.cluster.name": options.clusterIdentifier, - ...(options.filterAttributes || {}), - } as Dictionary, - }, - aggregationType: MetricsAggregationType.Avg, - aggregateColumnName: "value", - aggregationTimestampColumnName: "time", - startTimestamp: startDate, - endTimestamp: endDate, - limit: LIMIT_PER_PROJECT, - skip: 0, - groupBy: { - attributes: true, - }, + const memoryResult: AggregatedResult = await AnalyticsModelAPI.aggregate({ + modelType: Metric, + aggregateBy: { + query: { + projectId: ProjectUtil.getCurrentProjectId()!, + time: new InBetween(startDate, endDate), + name: options.memoryMetricName, + attributes: { + "resource.k8s.cluster.name": options.clusterIdentifier, + ...(options.filterAttributes || {}), + } as Dictionary, }, - }); + aggregationType: MetricsAggregationType.Avg, + aggregateColumnName: "value", + aggregationTimestampColumnName: "time", + startTimestamp: startDate, + endTimestamp: endDate, + limit: LIMIT_PER_PROJECT, + skip: 0, + groupBy: { + attributes: true, + }, + }, + }); const memoryMap: Map = new Map(); @@ -179,7 +177,7 @@ export default class KubernetesResourceUtils { resource.memoryUsageBytes = memValue; } } - } catch (_err) { + } catch { // Memory data is optional, don't fail if not available } diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/ContainerDetail.tsx b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/ContainerDetail.tsx index d111e8211e..e510c4f3bf 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/ContainerDetail.tsx +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/ContainerDetail.tsx @@ -140,7 +140,10 @@ const KubernetesClusterContainerDetail: FunctionComponent< children: (
- +
@@ -149,7 +152,10 @@ const KubernetesClusterContainerDetail: FunctionComponent< { name: "Logs", children: ( - + - + ), }, diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/CronJobDetail.tsx b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/CronJobDetail.tsx index 20403c1e4a..31c458a1f4 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/CronJobDetail.tsx +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/CronJobDetail.tsx @@ -71,22 +71,21 @@ const KubernetesClusterCronJobDetail: FunctionComponent< return; } - const fetchCronJobObject: () => Promise = - async (): Promise => { - setIsLoadingObject(true); - try { - const obj: KubernetesCronJobObject | null = - await fetchLatestK8sObject({ - clusterIdentifier: cluster.clusterIdentifier || "", - resourceType: "cronjobs", - resourceName: cronJobName, - }); - setCronJobObject(obj); - } catch { - // Graceful degradation — overview tab shows empty state - } - setIsLoadingObject(false); - }; + const fetchCronJobObject: () => Promise = async (): Promise => { + setIsLoadingObject(true); + try { + const obj: KubernetesCronJobObject | null = + await fetchLatestK8sObject({ + clusterIdentifier: cluster.clusterIdentifier || "", + resourceType: "cronjobs", + resourceName: cronJobName, + }); + setCronJobObject(obj); + } catch { + // Graceful degradation — overview tab shows empty state + } + setIsLoadingObject(false); + }; fetchCronJobObject().catch(() => {}); }, [cluster?.clusterIdentifier, cronJobName]); @@ -228,7 +227,10 @@ const KubernetesClusterCronJobDetail: FunctionComponent< { name: "Events", children: ( - + - + ), }, diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/DaemonSetDetail.tsx b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/DaemonSetDetail.tsx index a1837e0ce0..3121929fc5 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/DaemonSetDetail.tsx +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/DaemonSetDetail.tsx @@ -239,9 +239,7 @@ const KubernetesClusterDaemonSetDetail: FunctionComponent< title={`DaemonSet Metrics: ${daemonSetName}`} description="CPU and memory usage for pods in this daemonset over the last 6 hours." > - + ), }, diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/DeploymentDetail.tsx b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/DeploymentDetail.tsx index 79498ff38f..847f9c881c 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/DeploymentDetail.tsx +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/DeploymentDetail.tsx @@ -236,9 +236,7 @@ const KubernetesClusterDeploymentDetail: FunctionComponent< title={`Deployment Metrics: ${deploymentName}`} description="CPU and memory usage for pods in this deployment over the last 6 hours." > - + ), }, diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/Deployments.tsx b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/Deployments.tsx index 3dacfb9327..235adc8dae 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/Deployments.tsx +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/Deployments.tsx @@ -85,7 +85,9 @@ const KubernetesClusterDeployments: FunctionComponent< resources={resources} getViewRoute={(resource: KubernetesResource) => { return RouteUtil.populateRouteParams( - RouteMap[PageMap.KUBERNETES_CLUSTER_VIEW_DEPLOYMENT_DETAIL] as Route, + RouteMap[ + PageMap.KUBERNETES_CLUSTER_VIEW_DEPLOYMENT_DETAIL + ] as Route, { modelId: modelId, subModelId: new ObjectID(resource.name), diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/Events.tsx b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/Events.tsx index 0302bc902a..27807636e7 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/Events.tsx +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/Events.tsx @@ -24,10 +24,7 @@ import ErrorMessage from "Common/UI/Components/ErrorMessage/ErrorMessage"; import { PromiseVoidFunction } from "Common/Types/FunctionTypes"; import { JSONObject } from "Common/Types/JSON"; import InBetween from "Common/Types/BaseDatabase/InBetween"; -import { - getKvValue, - getKvStringValue, -} from "../Utils/KubernetesObjectParser"; +import { getKvValue, getKvStringValue } from "../Utils/KubernetesObjectParser"; import { KubernetesEvent } from "../Utils/KubernetesObjectFetcher"; const KubernetesClusterEvents: FunctionComponent< @@ -131,12 +128,9 @@ const KubernetesClusterEvents: FunctionComponent< } const objectKvList: JSONObject = objectVal; - const eventType: string = - getKvStringValue(objectKvList, "type") || ""; - const reason: string = - getKvStringValue(objectKvList, "reason") || ""; - const note: string = - getKvStringValue(objectKvList, "note") || ""; + const eventType: string = getKvStringValue(objectKvList, "type") || ""; + const reason: string = getKvStringValue(objectKvList, "reason") || ""; + const note: string = getKvStringValue(objectKvList, "note") || ""; // Get regarding object details using shared parser const regardingKv: string | JSONObject | null = getKvValue( @@ -160,17 +154,11 @@ const KubernetesClusterEvents: FunctionComponent< "metadata", ); const metadataObj: JSONObject | undefined = - metadataKv && typeof metadataKv !== "string" - ? metadataKv - : undefined; + metadataKv && typeof metadataKv !== "string" ? metadataKv : undefined; const namespace: string = - (regardingObj - ? getKvStringValue(regardingObj, "namespace") - : "") || - (metadataObj - ? getKvStringValue(metadataObj, "namespace") - : "") || + (regardingObj ? getKvStringValue(regardingObj, "namespace") : "") || + (metadataObj ? getKvStringValue(metadataObj, "namespace") : "") || ""; if (eventType || reason) { @@ -254,10 +242,7 @@ const KubernetesClusterEvents: FunctionComponent< const isWarning: boolean = event.type.toLowerCase() === "warning"; return ( - + {event.timestamp} diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/JobDetail.tsx b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/JobDetail.tsx index 2eb4239b35..8ed7927bf6 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/JobDetail.tsx +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/JobDetail.tsx @@ -231,7 +231,10 @@ const KubernetesClusterJobDetail: FunctionComponent< { name: "Events", children: ( - + - + ), }, diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/NamespaceDetail.tsx b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/NamespaceDetail.tsx index a576f9e460..e41802b9df 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/NamespaceDetail.tsx +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/NamespaceDetail.tsx @@ -200,7 +200,10 @@ const KubernetesClusterNamespaceDetail: FunctionComponent< { name: "Events", children: ( - + - + ), }, diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/NodeDetail.tsx b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/NodeDetail.tsx index b4e3d6b4ed..0bc447245c 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/NodeDetail.tsx +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/NodeDetail.tsx @@ -23,7 +23,10 @@ import { Tab } from "Common/UI/Components/Tabs/Tab"; import KubernetesOverviewTab from "../../../Components/Kubernetes/KubernetesOverviewTab"; import KubernetesEventsTab from "../../../Components/Kubernetes/KubernetesEventsTab"; import KubernetesMetricsTab from "../../../Components/Kubernetes/KubernetesMetricsTab"; -import { KubernetesNodeObject } from "../Utils/KubernetesObjectParser"; +import { + KubernetesCondition, + KubernetesNodeObject, +} from "../Utils/KubernetesObjectParser"; import { fetchLatestK8sObject } from "../Utils/KubernetesObjectFetcher"; const KubernetesClusterNodeDetail: FunctionComponent< @@ -230,11 +233,10 @@ const KubernetesClusterNodeDetail: FunctionComponent< if (!nodeObject) { return { label: "Unknown", isReady: false }; } - const readyCondition = nodeObject.status.conditions.find( - (c) => { + const readyCondition: KubernetesCondition | undefined = + nodeObject.status.conditions.find((c: KubernetesCondition) => { return c.type === "Ready"; - }, - ); + }); if (readyCondition && readyCondition.status === "True") { return { label: "Ready", isReady: true }; } @@ -249,7 +251,7 @@ const KubernetesClusterNodeDetail: FunctionComponent< ]; if (nodeObject) { - const nodeStatus = getNodeStatus(); + const nodeStatus: { label: string; isReady: boolean } = getNodeStatus(); summaryFields.push( { diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/PodDetail.tsx b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/PodDetail.tsx index dfed41d26a..79492d4309 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/PodDetail.tsx +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/PodDetail.tsx @@ -294,7 +294,10 @@ const KubernetesClusterPodDetail: FunctionComponent< { name: "Events", children: ( - + + - + ), }, @@ -251,10 +249,7 @@ const KubernetesClusterStatefulSetDetail: FunctionComponent<
- +
diff --git a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/StatefulSets.tsx b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/StatefulSets.tsx index 352a60f552..54cd58b1fd 100644 --- a/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/StatefulSets.tsx +++ b/App/FeatureSet/Dashboard/src/Pages/Kubernetes/View/StatefulSets.tsx @@ -85,7 +85,9 @@ const KubernetesClusterStatefulSets: FunctionComponent< resources={resources} getViewRoute={(resource: KubernetesResource) => { return RouteUtil.populateRouteParams( - RouteMap[PageMap.KUBERNETES_CLUSTER_VIEW_STATEFULSET_DETAIL] as Route, + RouteMap[ + PageMap.KUBERNETES_CLUSTER_VIEW_STATEFULSET_DETAIL + ] as Route, { modelId: modelId, subModelId: new ObjectID(resource.name), diff --git a/App/FeatureSet/Docs/Index.ts b/App/FeatureSet/Docs/Index.ts index f95531a257..7c97deaccc 100755 --- a/App/FeatureSet/Docs/Index.ts +++ b/App/FeatureSet/Docs/Index.ts @@ -90,7 +90,10 @@ const DocsFeatureSet: FeatureSet = { }) .join("\n") : "- No IP addresses configured."; - contentInMarkdown = contentInMarkdown.replace("{{IP_WHITELIST}}", ipList); + contentInMarkdown = contentInMarkdown.replace( + "{{IP_WHITELIST}}", + ipList, + ); } // Render Markdown content to HTML diff --git a/Common/Server/API/IPWhitelistAPI.ts b/Common/Server/API/IPWhitelistAPI.ts index 07bfb23a28..4e9c150fee 100644 --- a/Common/Server/API/IPWhitelistAPI.ts +++ b/Common/Server/API/IPWhitelistAPI.ts @@ -10,24 +10,21 @@ export default class IPWhitelistAPI { public static init(): ExpressRouter { const router: ExpressRouter = Express.getRouter(); - router.get( - "/ip-whitelist", - (req: ExpressRequest, res: ExpressResponse) => { - const ipList: Array = IpWhitelist - ? IpWhitelist.split(",") - .map((ip: string) => { - return ip.trim(); - }) - .filter((ip: string) => { - return ip.length > 0; - }) - : []; + router.get("/ip-whitelist", (req: ExpressRequest, res: ExpressResponse) => { + const ipList: Array = IpWhitelist + ? IpWhitelist.split(",") + .map((ip: string) => { + return ip.trim(); + }) + .filter((ip: string) => { + return ip.length > 0; + }) + : []; - Response.sendJsonObjectResponse(req, res, { - ipWhitelist: ipList, - }); - }, - ); + Response.sendJsonObjectResponse(req, res, { + ipWhitelist: ipList, + }); + }); return router; } diff --git a/Home/Utils/PageSEO.ts b/Home/Utils/PageSEO.ts index f42e417373..8ea5e37d28 100644 --- a/Home/Utils/PageSEO.ts +++ b/Home/Utils/PageSEO.ts @@ -439,8 +439,7 @@ export const PageSEOConfig: Record = { }, "/product/scheduled-maintenance": { - title: - "Scheduled Maintenance | Plan & Communicate Downtime | OneUptime", + title: "Scheduled Maintenance | Plan & Communicate Downtime | OneUptime", description: "Plan, schedule, and communicate maintenance windows to your users. Notify subscribers automatically, update status pages in real-time. Open source maintenance management.", canonicalPath: "/product/scheduled-maintenance",