Skip to content

Commit

Permalink
Add orphan pods to project overview
Browse files Browse the repository at this point in the history
  • Loading branch information
TheRealJon committed Jan 11, 2019
1 parent 2644b08 commit aadb62d
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 103 deletions.
115 changes: 83 additions & 32 deletions frontend/public/components/overview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
DaemonSetModel,
DeploymentModel,
DeploymentConfigModel,
PodModel,
ProjectModel,
ReplicationControllerModel,
ReplicaSetModel,
Expand All @@ -40,11 +41,13 @@ import {
Firehose,
StatusBox,
EmptyBox,
resourceObjPath,
} from '../utils';

import { overviewMenuActions, OverviewNamespaceDashboard } from './namespace-overview';
import { ProjectOverview } from './project-overview';
import { ResourceOverviewPage } from './resource-overview-page';
import { PodStatus } from '../pod';

enum View {
Resources = 'resources',
Expand Down Expand Up @@ -280,6 +283,12 @@ const sortBuilds = (builds: K8sResourceKind[]): K8sResourceKind[] => {
const reservedNSPrefixes = ['openshift-', 'kube-', 'kubernetes-'];
const isReservedNamespace = (ns: string) => ns === 'default' || ns === 'openshift' || reservedNSPrefixes.some(prefix => _.startsWith(ns, prefix));

const OverviewItemReadiness: React.SFC<OverviewItemReadinessProps> = ({desired = 0, href, ready = 0}) => (
<Link to={href}>
{ready} of {desired} pods
</Link>
);

const overviewEmptyStateToProps = ({UI}) => ({
activeNamespace: UI.get('activeNamespace'),
resources: UI.getIn(['overview', 'resources']),
Expand Down Expand Up @@ -564,7 +573,7 @@ class OverviewMainContent_ extends React.Component<OverviewMainContentProps, Ove

getServicesForResource(resource: K8sResourceKind): K8sResourceKind[] {
const {services} = this.props;
const template = _.get(resource, 'spec.template');
const template = resource.kind === 'Pod' ? resource : _.get(resource, 'spec.template');
return _.filter(services.data, service => {
const selector = new LabelSelector(_.get(service, 'spec.selector', {}));
return selector.matches(template);
Expand Down Expand Up @@ -679,19 +688,19 @@ class OverviewMainContent_ extends React.Component<OverviewMainContentProps, Ove
...ds,
kind: DaemonSetModel.kind,
};
const readiness = {
desired: ds.status.desiredNumberScheduled || 0,
ready: ds.status.currentNumberScheduled || 0,
};

const status = <OverviewItemReadiness
desired={ds.status.desiredNumberScheduled}
href={`${resourceObjPath(obj, obj.kind)}/pods`}
ready={ds.status.currentNumberScheduled}
/>;
return {
alerts,
buildConfigs,
obj,
pods,
readiness,
routes,
services,
status,
};
});
}
Expand All @@ -710,20 +719,24 @@ class OverviewMainContent_ extends React.Component<OverviewMainContentProps, Ove
...d,
kind: DeploymentModel.kind,
};
const readiness = {
desired: d.spec.replicas || 0,
ready: d.status.replicas || 0,
};
// TODO: Show pod status for previous and next revisions.
const status = isRollingOut
? <span className="text-muted">Rollout in progress...</span>
: <OverviewItemReadiness
desired={d.spec.replicas}
href={`${resourceObjPath(current.obj, _.get(current, 'obj.kind'))}/pods`}
ready={d.status.replicas}
/>;

return {
buildConfigs,
current,
isRollingOut,
obj,
previous,
readiness,
routes,
services,
status,
};
});
}
Expand All @@ -742,20 +755,24 @@ class OverviewMainContent_ extends React.Component<OverviewMainContentProps, Ove
...dc,
kind: DeploymentConfigModel.kind,
};
const readiness = {
desired: dc.spec.replicas || 0,
ready: dc.status.replicas || 0,
};

