A lot of charts work

This commit is contained in:
Eric Herbrandson
2019-04-16 20:05:17 -05:00
parent 6d12138a60
commit 8ea4bd32a0
24 changed files with 248 additions and 187 deletions
+2 -1
View File
@@ -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);
}
}
+1 -1
View File
@@ -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>
+5 -2
View File
@@ -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>
);
+27
View File
@@ -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;
}
+31
View File
@@ -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};
}
+30
View File
@@ -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));
+1 -1
View File
@@ -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;
+4
View File
@@ -53,4 +53,8 @@ td {
.wrapped > tbody > tr > td {
padding: 0.25rem;
}
.wrapped .wrapped_name {
font-weight: bold;
}
}
+3 -3
View File
@@ -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');
+6 -6
View File
@@ -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'>
+6 -6
View File
@@ -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'>
+17 -8
View File
@@ -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);
}
+6 -6
View File
@@ -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'>
+6 -6
View File
@@ -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'>
+31 -1
View File
@@ -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
View File
@@ -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);
}
+6 -66
View File
@@ -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};
}
+6 -6
View File
@@ -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'>
+6 -6
View File
@@ -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
+6 -6
View File
@@ -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'>
+6 -6
View File
@@ -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'>
+6 -2
View File
@@ -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()