mirror of
https://github.com/skooner-k8s/skooner.git
synced 2026-08-24 04:16:18 +00:00
A lot of charts work
This commit is contained in:
@@ -16,7 +16,8 @@ export default class Base extends Component {
|
||||
}
|
||||
|
||||
async clearDisposers() {
|
||||
for (const name of Object.keys(this.apis || {})) {
|
||||
const keys = Object.keys(this.apis || {});
|
||||
for (const name of keys) {
|
||||
this.clearDisposer(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export default function EventsPanel({items, filter, shortList, sort}) {
|
||||
<div className='td_iconLabel'>{x.involvedObject.kind}</div>
|
||||
</td>
|
||||
{!shortList && (
|
||||
<td>{x.involvedObject.namespace}:{x.involvedObject.name}</td>
|
||||
<td className='wrapped_name'>{x.involvedObject.namespace}:{x.involvedObject.name}</td>
|
||||
)}
|
||||
<td>{moment(x.metadata.creationTimestamp).fromNow(true)}</td>
|
||||
<td className='optional_small'>{x.reason}</td>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import './loadingChart.scss';
|
||||
import React from 'react';
|
||||
import ChartistGraph from 'react-chartist';
|
||||
|
||||
@@ -13,8 +14,10 @@ export default function Chart() {
|
||||
return (
|
||||
<div className='charts_donut'>
|
||||
<ChartistGraph data={{series: [0, 0, 1]}} options={options} type='Pie' />
|
||||
<span className='chart_donutLabel'>
|
||||
...
|
||||
<span className='chart_donutLabel loadingChart'>
|
||||
<span>.</span>
|
||||
<span>.</span>
|
||||
<span>.</span>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
.loadingChart span {
|
||||
animation-name: blink;
|
||||
animation-duration: 2s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0% {
|
||||
opacity: .1;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: .1;
|
||||
}
|
||||
}
|
||||
|
||||
.loadingChart span:nth-child(2) {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.loadingChart span:nth-child(3) {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import Chart from './chart';
|
||||
import LoadingChart from './loadingChart';
|
||||
import {parseCpu, TO_ONE_CPU} from '../utils/unitHelpers';
|
||||
|
||||
export default function NodeCpuChart({items, metrics}) {
|
||||
const totals = getNodeCpuTotals(items, metrics);
|
||||
|
||||
return (
|
||||
<div className='charts_item'>
|
||||
{totals ? (
|
||||
<Chart used={totals.used} available={totals.available} />
|
||||
) : (
|
||||
<LoadingChart />
|
||||
)}
|
||||
<div className='charts_itemLabel'>Node Cpu Use</div>
|
||||
<div className='charts_itemSubLabel'>Used vs Available</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getNodeCpuTotals(items, metrics) {
|
||||
if (!items || !metrics) return null;
|
||||
|
||||
const metricValues = Object.values(metrics);
|
||||
const used = _.sumBy(metricValues, x => parseCpu(x.usage.cpu)) / TO_ONE_CPU;
|
||||
const available = _.sumBy(items, x => parseCpu(x.status.capacity.cpu)) / TO_ONE_CPU;
|
||||
|
||||
return {used, available};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import Chart from './chart';
|
||||
import LoadingChart from './loadingChart';
|
||||
import {parseRam, TO_GB} from '../utils/unitHelpers';
|
||||
|
||||
export default function NodeRamChart({items, metrics}) {
|
||||
const totals = getNodeRamTotals(items, metrics);
|
||||
return (
|
||||
<div className='charts_item'>
|
||||
{totals ? (
|
||||
<Chart used={totals.used} usedSuffix='Gb' available={totals.available} availableSuffix='Gb' />
|
||||
) : (
|
||||
<LoadingChart />
|
||||
)}
|
||||
<div className='charts_itemLabel'>Node Ram Use</div>
|
||||
<div className='charts_itemSubLabel'>Used vs Available</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getNodeRamTotals(items, metrics) {
|
||||
if (!items || !metrics) return null;
|
||||
|
||||
const metricValues = Object.values(metrics);
|
||||
const used = _.sumBy(metricValues, x => parseRam(x.usage.memory)) / TO_GB;
|
||||
const available = _.sumBy(items, x => parseRam(x.status.capacity.memory)) / TO_GB;
|
||||
|
||||
return {used, available};
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import Chart from './chart';
|
||||
import LoadingChart from './loadingChart';
|
||||
import {parseCpu, TO_ONE_CPU} from '../utils/unitHelpers';
|
||||
|
||||
export default function CpuChart({items, metrics}) {
|
||||
export default function PodCpuChart({items, metrics}) {
|
||||
const totals = getPodCpuTotals(items, metrics);
|
||||
const decimals = totals && totals.used > 10 ? 1 : 2;
|
||||
|
||||
@@ -25,14 +25,14 @@ export default function CpuChart({items, metrics}) {
|
||||
);
|
||||
}
|
||||
|
||||
function getPodCpuTotals(items, metrics) {
|
||||
if (!items || !metrics) return null;
|
||||
function getPodCpuTotals(pods, metrics) {
|
||||
if (!pods || !metrics) return null;
|
||||
|
||||
const used = _(metrics)
|
||||
.flatMap(x => x.containers)
|
||||
.sumBy(x => parseCpu(x.usage.cpu));
|
||||
|
||||
const available = _(items)
|
||||
const available = _(pods)
|
||||
.flatMap(x => x.spec.containers)
|
||||
.filter(x => x.resources && x.resources.requests)
|
||||
.sumBy(x => parseCpu(x.resources.requests.cpu));
|
||||
@@ -20,7 +20,7 @@ $ct-series-colors: (
|
||||
|
||||
.charts_item {
|
||||
color: $color-dark;
|
||||
box-shadow: 0 0 5px 0 $color-dark;
|
||||
box-shadow: 0 0 5px 0 $color-light;
|
||||
background-color: $color-white;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
||||
@@ -53,4 +53,8 @@ td {
|
||||
.wrapped > tbody > tr > td {
|
||||
padding: 0.25rem;
|
||||
}
|
||||
|
||||
.wrapped .wrapped_name {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
export default function getPodMetrics(pods, metrics) {
|
||||
if (!pods || !metrics) return null;
|
||||
export default function getMetrics(items, metrics) {
|
||||
if (!items || !metrics) return null;
|
||||
|
||||
const names = _.map(pods, x => x.metadata.name);
|
||||
const names = _.map(items, x => x.metadata.name);
|
||||
const filteredMetrics = metrics.filter(x => names.includes(x.metadata.name));
|
||||
|
||||
return _.keyBy(filteredMetrics, 'metadata.name');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import Base from '../components/base';
|
||||
import ContainersPanel from '../components/containersPanel';
|
||||
import CpuChart from '../components/cpuChart';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import DeleteButton from '../components/deleteButton';
|
||||
import EventsPanel from '../components/eventsPanel';
|
||||
import Field from '../components/field';
|
||||
@@ -9,10 +9,10 @@ import ItemHeader from '../components/itemHeader';
|
||||
import Loading from '../components/loading';
|
||||
import MetadataFields from '../components/metadataFields';
|
||||
import PodsPanel from '../components/podsPanel';
|
||||
import RamChart from '../components/ramChart';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import SaveButton from '../components/saveButton';
|
||||
import api from '../services/api';
|
||||
import getPodMetrics from '../utils/metricsHelpers';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
import {filterByOwner} from '../utils/filterHelper';
|
||||
import {defaultSortInfo} from '../components/sorter';
|
||||
import ChartsContainer from '../components/chartsContainer';
|
||||
@@ -42,7 +42,7 @@ export default class CronJob extends Base {
|
||||
|
||||
const filteredPods = filterByOwner(pods, item);
|
||||
const filteredEvents = filterByOwner(events, item);
|
||||
const filteredMetrics = getPodMetrics(filteredPods, metrics);
|
||||
const filteredMetrics = getMetrics(filteredPods, metrics);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
@@ -64,8 +64,8 @@ export default class CronJob extends Base {
|
||||
<div className='charts_number'>{(item && item.status.active) ? item.status.active.length : 0}</div>
|
||||
<div className='charts_itemLabel'>Active</div>
|
||||
</div>
|
||||
<CpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<RamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodCpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodRamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<div className='contentPanel'>
|
||||
|
||||
@@ -10,9 +10,9 @@ import EventsPanel from '../components/eventsPanel';
|
||||
import PodsPanel from '../components/podsPanel';
|
||||
import Chart from '../components/chart';
|
||||
import LoadingChart from '../components/loadingChart';
|
||||
import RamChart from '../components/ramChart';
|
||||
import CpuChart from '../components/cpuChart';
|
||||
import getPodMetrics from '../utils/metricsHelpers';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
import {filterByOwner} from '../utils/filterHelper';
|
||||
import ContainersPanel from '../components/containersPanel';
|
||||
import {defaultSortInfo} from '../components/sorter';
|
||||
@@ -43,7 +43,7 @@ export default class DaemonSet extends Base {
|
||||
|
||||
const filteredPods = filterByOwner(pods, item);
|
||||
const filteredEvents = filterByOwner(events, item);
|
||||
const filteredMetrics = getPodMetrics(filteredPods, metrics);
|
||||
const filteredMetrics = getMetrics(filteredPods, metrics);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
@@ -74,8 +74,8 @@ export default class DaemonSet extends Base {
|
||||
<div className='charts_itemLabel'>Replicas</div>
|
||||
<div className='charts_itemSubLabel'>Ready vs Requested</div>
|
||||
</div>
|
||||
<CpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<RamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodCpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodRamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<div className='contentPanel'>
|
||||
|
||||
@@ -8,9 +8,11 @@ import NodeStatusChart from '../components/nodeStatusChart';
|
||||
import test from '../utils/filterHelper';
|
||||
import {defaultSortInfo, sortByDate} from '../components/sorter';
|
||||
import PodStatusChart from '../components/podStatusChart';
|
||||
import CpuChart from '../components/cpuChart';
|
||||
import RamChart from '../components/ramChart';
|
||||
import getPodMetrics from '../utils/metricsHelpers';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import NodeCpuChart from '../components/nodeCpuChart';
|
||||
import NodeRamChart from '../components/nodeRamChart';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
|
||||
export default class Dashboard extends Base {
|
||||
state = {
|
||||
@@ -24,13 +26,15 @@ export default class Dashboard extends Base {
|
||||
pods: api.pod.list(null, pods => this.setState({pods})),
|
||||
podMetrics: api.metrics.pods(null, podMetrics => this.setState({podMetrics})),
|
||||
nodes: api.node.list(nodes => this.setState({nodes})),
|
||||
nodeMetrics: api.metrics.nodes(nodeMetrics => this.setState({nodeMetrics})),
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {events, pods, podMetrics, nodes, sort, filter} = this.state;
|
||||
const {events, pods, podMetrics, nodes, nodeMetrics, sort, filter} = this.state;
|
||||
const filteredEvents = filterEvents(events, filter);
|
||||
const filteredPodMetrics = getPodMetrics(pods, podMetrics);
|
||||
const filteredPodMetrics = getMetrics(pods, podMetrics);
|
||||
const filteredNodeMetrics = getMetrics(nodes, nodeMetrics);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
@@ -42,9 +46,14 @@ export default class Dashboard extends Base {
|
||||
|
||||
<ChartsContainer>
|
||||
<NodeStatusChart items={nodes} />
|
||||
<NodeCpuChart items={nodes} metrics={filteredNodeMetrics} />
|
||||
<NodeRamChart items={nodes} metrics={filteredNodeMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<ChartsContainer>
|
||||
<PodStatusChart items={pods} />
|
||||
<CpuChart items={pods} metrics={filteredPodMetrics} />
|
||||
<RamChart items={pods} metrics={filteredPodMetrics} />
|
||||
<PodCpuChart items={pods} metrics={filteredPodMetrics} />
|
||||
<PodRamChart items={pods} metrics={filteredPodMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<div className='contentPanel_header'>Events</div>
|
||||
@@ -58,6 +67,6 @@ function filterEvents(events, filter) {
|
||||
if (!events) return null;
|
||||
|
||||
return events
|
||||
.filter(x => test(filter, x.involvedObject.name, x.involvedObject.namespace, x.message))
|
||||
.filter(x => test(filter, x.involvedObject.name, x.reason, x.message))
|
||||
.slice(0, 250);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import React from 'react';
|
||||
import Base from '../components/base';
|
||||
import ContainersPanel from '../components/containersPanel';
|
||||
import CpuChart from '../components/cpuChart';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import DeleteButton from '../components/deleteButton';
|
||||
import EventsPanel from '../components/eventsPanel';
|
||||
import ItemHeader from '../components/itemHeader';
|
||||
import Loading from '../components/loading';
|
||||
import MetadataFields from '../components/metadataFields';
|
||||
import PodsPanel from '../components/podsPanel';
|
||||
import RamChart from '../components/ramChart';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import ReplicaSetsPanel from '../components/replicaSetsPanel';
|
||||
import SaveButton from '../components/saveButton';
|
||||
import ScaleButton from '../components/scaleButton';
|
||||
import api from '../services/api';
|
||||
import {filterByOwner, filterByOwners} from '../utils/filterHelper';
|
||||
import getPodMetrics from '../utils/metricsHelpers';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
import {defaultSortInfo} from '../components/sorter';
|
||||
import ReplicasChart from '../components/replicasChart';
|
||||
import ChartsContainer from '../components/chartsContainer';
|
||||
@@ -56,7 +56,7 @@ export default class Deployment extends Base {
|
||||
const filteredEvents = filterByOwner(events, item);
|
||||
const filteredReplicaSets = filterByOwner(replicaSets, item);
|
||||
const filteredPods = filterByOwners(pods, filteredReplicaSets);
|
||||
const filteredMetrics = getPodMetrics(filteredPods, metrics);
|
||||
const filteredMetrics = getMetrics(filteredPods, metrics);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
@@ -81,8 +81,8 @@ export default class Deployment extends Base {
|
||||
|
||||
<ChartsContainer>
|
||||
<ReplicasChart item={item} />
|
||||
<CpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<RamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodCpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodRamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<div className='contentPanel'>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import Base from '../components/base';
|
||||
import ContainersPanel from '../components/containersPanel';
|
||||
import CpuChart from '../components/cpuChart';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import DeleteButton from '../components/deleteButton';
|
||||
import EventsPanel from '../components/eventsPanel';
|
||||
import Field from '../components/field';
|
||||
@@ -9,10 +9,10 @@ import ItemHeader from '../components/itemHeader';
|
||||
import Loading from '../components/loading';
|
||||
import MetadataFields from '../components/metadataFields';
|
||||
import PodsPanel from '../components/podsPanel';
|
||||
import RamChart from '../components/ramChart';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import SaveButton from '../components/saveButton';
|
||||
import api from '../services/api';
|
||||
import getPodMetrics from '../utils/metricsHelpers';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
import {filterByOwner} from '../utils/filterHelper';
|
||||
import {defaultSortInfo} from '../components/sorter';
|
||||
import ChartsContainer from '../components/chartsContainer';
|
||||
@@ -42,7 +42,7 @@ export default class Job extends Base {
|
||||
|
||||
const filteredPods = filterByOwner(pods, item);
|
||||
const filteredEvents = filterByOwner(events, item);
|
||||
const filteredMetrics = getPodMetrics(filteredPods, metrics);
|
||||
const filteredMetrics = getMetrics(filteredPods, metrics);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
@@ -70,8 +70,8 @@ export default class Job extends Base {
|
||||
</div>
|
||||
<div className='charts_itemLabel'>Active / Succeeded</div>
|
||||
</div>
|
||||
<CpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<RamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodCpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodRamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<div className='contentPanel'>
|
||||
|
||||
@@ -6,23 +6,38 @@ import Loading from '../components/loading';
|
||||
import Field from '../components/field';
|
||||
import MetadataFields from '../components/metadataFields';
|
||||
import DeleteButton from '../components/deleteButton';
|
||||
import PodsPanel from '../components/podsPanel';
|
||||
import EventsPanel from '../components/eventsPanel';
|
||||
import {defaultSortInfo} from '../components/sorter';
|
||||
import ChartsContainer from '../components/chartsContainer';
|
||||
import PodStatusChart from '../components/podStatusChart';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
|
||||
const service = api.namespace;
|
||||
|
||||
export default class Namespace extends Base {
|
||||
state = {
|
||||
podsSort: defaultSortInfo(x => this.setState({podsSort: x})),
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const {namespace} = this.props;
|
||||
|
||||
this.registerApi({
|
||||
item: service.get(namespace, item => this.setState({item})),
|
||||
events: api.event.list(namespace, events => this.setState({events})),
|
||||
pods: api.pod.list(namespace, pods => this.setState({pods})),
|
||||
podMetrics: api.metrics.pods(namespace, podMetrics => this.setState({podMetrics})),
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {namespace} = this.props;
|
||||
const {item, events} = this.state || {};
|
||||
const {item, events, pods, podMetrics, podsSort} = this.state;
|
||||
|
||||
const filteredPodMetrics = getMetrics(pods, podMetrics);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
@@ -34,6 +49,12 @@ export default class Namespace extends Base {
|
||||
</>
|
||||
</ItemHeader>
|
||||
|
||||
<ChartsContainer>
|
||||
<PodStatusChart items={pods} />
|
||||
<PodCpuChart items={pods} metrics={filteredPodMetrics} />
|
||||
<PodRamChart items={pods} metrics={filteredPodMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<div className='contentPanel'>
|
||||
{!item ? <Loading /> : (
|
||||
<div>
|
||||
@@ -43,6 +64,15 @@ export default class Namespace extends Base {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className='contentPanel_header'>Pods</div>
|
||||
<PodsPanel
|
||||
items={pods}
|
||||
sort={podsSort}
|
||||
metrics={filteredPodMetrics}
|
||||
skipNamespace={true}
|
||||
skipNodeName={false}
|
||||
/>
|
||||
|
||||
<div className='contentPanel_header'>Events</div>
|
||||
<EventsPanel items={events} />
|
||||
</div>
|
||||
|
||||
+32
-50
@@ -3,17 +3,20 @@ import React from 'react';
|
||||
import moment from 'moment';
|
||||
import api from '../services/api';
|
||||
import Base from '../components/base';
|
||||
import Chart from '../components/chart';
|
||||
import ItemHeader from '../components/itemHeader';
|
||||
import Loading from '../components/loading';
|
||||
import LoadingChart from '../components/loadingChart';
|
||||
import MetadataFields from '../components/metadataFields';
|
||||
import PodsPanel from '../components/podsPanel';
|
||||
import {defaultSortInfo} from '../components/sorter';
|
||||
import {parseCpu, parseRam, TO_GB, TO_ONE_M_CPU} from '../utils/unitHelpers';
|
||||
import PodStatusChart from '../components/podStatusChart';
|
||||
import Field from '../components/field';
|
||||
import ChartsContainer from '../components/chartsContainer';
|
||||
import NodeCpuChart from '../components/nodeCpuChart';
|
||||
import NodeRamChart from '../components/nodeRamChart';
|
||||
import PodStatusChart from '../components/podStatusChart';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
|
||||
export default class Node extends Base {
|
||||
state = {
|
||||
@@ -25,12 +28,9 @@ export default class Node extends Base {
|
||||
|
||||
this.registerApi({
|
||||
item: api.node.get(name, item => this.setState({item})),
|
||||
pods: api.pod.list(null, pods => this.setState({pods})),
|
||||
metrics: api.metrics.node(name, metrics => this.setState({metrics})),
|
||||
podMetrics: api.metrics.pods(null, (x) => {
|
||||
const podMetrics = _.keyBy(x, 'metadata.name');
|
||||
this.setState({podMetrics});
|
||||
}),
|
||||
pods: api.pod.list(null, pods => this.setState({pods})),
|
||||
podMetrics: api.metrics.pods(null, podMetrics => this.setState({podMetrics})),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -39,15 +39,29 @@ export default class Node extends Base {
|
||||
const {item, pods, metrics, podMetrics, podsSort} = this.state;
|
||||
|
||||
const filteredPods = pods && pods.filter(x => x.spec.nodeName === name);
|
||||
const filteredPodMetrics = getMetrics(filteredPods, podMetrics);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
<ItemHeader title={['Node', name]} />
|
||||
|
||||
<ChartsContainer>
|
||||
<div className='charts_item'>
|
||||
{item ? (
|
||||
<span className='charts_number'>{getUpTime(item)}</span>
|
||||
) : (
|
||||
<LoadingChart />
|
||||
)}
|
||||
<div className='charts_itemLabel'>Days Up</div>
|
||||
</div>
|
||||
<NodeCpuChart items={item && [item]} metrics={metrics && [metrics]} />
|
||||
<NodeRamChart items={item && [item]} metrics={metrics && [metrics]} />
|
||||
</ChartsContainer>
|
||||
|
||||
<ChartsContainer>
|
||||
<PodStatusChart items={filteredPods} />
|
||||
<CpuChart item={item} metrics={metrics} />
|
||||
<RamChart item={item} metrics={metrics} />
|
||||
<PodCpuChart items={filteredPods} metrics={filteredPodMetrics} />
|
||||
<PodRamChart items={filteredPods} metrics={filteredPodMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<div className='contentPanel'>
|
||||
@@ -97,7 +111,7 @@ export default class Node extends Base {
|
||||
<PodsPanel
|
||||
items={filteredPods}
|
||||
sort={podsSort}
|
||||
metrics={podMetrics}
|
||||
metrics={filteredPodMetrics}
|
||||
skipNodeName={true}
|
||||
/>
|
||||
</div>
|
||||
@@ -105,44 +119,12 @@ export default class Node extends Base {
|
||||
}
|
||||
}
|
||||
|
||||
function CpuChart({item, metrics}) {
|
||||
const usedCpu = metrics && parseCpu(metrics.usage.cpu) / TO_ONE_M_CPU;
|
||||
const availableCpu = item && parseCpu(item.status.capacity.cpu) / TO_ONE_M_CPU;
|
||||
function getUpTime({status}) {
|
||||
const ready = status.conditions.find(y => y.type === 'Ready');
|
||||
if (!ready) return 'N/A';
|
||||
|
||||
return (
|
||||
<div className='charts_item'>
|
||||
{item && metrics ? (
|
||||
<Chart
|
||||
used={usedCpu}
|
||||
usedSuffix='m'
|
||||
available={availableCpu}
|
||||
availableSuffix='m'
|
||||
/>
|
||||
) : (
|
||||
<LoadingChart />
|
||||
)}
|
||||
<div className='charts_itemLabel'>Cpu Used</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RamChart({item, metrics}) {
|
||||
const usedRam = metrics && parseRam(metrics.usage.memory) / TO_GB;
|
||||
const availableRam = item && parseRam(item.status.capacity.memory) / TO_GB;
|
||||
|
||||
return (
|
||||
<div className='charts_item'>
|
||||
{item && metrics ? (
|
||||
<Chart
|
||||
used={usedRam}
|
||||
usedSuffix='Gi'
|
||||
available={availableRam}
|
||||
availableSuffix='Gi'
|
||||
/>
|
||||
) : (
|
||||
<LoadingChart />
|
||||
)}
|
||||
<div className='charts_itemLabel'>Ram Used</div>
|
||||
</div>
|
||||
);
|
||||
const last = moment(ready.lastTransitionTime);
|
||||
const diff = moment().diff(last);
|
||||
const hours = moment.duration(diff).asDays();
|
||||
return _.round(hours);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import Base from '../components/base';
|
||||
import ChartsContainer from '../components/chartsContainer';
|
||||
@@ -8,9 +7,9 @@ import NodeStatusChart from '../components/nodeStatusChart';
|
||||
import api from '../services/api';
|
||||
import test from '../utils/filterHelper';
|
||||
import NodesPanel from '../components/nodesPanel';
|
||||
import Chart from '../components/chart';
|
||||
import LoadingChart from '../components/loadingChart';
|
||||
import {parseCpu, parseRam, TO_GB, TO_ONE_CPU} from '../utils/unitHelpers';
|
||||
import NodeCpuChart from '../components/nodeCpuChart';
|
||||
import NodeRamChart from '../components/nodeRamChart';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
|
||||
export default class Nodes extends Base {
|
||||
state = {
|
||||
@@ -34,7 +33,7 @@ export default class Nodes extends Base {
|
||||
return test(filter, x.metadata.name, ...searchableLabels);
|
||||
});
|
||||
|
||||
const filteredMetrics = getNodeMetrics(filtered, metrics);
|
||||
const filteredMetrics = getMetrics(filtered, metrics);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
@@ -46,8 +45,8 @@ export default class Nodes extends Base {
|
||||
|
||||
<ChartsContainer>
|
||||
<NodeStatusChart items={filtered} />
|
||||
<CpuTotalsChart items={filtered} metrics={filteredMetrics} />
|
||||
<RamTotalsChart items={filtered} metrics={filteredMetrics} />
|
||||
<NodeCpuChart items={filtered} metrics={filteredMetrics} />
|
||||
<NodeRamChart items={filtered} metrics={filteredMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<NodesPanel
|
||||
@@ -59,62 +58,3 @@ export default class Nodes extends Base {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function CpuTotalsChart({items, metrics}) {
|
||||
const totals = getNodeCpuTotals(items, metrics);
|
||||
return (
|
||||
<div className='charts_item'>
|
||||
{totals ? (
|
||||
<Chart used={totals.used} available={totals.available} />
|
||||
) : (
|
||||
<LoadingChart />
|
||||
)}
|
||||
<div className='charts_itemLabel'>Cores</div>
|
||||
<div className='charts_itemSubLabel'>Used vs Available</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RamTotalsChart({items, metrics}) {
|
||||
const totals = getNodeRamTotals(items, metrics);
|
||||
return (
|
||||
<div className='charts_item'>
|
||||
{totals ? (
|
||||
<Chart used={totals.used} usedSuffix='Gb' available={totals.available} availableSuffix='Gb' />
|
||||
) : (
|
||||
<LoadingChart />
|
||||
)}
|
||||
<div className='charts_itemLabel'>Ram</div>
|
||||
<div className='charts_itemSubLabel'>Used vs Available</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getNodeMetrics(nodes, metrics) {
|
||||
if (!nodes || !metrics) return null;
|
||||
|
||||
const names = _.map(nodes, x => x.metadata.name);
|
||||
const filteredMetrics = metrics.filter(x => names.includes(x.metadata.name));
|
||||
|
||||
return _.keyBy(filteredMetrics, 'metadata.name');
|
||||
}
|
||||
|
||||
function getNodeCpuTotals(items, metrics) {
|
||||
if (!items || !metrics) return null;
|
||||
|
||||
const metricValues = Object.values(metrics);
|
||||
const used = _.sumBy(metricValues, x => parseCpu(x.usage.cpu)) / TO_ONE_CPU;
|
||||
const available = _.sumBy(items, x => parseCpu(x.status.capacity.cpu)) / TO_ONE_CPU;
|
||||
|
||||
return {used, available};
|
||||
}
|
||||
|
||||
function getNodeRamTotals(items, metrics) {
|
||||
if (!items || !metrics) return null;
|
||||
|
||||
const metricValues = Object.values(metrics);
|
||||
const used = _.sumBy(metricValues, x => parseRam(x.usage.memory)) / TO_GB;
|
||||
const available = _.sumBy(items, x => parseRam(x.status.capacity.memory)) / TO_GB;
|
||||
|
||||
return {used, available};
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ import EventsPanel from '../components/eventsPanel';
|
||||
import ContainersPanel from '../components/containersPanel';
|
||||
import {objectMap} from '../components/listViewHelpers';
|
||||
import {filterByOwner} from '../utils/filterHelper';
|
||||
import getPodMetrics from '../utils/metricsHelpers';
|
||||
import CpuChart from '../components/cpuChart';
|
||||
import RamChart from '../components/ramChart';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import ChartsContainer from '../components/chartsContainer';
|
||||
|
||||
const service = api.pod;
|
||||
@@ -39,7 +39,7 @@ export default class Pod extends Base {
|
||||
|
||||
const errors = getErrors(item);
|
||||
const filteredEvents = filterByOwner(events, item);
|
||||
const filteredMetrics = getPodMetrics(item && [item], metrics && [metrics]);
|
||||
const filteredMetrics = getMetrics(item && [item], metrics && [metrics]);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
@@ -69,8 +69,8 @@ export default class Pod extends Base {
|
||||
{errors && !!errors.length && <Error messages={errors} />}
|
||||
|
||||
<ChartsContainer>
|
||||
<CpuChart items={item && [item]} metrics={filteredMetrics} />
|
||||
<RamChart items={item && [item]} metrics={filteredMetrics} />
|
||||
<PodCpuChart items={item && [item]} metrics={filteredMetrics} />
|
||||
<PodRamChart items={item && [item]} metrics={filteredMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<div className='contentPanel'>
|
||||
|
||||
@@ -3,12 +3,12 @@ import Base from '../components/base';
|
||||
import Filter from '../components/filter';
|
||||
import api from '../services/api';
|
||||
import test from '../utils/filterHelper';
|
||||
import CpuChart from '../components/cpuChart';
|
||||
import RamChart from '../components/ramChart';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import PodsPanel from '../components/podsPanel';
|
||||
import PodStatusChart from '../components/podStatusChart';
|
||||
import {defaultSortInfo} from '../components/sorter';
|
||||
import getPodMetrics from '../utils/metricsHelpers';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
import ChartsContainer from '../components/chartsContainer';
|
||||
|
||||
export default class Pods extends Base {
|
||||
@@ -31,7 +31,7 @@ export default class Pods extends Base {
|
||||
render() {
|
||||
const {items, metrics, namespace, sort, filter} = this.state;
|
||||
const filtered = items && items.filter(x => test(filter, x.metadata.name));
|
||||
const filteredMetrics = getPodMetrics(filtered, metrics);
|
||||
const filteredMetrics = getMetrics(filtered, metrics);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
@@ -44,8 +44,8 @@ export default class Pods extends Base {
|
||||
|
||||
<ChartsContainer>
|
||||
<PodStatusChart items={filtered} />
|
||||
<CpuChart items={filtered} metrics={filteredMetrics} />
|
||||
<RamChart items={filtered} metrics={filteredMetrics} />
|
||||
<PodCpuChart items={filtered} metrics={filteredMetrics} />
|
||||
<PodRamChart items={filtered} metrics={filteredMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<PodsPanel
|
||||
|
||||
@@ -3,9 +3,9 @@ import React from 'react';
|
||||
import api from '../services/api';
|
||||
import Base from '../components/base';
|
||||
import ContainersPanel from '../components/containersPanel';
|
||||
import CpuChart from '../components/cpuChart';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import ReplicasChart from '../components/replicasChart';
|
||||
import RamChart from '../components/ramChart';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import DeleteButton from '../components/deleteButton';
|
||||
import EventsPanel from '../components/eventsPanel';
|
||||
import ItemHeader from '../components/itemHeader';
|
||||
@@ -16,7 +16,7 @@ import PodsPanel from '../components/podsPanel';
|
||||
import SaveButton from '../components/saveButton';
|
||||
import ScaleButton from '../components/scaleButton';
|
||||
import {defaultSortInfo} from '../components/sorter';
|
||||
import getPodMetrics from '../utils/metricsHelpers';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
import {filterByOwner} from '../utils/filterHelper';
|
||||
import ChartsContainer from '../components/chartsContainer';
|
||||
|
||||
@@ -45,7 +45,7 @@ export default class ReplicaSet extends Base {
|
||||
|
||||
const filteredPods = filterByOwner(pods, item);
|
||||
const filteredEvents = filterByOwner(events, item);
|
||||
const filteredMetrics = getPodMetrics(filteredPods, metrics);
|
||||
const filteredMetrics = getMetrics(filteredPods, metrics);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
@@ -70,8 +70,8 @@ export default class ReplicaSet extends Base {
|
||||
|
||||
<ChartsContainer>
|
||||
<ReplicasChart item={item} />
|
||||
<CpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<RamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodCpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodRamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<div className='contentPanel'>
|
||||
|
||||
@@ -9,9 +9,9 @@ import ScaleButton from '../components/scaleButton';
|
||||
import SaveButton from '../components/saveButton';
|
||||
import DeleteButton from '../components/deleteButton';
|
||||
import EventsPanel from '../components/eventsPanel';
|
||||
import RamChart from '../components/ramChart';
|
||||
import CpuChart from '../components/cpuChart';
|
||||
import getPodMetrics from '../utils/metricsHelpers';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
import {filterByOwner} from '../utils/filterHelper';
|
||||
import ContainersPanel from '../components/containersPanel';
|
||||
import {defaultSortInfo} from '../components/sorter';
|
||||
@@ -43,7 +43,7 @@ export default class StatefulSet extends Base {
|
||||
|
||||
const filteredPods = filterByOwner(pods, item);
|
||||
const filteredEvents = filterByOwner(events, item);
|
||||
const filteredMetrics = getPodMetrics(filteredPods, metrics);
|
||||
const filteredMetrics = getMetrics(filteredPods, metrics);
|
||||
|
||||
return (
|
||||
<div id='content'>
|
||||
@@ -68,8 +68,8 @@ export default class StatefulSet extends Base {
|
||||
|
||||
<ChartsContainer>
|
||||
<ReplicasChart item={item} />
|
||||
<CpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<RamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodCpuChart items={filteredPods} metrics={filteredMetrics} />
|
||||
<PodRamChart items={filteredPods} metrics={filteredMetrics} />
|
||||
</ChartsContainer>
|
||||
|
||||
<div className='contentPanel'>
|
||||
|
||||
@@ -145,9 +145,13 @@ function getExpectedCount({spec, status}) {
|
||||
}
|
||||
|
||||
function filterControllers(filter, items) {
|
||||
const results = items.flat();
|
||||
const results = items
|
||||
.flat()
|
||||
.filter(x => !!x);
|
||||
|
||||
if (results.length && items.some(x => !x)) return null;
|
||||
// If there are no results yet but some of the workload types are still
|
||||
// loading, return "null" so we display the "loading" control
|
||||
if (!results.length && items.some(x => !x)) return null;
|
||||
|
||||
return _(results)
|
||||
.flatten()
|
||||
|
||||
Reference in New Issue
Block a user