1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Show all node resources in node view (#2861)

Signed-off-by: vshakirova <vshakirova@mirantis.com>
This commit is contained in:
Violetta 2021-05-27 16:52:35 +04:00 committed by GitHub
parent 81a35737fd
commit 6cee819c8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 165 additions and 21 deletions

View File

@ -52,39 +52,56 @@ export interface INodeMetrics<T = IMetrics> {
export interface Node { export interface Node {
spec: { spec: {
podCIDR: string; podCIDR?: string;
externalID: string; podCIDRs?: string[];
providerID?: string;
/**
* @deprecated see https://issues.k8s.io/61966
*/
externalID?: string;
taints?: { taints?: {
key: string; key: string;
value: string; value: string;
effect: string; effect: string;
timeAdded: string;
}[]; }[];
unschedulable?: boolean; unschedulable?: boolean;
}; };
status: { status: {
capacity: { capacity?: {
cpu: string; cpu: string;
["ephemeral-storage"]: string;
["hugepages-1Gi"]: string;
["hugepages-2Mi"]: string;
memory: string; memory: string;
pods: string; pods: string;
}; };
allocatable: { allocatable?: {
cpu: string; cpu: string;
["ephemeral-storage"]: string;
["hugepages-1Gi"]: string;
["hugepages-2Mi"]: string;
memory: string; memory: string;
pods: string; pods: string;
}; };
conditions: { conditions?: {
type: string; type: string;
status?: string; status: string;
lastHeartbeatTime?: string; lastHeartbeatTime?: string;
lastTransitionTime?: string; lastTransitionTime?: string;
reason?: string; reason?: string;
message?: string; message?: string;
}[]; }[];
addresses: { addresses?: {
type: string; type: string;
address: string; address: string;
}[]; }[];
nodeInfo: { daemonEndpoints?: {
kubeletEndpoint: {
Port: number; //it must be uppercase for backwards compatibility
}
}
nodeInfo?: {
machineID: string; machineID: string;
systemUUID: string; systemUUID: string;
bootID: string; bootID: string;
@ -96,9 +113,14 @@ export interface Node {
operatingSystem: string; operatingSystem: string;
architecture: string; architecture: string;
}; };
images: { images?: {
names: string[]; names: string[];
sizeBytes: number; sizeBytes?: number;
}[];
volumesInUse?: string[];
volumesAttached?: {
name: string;
devicePath: string;
}[]; }[];
}; };
} }

View File

@ -0,0 +1,48 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
.NodeDetailsResources {
.Table {
margin: 0 (-$margin * 3);
}
.TableCell {
&:first-child {
margin-left: $margin;
}
&:last-child {
margin-right: $margin;
}
&.pods {
flex-grow: 0.5;
}
&.memory {
flex-grow: 0.5;
}
&.cpu {
flex-grow:0.5;
}
}
}

View File

@ -0,0 +1,78 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import "./node-details-resources.scss";
import { Table } from "../table/table";
import { TableHead } from "../table/table-head";
import { TableRow } from "../table/table-row";
import React from "react";
import type { Node } from "../../api/endpoints";
import { TableCell } from "../table/table-cell";
interface Props {
node: Node;
type: "allocatable" | "capacity";
}
export class NodeDetailsResources extends React.Component<Props> {
toMi(resource: string) {
if (resource.endsWith("Ki")) {
return `${(parseInt(resource) / 1024).toFixed(1)}Mi`;
}
return resource;
}
render() {
const status = this.props.node.status;
const type = this.props.type;
if (!status) return null;
return (
<div className="NodeDetailsResources flex column">
<Table
selectable
scrollable={false}
>
<TableHead>
<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>
);
}
}

View File

@ -40,6 +40,8 @@ import { KubeEventDetails } from "../+events/kube-event-details";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting";
import { ClusterStore } from "../../../common/cluster-store"; import { ClusterStore } from "../../../common/cluster-store";
import { NodeDetailsResources } from "./node-details-resources";
import { DrawerTitle } from "../drawer/drawer-title";
interface Props extends KubeObjectDetailsProps<Node> { interface Props extends KubeObjectDetailsProps<Node> {
} }
@ -64,7 +66,7 @@ export class NodeDetails extends React.Component<Props> {
if (!node) return null; if (!node) return null;
const { status } = node; const { status } = node;
const { nodeInfo, addresses, capacity, allocatable } = status; const { nodeInfo, addresses } = status;
const conditions = node.getActiveConditions(); const conditions = node.getActiveConditions();
const taints = node.getTaints(); const taints = node.getTaints();
const childPods = podsStore.getPodsByNode(node.getName()); const childPods = podsStore.getPodsByNode(node.getName());
@ -88,16 +90,6 @@ export class NodeDetails extends React.Component<Props> {
</ResourceMetrics> </ResourceMetrics>
)} )}
<KubeObjectMeta object={node} hideFields={["labels", "annotations", "uid", "resourceVersion", "selfLink"]}/> <KubeObjectMeta object={node} hideFields={["labels", "annotations", "uid", "resourceVersion", "selfLink"]}/>
<DrawerItem name="Capacity">
CPU: {capacity.cpu},{" "}
Memory: {Math.floor(parseInt(capacity.memory) / 1024)}Mi,{" "}
Pods: {capacity.pods}
</DrawerItem>
<DrawerItem name="Allocatable">
CPU: {allocatable.cpu},{" "}
Memory: {Math.floor(parseInt(allocatable.memory) / 1024)}Mi,{" "}
Pods: {allocatable.pods}
</DrawerItem>
{addresses && {addresses &&
<DrawerItem name="Addresses"> <DrawerItem name="Addresses">
{ {
@ -167,6 +159,10 @@ export class NodeDetails extends React.Component<Props> {
} }
</DrawerItem> </DrawerItem>
} }
<DrawerTitle title="Capacity"/>
<NodeDetailsResources node={node} type={"capacity"}/>
<DrawerTitle title="Allocatable"/>
<NodeDetailsResources node={node} type={"allocatable"}/>
<PodDetailsList <PodDetailsList
pods={childPods} pods={childPods}
owner={node} owner={node}