// TODO: Show pod status for previous and next revisions.
const status = isRollingOut
? <span className="text-muted">Rollout in progress...</span>
: <OverviewItemReadiness
desired={dc.spec.replicas}
href={`${resourceObjPath(current.obj, _.get(current, 'obj.kind'))}/pods`}
ready={dc.status.replicas}
/>;
return {
buildConfigs,
current,
isRollingOut,
obj,
previous,
readiness,
routes,
services,
status,
};
});
}
Expand All @@ -764,30 +781,62 @@ class OverviewMainContent_ extends React.Component<OverviewMainContentProps, Ove
const {statefulSets} = this.props;
return _.map(statefulSets.data, (ss) => {
const buildConfigs = this.getBuildConfigsForResource(ss);
const obj = {
...ss,
kind: StatefulSetModel.kind,
};
const readiness = {
desired: ss.spec.replicas || 0,
ready: ss.status.replicas || 0,
};
const pods = this.getPodsForResource(ss);
const alerts = combinePodAlerts(pods);
const services = this.getServicesForResource(ss);
const routes = this.getRoutesForServices(services);
const obj = {
...ss,
kind: StatefulSetModel.kind,
};
const status = <OverviewItemReadiness
desired={ss.spec.replicas}
href={`${resourceObjPath(obj, obj.kind)}/pods`}
ready={ss.status.replicas}
/>;

return {
alerts,
buildConfigs,
obj,
pods,
readiness,
routes,
services,
status,
};
});
}

createPodItems(): OverviewItem[] {
const {pods} = this.props;
return _.reduce(pods.data, (acc, pod) => {
const owners = _.get(pod, 'metadata.ownerReferences');
const phase = _.get(pod, 'status.phase');
if (!_.isEmpty(owners) || ['Succeeded', 'Failed'].includes(phase)) {
return acc;
}

const obj = {
...pod,
kind: PodModel.kind,
};
const alerts = getPodAlerts(pod);
const services = this.getServicesForResource(obj);
const routes = this.getRoutesForServices(services);
const status = <PodStatus pod={pod} />;
return [
...acc,
{
alerts,
obj,
routes,
services,
status,
},
];
}, []);
}

createOverviewData(): void {
const {loaded, updateResources} = this.props;

Expand All @@ -800,6 +849,7 @@ class OverviewMainContent_ extends React.Component<OverviewMainContentProps, Ove
...this.createDeploymentItems(),
...this.createDeploymentConfigItems(),
...this.createStatefulSetItems(),
...this.createPodItems(),
];

updateResources(items);
Expand Down Expand Up @@ -1031,11 +1081,6 @@ export type PodControllerOverviewItem = {
pods: K8sResourceKind[];
};

type OverviewItemReadiness = {
desired: string | number;
ready: string | number;
};

export type BuildConfigOverviewItem = K8sResourceKind & {
builds: K8sResourceKind[];
};
Expand All @@ -1048,9 +1093,9 @@ export type OverviewItem = {
obj: K8sResourceKind;
pods?: K8sResourceKind[];
previous?: PodControllerOverviewItem;
readiness: OverviewItemReadiness;
routes: K8sResourceKind[];
services: K8sResourceKind[];
status?: React.ReactNode;
};

