Turn on strict mode in tsconfig.json, some helpful lints, and required cleanup where strictness necessitates it (#5195)

* Turn on strict mode in tsconfig.json

- Add route, clusterRoute, and payloadValidatedClusterRoute helper
  functions to improve types with backend routes

- Turn on the following new lints:
  - react/jsx-first-prop-new-line
  - react/jsx-wrap-multilines
  - react/jsx-one-expression-per-line
  - react/jsx-max-props-per-line
  - react/jsx-indent
  - react/jsx-indent-props

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix build

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Replace KubeObject scope strings with enum

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Revert package.json version changes

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* revert move hostedCluster(Id)

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* change some type param names to be not single letters

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove copy-extension-themes

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* add new make clean action

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix build to not use webpack for generating types

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object-menu.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* revert move fileNameMigration to index

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix ref logic error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix log-resource-selector.test.tsx tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-store.test.ts test by overriding createStorage to not touch file system

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster.test.ts tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube=api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fixed hotbar-store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kubeconfig-manager.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster-role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pods.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix delete-cluster-dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix daemonset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix replicaset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix statefulsets/dialog/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix replicasets/scale-dialog/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployments.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployments/scale/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cronjob.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix stateful-set.api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployment.api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix api-manager.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix statefulset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix job.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pods.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix scroll-spy.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix hotbar-remove-command.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog-entity-registry.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix welcome.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix verify-that-all-routes-have-route-component.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pod-tolerations.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* better fix for previous 3 fixes, plus also select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object-menu.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix app-paths.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-tabs.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix isReactNode typing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sub-title.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix drawer.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix list-layout.tsx and header.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix error-boundary.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix upgrade-chart/store.ts and dock-tab.store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix install-chart/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix edit-resource/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix create-resource/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix namespace-select.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix namespace-select-filter.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix crd-list.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix wrong types for extensions

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix circular dependency

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix circular dependency on catalogCategoryRegistry

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix api-kube

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type errors, most <Select /> errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fixing more type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* some more fixing type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* convert all KubeApis to injectable with legacy global backups

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* factor out into a common file all the exports

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* convert all KubeObjectStores to injectable with legacy global backups

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unused legacy KubeApi globals

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix bad previous commit

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* more crash fixing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* try and fix behavioural tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sidebar-and-tab-navigation-for-core.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sidebar-and-tab-navigation-for-extensions.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make ThemeStore non-singleton and fix navigation-to-terminal-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* extensions.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog-entity-registry.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix log-resource-selector.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-tabs.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix delete-cluster-dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-kubernetes-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-editor-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-proxy-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-application-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix hotbar-remove-command.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster-role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-extension-specific-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-telemetry-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix closing-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-editor-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-proxy-preferences.test.ts

- Fix other type errors too

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* final tweaks

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add more tsconfig files, fix bug in <Catalog>

- Make all of history, navigation injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Convert all of kube-details-params/ and navigate/ to injectable

- This fixes a runtime error that was encountered during testing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix runtime errors on renderer

- remove all static uses of `createPageParam` (and then removed the
  legacy global)
- Made LensRendererExtension and LensMainExtension just used
  dependencies and not the getLegacyDi
- Fixed circular dep in extension-loader

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Move registerStore calls to after injectMany

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* replace all the rest of the legacy uses of apiManager

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix stack overflow and cycles in DI

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix NamespaceSelectFilter not opening

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix WizardStep and AddNamespaceDialog

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix KubeApi's not being registered

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* cleanup WindowManager

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Proper fix for Wizard, fix NamespaceStore.subscribe

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Rewrite withTooltip to be more type correct

- Fixes mobx related "too many recursive actions" error

- Change all the uses of withTooltips to be functional components

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add e2e test to cover kube api registration

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* cleanup internal-commands

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove cast in <Animate>

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix command-palette e2e test

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix type error after rebase

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix test name

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix code to help CodeQL scanner

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* update intree extension lock files

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix build-extensions picking wrong @types/react

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix tests from rebase

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make KubeconfigSyncManager more injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix crash in test mode for Dialog

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* make Select snapshots deterministic

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix new type error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object.store.test.ts typing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix merge build issues

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix snapshots after merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint after merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* reexport BaseKubeJsonApiObjectMetadata

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typo in terminalSpawningPool

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove duplicate license header

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typo to waitUntilDefined

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove iter use from getLegacyGlobalDiForExtensionApi

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove complex createStorage override

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* override logger with mocks only when needed for tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove specialized overrideStore flags for getDiForUnitTesting

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unnecessary | undefined types from the exactOptionalFieldTypes experiment

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* use more descriptive name for local test mocks

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unnecessary addition to 'make clean' target

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove oddity of KubeObjectStore.getById(undefined) being allowed

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* rename KubeObject.getDescriptor in favour of name without fundemental JS meaning

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Simplify legacyRegisterApi when working in behaviour unit tests

- Don't emit within main environment as there should be no auto
  registering there

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* change confusing variable name in ReactiveDuration

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* make visitor pattern more explicit for Entity contextMenuOpen

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* toggleDetails -> toggleKubeDetailsPane is more specific

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove outdated comment

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix bug where LensExtension dependencies are not set

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix tests from the revert of react 18

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix more tests from merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typings with new is-compatible-extension tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* more type fixing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Revert in-tree extension versions

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Improve name of guarding injectable for stores and apis

- New name better implies that it is just a guard state and does not do
  anything

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add helper for <Select>.isMulti for storing in a Set<Value>

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix is-compatible-extension.test.ts types

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton authored and GitHub committed 2022-05-16 07:17:57 -04:00
1 parent 381d77c633
commit dfcb7c3330
1062 files changed
+26512 -28689

No files matched your search

@@ -17,46 +17,48 @@ export interface NodeDetailsResourcesProps {
type: "allocatable" | "capacity";
}
export class NodeDetailsResources extends React.Component<NodeDetailsResourcesProps> {
toMi(resource: string) {
if (resource?.endsWith("Ki")) {
return `${(parseInt(resource) / 1024).toFixed(1)}Mi`;
}
return resource;
function toMi(resource: string | undefined) {
if (resource?.endsWith("Ki")) {
return `${(parseInt(resource) / 1024).toFixed(1)}Mi`;
}
render() {
const status = this.props.node.status;
const type = this.props.type;
return resource;
}
if (!status) return null;
export function NodeDetailsResources({ type, node: { status = {}}}: NodeDetailsResourcesProps) {
const resourceStatus = status[type];
return (
<div className="NodeDetailsResources flex column">
<Table
selectable
scrollable={false}
>
<TableHead sticky={false}>
<TableCell className="cpu">CPU</TableCell>
<TableCell className="memory">Memory</TableCell>
<TableCell className="ephemeral-storage">Ephemeral Storage</TableCell>
<TableCell className="hugepages-1Gi">Hugepages-1Gi</TableCell>
<TableCell className="hugepages-2Mi">Hugepages-2Mi</TableCell>
<TableCell className="pods">Pods</TableCell>
</TableHead>
<TableRow>
<TableCell className="cpu">{status[type].cpu}</TableCell>
<TableCell className="memory">{this.toMi(status[type].memory)}</TableCell>
<TableCell
className="ephemeral-storage">{this.toMi(status[type]["ephemeral-storage"])}</TableCell>
<TableCell className="hugepages-1Gi">{status[type]["hugepages-1Gi"]}</TableCell>
<TableCell className="hugepages-2Mi">{status[type]["hugepages-2Mi"]}</TableCell>
<TableCell className="pods">{status[type].pods}</TableCell>
</TableRow>
</Table>
</div>
);
if (!resourceStatus) {
return null;
}
return (
<div className="NodeDetailsResources flex column">
<Table
selectable
scrollable={false}
>
<TableHead sticky={false}>
<TableCell className="cpu">CPU</TableCell>
<TableCell className="memory">Memory</TableCell>
<TableCell className="ephemeral-storage">Ephemeral Storage</TableCell>
<TableCell className="hugepages-1Gi">Hugepages-1Gi</TableCell>
<TableCell className="hugepages-2Mi">Hugepages-2Mi</TableCell>
<TableCell className="pods">Pods</TableCell>
</TableHead>
<TableRow>
<TableCell className="cpu">{resourceStatus.cpu}</TableCell>
<TableCell className="memory">{toMi(resourceStatus.memory)}</TableCell>
<TableCell
className="ephemeral-storage"
>
{toMi(resourceStatus["ephemeral-storage"])}
</TableCell>
<TableCell className="hugepages-1Gi">{resourceStatus["hugepages-1Gi"]}</TableCell>
<TableCell className="hugepages-2Mi">{resourceStatus["hugepages-2Mi"]}</TableCell>
<TableCell className="pods">{resourceStatus.pods}</TableCell>
</TableRow>
</Table>
</div>
);
}
+88 -84
View File
@@ -12,36 +12,37 @@ import { disposeOnUnmount, observer } from "mobx-react";
import { DrawerItem, DrawerItemLabels } from "../drawer";
import { Badge } from "../badge";
import { ResourceMetrics } from "../resource-metrics";
import { podsStore } from "../+workloads-pods/pods.store";
import type { KubeObjectDetailsProps } from "../kube-object-details";
import type { IClusterMetrics } from "../../../common/k8s-api/endpoints";
import type { ClusterMetricData } from "../../../common/k8s-api/endpoints";
import { formatNodeTaint, getMetricsByNodeNames, Node } from "../../../common/k8s-api/endpoints";
import { NodeCharts } from "./node-charts";
import { makeObservable, observable, reaction } from "mobx";
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
import { KubeObjectMeta } from "../kube-object-meta";
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
import { NodeDetailsResources } from "./details-resources";
import { DrawerTitle } from "../drawer/drawer-title";
import type { Disposer } from "../../utils";
import logger from "../../../common/logger";
import type { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
import { withInjectables } from "@ogre-tools/injectable-react";
import kubeWatchApiInjectable
from "../../kube-watch-api/kube-watch-api.injectable";
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
import type { PodStore } from "../+workloads-pods/store";
import podStoreInjectable from "../+workloads-pods/store.injectable";
import type { GetActiveClusterEntity } from "../../api/catalog/entity/get-active-cluster-entity.injectable";
import getActiveClusterEntityInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable";
export interface NodeDetailsProps extends KubeObjectDetailsProps<Node> {
}
interface Dependencies {
subscribeStores: (stores: KubeObjectStore<KubeObject>[]) => Disposer;
subscribeStores: SubscribeStores;
podStore: PodStore;
getActiveClusterEntity: GetActiveClusterEntity;
}
@observer
class NonInjectedNodeDetails extends React.Component<NodeDetailsProps & Dependencies> {
@observable metrics: Partial<IClusterMetrics>;
@observable metrics: Partial<ClusterMetricData> | null = null;
constructor(props: NodeDetailsProps & Dependencies) {
super(props);
@@ -55,7 +56,7 @@ class NonInjectedNodeDetails extends React.Component<NodeDetailsProps & Dependen
}),
this.props.subscribeStores([
podsStore,
this.props.podStore,
]),
]);
}
@@ -67,7 +68,7 @@ class NonInjectedNodeDetails extends React.Component<NodeDetailsProps & Dependen
};
render() {
const { object: node } = this.props;
const { object: node, podStore, getActiveClusterEntity } = this.props;
if (!node) {
return null;
@@ -79,55 +80,61 @@ class NonInjectedNodeDetails extends React.Component<NodeDetailsProps & Dependen
return null;
}
const { status } = node;
const { nodeInfo, addresses } = status;
const { nodeInfo, addresses } = node.status ?? {};
const conditions = node.getActiveConditions();
const taints = node.getTaints();
const childPods = podsStore.getPodsByNode(node.getName());
const childPods = podStore.getPodsByNode(node.getName());
const { metrics } = this;
const metricTabs = [
"CPU",
"Memory",
"Disk",
"Pods",
];
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Node);
return (
<div className="NodeDetails">
{!isMetricHidden && podsStore.isLoaded && (
{!isMetricHidden && podStore.isLoaded && (
<ResourceMetrics
loader={this.loadMetrics}
tabs={metricTabs} object={node} params={{ metrics }}
tabs={[
"CPU",
"Memory",
"Disk",
"Pods",
]}
object={node}
metrics={metrics}
>
<NodeCharts/>
</ResourceMetrics>
)}
<KubeObjectMeta object={node} hideFields={["labels", "annotations", "uid", "resourceVersion", "selfLink"]}/>
{addresses &&
<DrawerItem name="Addresses">
{
addresses.map(({ type, address }) => (
<p key={type}>{type}: {address}</p>
))
}
</DrawerItem>
}
<DrawerItem name="OS">
{nodeInfo.operatingSystem} ({nodeInfo.architecture})
</DrawerItem>
<DrawerItem name="OS Image">
{nodeInfo.osImage}
</DrawerItem>
<DrawerItem name="Kernel version">
{nodeInfo.kernelVersion}
</DrawerItem>
<DrawerItem name="Container runtime">
{nodeInfo.containerRuntimeVersion}
</DrawerItem>
<DrawerItem name="Kubelet version">
{nodeInfo.kubeletVersion}
</DrawerItem>
{addresses && (
<DrawerItem name="Addresses">
{
addresses.map(({ type, address }) => (
<p key={type}>
{`${type}: ${address}`}
</p>
))
}
</DrawerItem>
)}
{nodeInfo && (
<>
<DrawerItem name="OS">
{`${nodeInfo.operatingSystem} (${nodeInfo.architecture})`}
</DrawerItem>
<DrawerItem name="OS Image">
{nodeInfo.osImage}
</DrawerItem>
<DrawerItem name="Kernel version">
{nodeInfo.kernelVersion}
</DrawerItem>
<DrawerItem name="Container runtime">
{nodeInfo.containerRuntimeVersion}
</DrawerItem>
<DrawerItem name="Kubelet version">
{nodeInfo.kubeletVersion}
</DrawerItem>
</>
)}
<DrawerItemLabels
name="Labels"
labels={node.getLabels()}
@@ -141,38 +148,37 @@ class NonInjectedNodeDetails extends React.Component<NodeDetailsProps & Dependen
{taints.map(taint => <Badge key={taint.key} label={formatNodeTaint(taint)} />)}
</DrawerItem>
)}
{conditions &&
<DrawerItem name="Conditions" className="conditions" labelsOnly>
{
conditions.map(condition => {
const { type } = condition;
return (
<Badge
key={type}
label={type}
className={kebabCase(type)}
tooltip={{
formatters: {
tableView: true,
},
children: Object.entries(condition).map(([key, value]) =>
{conditions && (
<DrawerItem
name="Conditions"
className="conditions"
labelsOnly
>
{conditions.map(condition => (
<Badge
key={condition.type}
label={condition.type}
className={kebabCase(condition.type)}
tooltip={{
formatters: {
tableView: true,
},
children: Object.entries(condition)
.map(([key, value]) => (
<div key={key} className="flex gaps align-center">
<div className="name">{upperFirst(key)}</div>
<div className="value">{value}</div>
</div>,
),
}}
/>
);
})
}
</DrawerItem>
}
</div>
)),
}}
/>
))}
</DrawerItem>
)}
<DrawerTitle>Capacity</DrawerTitle>
<NodeDetailsResources node={node} type={"capacity"}/>
<NodeDetailsResources node={node} type="capacity"/>
<DrawerTitle>Allocatable</DrawerTitle>
<NodeDetailsResources node={node} type={"allocatable"}/>
<NodeDetailsResources node={node} type="allocatable"/>
<PodDetailsList
pods={childPods}
owner={node}
@@ -184,14 +190,12 @@ class NonInjectedNodeDetails extends React.Component<NodeDetailsProps & Dependen
}
}
export const NodeDetails = withInjectables<Dependencies, NodeDetailsProps>(
NonInjectedNodeDetails,
{
getProps: (di, props) => ({
subscribeStores: di.inject(kubeWatchApiInjectable).subscribeStores,
...props,
}),
},
);
export const NodeDetails = withInjectables<Dependencies, NodeDetailsProps>(NonInjectedNodeDetails, {
getProps: (di, props) => ({
...props,
subscribeStores: di.inject(subscribeStoresInjectable),
podStore: di.inject(podStoreInjectable),
getActiveClusterEntity: di.inject(getActiveClusterEntityInjectable),
}),
});
@@ -0,0 +1,12 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { asLegacyGlobalForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
import nodeStoreInjectable from "./store.injectable";
/**
* @deprecated use `di.inject(nodeStoreInjectable)` instead
*/
export const nodeStore = asLegacyGlobalForExtensionApi(nodeStoreInjectable);
+35 -52
View File
@@ -4,32 +4,34 @@
*/
import React, { useContext } from "react";
import type { IClusterMetrics, Node } from "../../../common/k8s-api/endpoints";
import { BarChart, cpuOptions, memoryOptions } from "../chart";
import type { ChartDataSets } from "../chart";
import { BarChart } from "../chart";
import { isMetricsEmpty, normalizeMetrics } from "../../../common/k8s-api/endpoints/metrics.api";
import { NoMetrics } from "../resource-metrics/no-metrics";
import type { IResourceMetricsValue } from "../resource-metrics";
import { ResourceMetricsContext } from "../resource-metrics";
import { observer } from "mobx-react";
import type { ChartOptions, ChartPoint } from "chart.js";
import { ThemeStore } from "../../theme.store";
import { mapValues } from "lodash";
import { type MetricsTab, metricTabOptions } from "../chart/options";
import type { ThemeStore } from "../../themes/store";
import { withInjectables } from "@ogre-tools/injectable-react";
import themeStoreInjectable from "../../themes/store.injectable";
type IContext = IResourceMetricsValue<Node, { metrics: IClusterMetrics }>;
export interface NodeChartsProps {}
interface Dependencies {
themeStore: ThemeStore;
}
const NonInjectedNodeCharts = observer(({
themeStore,
}: Dependencies & NodeChartsProps) => {
const { metrics, tab, object } = useContext(ResourceMetricsContext) ?? {};
if (!metrics || !object || !tab) return null;
if (isMetricsEmpty(metrics)) return <NoMetrics/>;
export const NodeCharts = observer(() => {
const { params: { metrics }, tabId, object } = useContext<IContext>(ResourceMetricsContext);
const id = object.getId();
const { chartCapacityColor } = ThemeStore.getInstance().activeTheme.colors;
if (!metrics) {
return null;
}
if (isMetricsEmpty(metrics)) {
return <NoMetrics />;
}
const { chartCapacityColor } = themeStore.activeTheme.colors;
const {
memoryUsage,
workloadMemoryUsage,
@@ -46,9 +48,8 @@ export const NodeCharts = observer(() => {
fsUsage,
} = mapValues(metrics, metric => normalizeMetrics(metric).data.result[0].values);
const datasets = [
// CPU
[
const datasets: Partial<Record<MetricsTab, ChartDataSets[]>> = {
CPU: [
{
id: `${id}-cpuUsage`,
label: `Usage`,
@@ -78,8 +79,7 @@ export const NodeCharts = observer(() => {
data: cpuCapacity.map(([x, y]) => ({ x, y })),
},
],
// Memory
[
Memory: [
{
id: `${id}-memoryUsage`,
label: `Usage`,
@@ -116,8 +116,7 @@ export const NodeCharts = observer(() => {
data: memoryCapacity.map(([x, y]) => ({ x, y })),
},
],
// Disk
[
Disk: [
{
id: `${id}-fsUsage`,
label: `Usage`,
@@ -133,8 +132,7 @@ export const NodeCharts = observer(() => {
data: fsSize.map(([x, y]) => ({ x, y })),
},
],
// Pods
[
Pods: [
{
id: `${id}-podUsage`,
label: `Usage`,
@@ -150,35 +148,20 @@ export const NodeCharts = observer(() => {
data: podCapacity.map(([x, y]) => ({ x, y })),
},
],
];
const podOptions: ChartOptions = {
scales: {
yAxes: [{
ticks: {
callback: value => value,
},
}],
},
tooltips: {
callbacks: {
label: ({ datasetIndex, index }, { datasets }) => {
const { label, data } = datasets[datasetIndex];
const value = data[index] as ChartPoint;
return `${label}: ${value.y}`;
},
},
},
};
const options = [cpuOptions, memoryOptions, memoryOptions, podOptions];
return (
<BarChart
name={`${object.getName()}-metric-${tabId}`}
options={options[tabId]}
data={{ datasets: datasets[tabId] }}
name={`${object.getName()}-metric-${tab}`}
options={metricTabOptions[tab]}
data={{ datasets: datasets[tab] }}
/>
);
});
export const NodeCharts = withInjectables<Dependencies, NodeChartsProps>(NonInjectedNodeCharts, {
getProps: (di, props) => ({
...props,
themeStore: di.inject(themeStoreInjectable),
}),
});
+29 -15
View File
@@ -8,10 +8,10 @@ import React from "react";
import { observer } from "mobx-react";
import { cssNames, interval } from "../../utils";
import { TabLayout } from "../layout/tab-layout-2";
import { nodesStore } from "./nodes.store";
import { nodeStore } from "./legacy-store";
import { KubeObjectListLayout } from "../kube-object-list-layout";
import type { INodeMetrics, Node } from "../../../common/k8s-api/endpoints/nodes.api";
import { formatNodeTaint, getMetricsForAllNodes } from "../../../common/k8s-api/endpoints/nodes.api";
import type { NodeMetricData, Node } from "../../../common/k8s-api/endpoints/node.api";
import { formatNodeTaint, getMetricsForAllNodes } from "../../../common/k8s-api/endpoints/node.api";
import { LineProgress } from "../line-progress";
import { bytesToUnits } from "../../../common/utils/convertMemory";
import { Tooltip, TooltipPosition } from "../tooltip";
@@ -19,7 +19,7 @@ import kebabCase from "lodash/kebabCase";
import upperFirst from "lodash/upperFirst";
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
import { Badge } from "../badge/badge";
import { eventStore } from "../+events/event.store";
import { eventStore } from "../+events/legacy-store";
import { makeObservable, observable } from "mobx";
import isEmpty from "lodash/isEmpty";
import { KubeObjectAge } from "../kube-object/age";
@@ -48,7 +48,7 @@ interface UsageArgs {
@observer
export class NodesRoute extends React.Component {
@observable.ref metrics: Partial<INodeMetrics> = {};
@observable.ref metrics: Partial<NodeMetricData> = {};
private metricsWatcher = interval(30, async () => this.metrics = await getMetricsForAllNodes());
constructor(props: any) {
@@ -74,7 +74,7 @@ export class NodesRoute extends React.Component {
return metricNames.map(metricName => {
try {
const metric = this.metrics[metricName];
const result = metric.data.result.find(({ metric: { node, instance, kubernetes_node }}) => (
const result = metric?.data.result.find(({ metric: { node, instance, kubernetes_node }}) => (
nodeName === node
|| nodeName === instance
|| nodeName === kubernetes_node
@@ -145,7 +145,7 @@ export class NodesRoute extends React.Component {
}
renderConditions(node: Node) {
if (!node.status.conditions) {
if (!node.status?.conditions) {
return null;
}
@@ -154,14 +154,19 @@ export class NodesRoute extends React.Component {
const tooltipId = `node-${node.getName()}-condition-${type}`;
return (
<div key={type} id={tooltipId} className={cssNames("condition", kebabCase(type))}>
<div
key={type}
id={tooltipId}
className={cssNames("condition", kebabCase(type))}
>
{type}
<Tooltip targetId={tooltipId} formatters={{ tableView: true }}>
{Object.entries(condition).map(([key, value]) =>
{Object.entries(condition).map(([key, value]) => (
<div key={key} className="flex gaps align-center">
<div className="name">{upperFirst(key)}</div>
<div className="value">{value}</div>
</div>,
</div>
),
)}
</Tooltip>
</div>
@@ -176,8 +181,8 @@ export class NodesRoute extends React.Component {
isConfigurable
tableId="nodes"
className="Nodes"
store={nodesStore}
isReady={nodesStore.isLoaded}
store={nodeStore}
isReady={nodeStore.isLoaded}
dependentStores={[eventStore]}
isSelectable={false}
sortingCallbacks={{
@@ -215,19 +220,28 @@ export class NodesRoute extends React.Component {
const taints = node.getTaints();
return [
<Badge flat key="name" label={node.getName()} tooltip={node.getName()} />,
<Badge
flat
key="name"
label={node.getName()}
tooltip={node.getName()}
/>,
<KubeObjectStatusIcon key="icon" object={node} />,
this.renderCpuUsage(node),
this.renderMemoryUsage(node),
this.renderDiskUsage(node),
<>
<span id={tooltipId}>{taints.length}</span>
<Tooltip targetId={tooltipId} tooltipOnParentHover={true} style={{ whiteSpace: "pre-line" }}>
<Tooltip
targetId={tooltipId}
tooltipOnParentHover={true}
style={{ whiteSpace: "pre-line" }}
>
{taints.map(formatNodeTaint).join("\n")}
</Tooltip>
</>,
node.getRoleLabels(),
node.status.nodeInfo.kubeletVersion,
node.getKubeletVersion(),
<KubeObjectAge key="age" object={node} />,
this.renderConditions(node),
];
@@ -0,0 +1,24 @@
/**
* 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 assert from "assert";
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
import nodeApiInjectable from "../../../common/k8s-api/endpoints/node.api.injectable";
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
import { NodeStore } from "./store";
const nodeStoreInjectable = getInjectable({
id: "node-store",
instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectable), "nodeStore is only available in certain environments");
const api = di.inject(nodeApiInjectable);
return new NodeStore(api);
},
injectionToken: kubeObjectStoreInjectionToken,
});
export default nodeStoreInjectable;
@@ -5,17 +5,14 @@
import { sum } from "lodash";
import { computed, makeObservable } from "mobx";
import { apiManager } from "../../../common/k8s-api/api-manager";
import type { Node } from "../../../common/k8s-api/endpoints";
import { nodesApi } from "../../../common/k8s-api/endpoints";
import type { Node, NodeApi } from "../../../common/k8s-api/endpoints";
import type { KubeObjectStoreOptions } from "../../../common/k8s-api/kube-object.store";
import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
import { autoBind } from "../../utils";
export class NodesStore extends KubeObjectStore<Node> {
api = nodesApi;
constructor() {
super();
export class NodeStore extends KubeObjectStore<Node, NodeApi> {
constructor(api: NodeApi, opts?: KubeObjectStoreOptions) {
super(api, opts);
makeObservable(this);
autoBind(this);
@@ -30,9 +27,6 @@ export class NodesStore extends KubeObjectStore<Node> {
}
getWarningsCount(): number {
return sum(this.items.map((node: Node) => node.getWarningConditions().length));
return sum(this.items.map((node) => node.getWarningConditions().length));
}
}
export const nodesStore = new NodesStore();
apiManager.registerStore(nodesStore);