export type OverviewGroup = {
Expand All @@ -1067,6 +1112,12 @@ export type OverviewMetrics = {
memory?: MetricValuesByPod;
};

type OverviewItemReadinessProps = {
desired: number;
href: string;
ready: number;
};

type OverviewHeadingPropsFromState = {
selectedView: View;
};
Expand Down
53 changes: 53 additions & 0 deletions frontend/public/components/overview/pod-overview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* eslint-disable no-unused-vars, no-undef */
import * as React from 'react';
import { OverviewItem } from '.';
import { PodResourceSummary, PodDetailsList, menuActions } from '../pod';
import { PodModel } from '../../models';
import { ResourceOverviewDetails } from './resource-overview-details';
import { NetworkingOverview } from './networking-overview';

const PodOverviewDetails: React.SFC<PodOverviewDetailsProps> = ({item:{obj: pod}}) => {
return <div className="overview__sidebar-pane-body resource-overview__body">
<div className="resource-overview__summary">
<PodResourceSummary pod={pod} />
</div>
<div className="resource-overview__details">
<PodDetailsList pod={pod} />
</div>
</div>;
};

const PodResourcesTab: React.SFC<PodResourcesTabProps> = ({item: {routes , services}}) => <div className="overview__sidebar-pane-body">
<NetworkingOverview services={services} routes={routes} />
</div>;

const tabs = [
{
name: 'Overview',
component: PodOverviewDetails,
},
{
name: 'Resources',
component: PodResourcesTab,
},
];

export const PodOverviewPage: React.SFC<PodOverviewPageProps> = ({item}) =>
<ResourceOverviewDetails
item={item}
kindObj={PodModel}
menuActions={menuActions}
tabs={tabs}
/>;

type PodOverviewDetailsProps = {
item: OverviewItem;
};

type PodResourcesTabProps = {
item: OverviewItem;
};

type PodOverviewPageProps = {
item: OverviewItem;
};
34 changes: 13 additions & 21 deletions frontend/public/components/overview/project-overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,24 @@ const MetricsTooltip: React.SFC<MetricsTooltipProps> = ({metricLabel, byPod, chi
return <Tooltip content={content} styles={overviewTooltipStyles} disableOnMobile>{children}</Tooltip>;
};


const Metrics: React.SFC<MetricsProps> = ({metrics, item}) => {
const getPods = () => {
if (item.obj.kind === 'Pod') {
return [item.obj];
}
return item.current ? item.current.pods : item.pods;
};

if (_.isEmpty(metrics)) {
return null;
}

const pods = item.current ? item.current.pods : item.pods;
let totalBytes = 0;
let totalCores = 0;
const memoryByPod = [];
const cpuByPod = [];
_.each(pods, ({ metadata: { name } }: K8sResourceKind) => {
_.each(getPods(), ({ metadata: { name } }: K8sResourceKind) => {
const bytes = _.get(metrics, ['memory', name]);
if (_.isFinite(bytes)) {
totalBytes += bytes;
Expand Down Expand Up @@ -137,25 +144,10 @@ const Metrics: React.SFC<MetricsProps> = ({metrics, item}) => {
};

const Status: React.SFC<StatusProps> = ({item}) => {
const {isRollingOut, readiness, obj, current} = item;
if (isRollingOut) {
// TODO: Show pod status for previous and next revisions.
return <div className="project-overview__detail project-overview__detail--status text-muted">
Rollout in progress...
</div>;
}

if (readiness) {
const podLink = current ? `${resourceObjPath(current.obj, _.get(current, 'obj.kind'))}/pods`
: `${resourceObjPath(obj, obj.kind)}/pods`;
return <div className="project-overview__detail project-overview__detail--status">
<Link to={podLink}>
{readiness.ready} of {readiness.desired} pods
</Link>
</div>;
}

return null;
const {status} = item;
return status ? <div className="project-overview__detail project-overview__detail--status">
{status}
</div> : null;
};

const iconClassBySeverity = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-unused-vars, no-undef */
import * as React from 'react';

import { connectToModel } from '../../kinds';
Expand Down Expand Up @@ -45,8 +46,6 @@ export const ResourceOverviewPage = connectToModel(({kindObj, item}) => {
return <AsyncComponent loader={loader} kindObj={kindObj} item={item} />;
});

/* eslint-disable no-unused-vars, no-undef */
type OverviewDetailsResourcesTabProps = {
item: OverviewItem;
};
/* eslint-enable no-unused-vars, no-undef */
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import {
DeploymentModel,
DeploymentConfigModel,
StatefulSetModel,
PodModel,
} from '../../models';

export const resourceOverviewPages = ImmutableMap<GroupVersionKind | string, () => Promise<React.ComponentType<any>>>()
.set(referenceForModel(DaemonSetModel), () => import('./daemon-set-overview' /* webpackChunkNmae: "daemon-set"*/).then(m => m.DaemonSetOverview))
.set(referenceForModel(DeploymentModel), () => import('./deployment-overview' /* webpackChunkNmae: "deployment"*/).then(m => m.DeploymentOverviewPage))
.set(referenceForModel(DeploymentConfigModel), () => import('./deployment-config-overview' /* webpackChunkNmae: "deployment-config"*/).then(m => m.DeploymentConfigOverviewPage))
.set(referenceForModel(PodModel), () => import('./pod-overview' /* webpackChunkNmae: "pod"*/).then(m => m.PodOverviewPage))
.set(referenceForModel(StatefulSetModel), () => import('./stateful-set-overview' /* webpackChunkNmae: "stateful-set"*/).then(m => m.StatefulSetOverview));
Loading

0 comments on commit aadb62d

Please sign in to comment.