Skip to content

Commit

Permalink
Update Rotue section in Knative revision sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
karthik committed Sep 30, 2020
1 parent ce1e950 commit d54f1c3
Show file tree
Hide file tree
Showing 9 changed files with 272 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import * as React from 'react';
import { K8sResourceKind } from '@console/internal/module/k8s';
import { RoutesOverviewListItem } from '../../types';
import KSRoutesOverviewListItem from './KSRoutesOverviewListItem';
import KSRouteSplitListItem from './KSRouteSplitListItem';

type KSRoutesProps = {
route: K8sResourceKind;
routeLinks: RoutesOverviewListItem[];
};

const KSRoutes: React.FC<KSRoutesProps> = ({ route, routeLinks }) => (
const KSRoutes: React.FC<KSRoutesProps> = ({ route }) => (
<>
<KSRoutesOverviewListItem ksroute={route} />
{routeLinks.map((splitRoute) => (
<KSRouteSplitListItem key={splitRoute.uid} route={splitRoute} />
))}
</>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { K8sResourceKind, referenceForModel } from '@console/internal/module/k8s
import { ResourceLink } from '@console/internal/components/utils';
import { Traffic } from '../../types';
import { RevisionModel } from '../../models';
import RoutesUrlLink from './RoutesUrlLink';

import './RevisionsOverviewListItem.scss';

export type RevisionsOverviewListItemProps = {
Expand All @@ -23,27 +25,38 @@ const RevisionsOverviewListItem: React.FC<RevisionsOverviewListItemProps> = ({
const {
status: { traffic },
} = service;
const getTraffic = (revName: string) => {
const getTrafficByRevision = (revName: string) => {
if (!traffic || !traffic.length) {
return null;
return {};
}
const trafficPercent = traffic
.filter((t: Traffic) => t.revisionName === revName)
.map((tr: Traffic) => tr.percent)
.reduce((a: number, b: number) => a + b, 0);

return trafficPercent ? `${trafficPercent}%` : null;
.reduce(
(acc, tr: Traffic) => {
acc.percent += tr.percent;
if (tr.url) {
acc.urls.push(tr.url);
}
return acc;
},
{ urls: [], percent: 0 },
);
return {
...trafficPercent,
percent: trafficPercent.percent ? `${trafficPercent.percent}%` : null,
};
};
const deploymentData = _.get(revision, 'resources.current.obj.metadata.ownerReferences[0]', {});
const current = _.get(revision, 'resources.current', null);
const availableReplicas = _.get(revision, 'resources.current.obj.status.availableReplicas', '0');
const { urls = [], percent: trafficPercent } = getTrafficByRevision(name);
return (
<li className="list-group-item">
<div className="row">
<div className="col-sm-8 col-xs-9">
<ResourceLink kind={referenceForModel(RevisionModel)} name={name} namespace={namespace} />
</div>
<span className="col-sm-4 col-xs-3 text-right">{getTraffic(name)}</span>
<span className="col-sm-4 col-xs-3 text-right">{trafficPercent}</span>
</div>
{deploymentData.name && (
<div className="odc-revision-deployment-list">
Expand All @@ -70,6 +83,13 @@ const RevisionsOverviewListItem: React.FC<RevisionsOverviewListItemProps> = ({
</div>
</div>
</div>
{urls.length > 0 && (
<div className="row">
<div className="col-sm-12">
<RoutesUrlLink urls={urls} />
</div>
</div>
)}
</div>
)}
</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import * as React from 'react';
import * as _ from 'lodash';
import { K8sResourceKind } from '@console/internal/module/k8s';
import { SidebarSectionHeading } from '@console/internal/components/utils';
import { getKnativeRoutesLinks } from '../../utils/resource-overview-utils';
import { getKnativeRoutesLinks, groupTrafficByRevision } from '../../utils/resource-overview-utils';
import RoutesOverviewListItem from './RoutesOverviewListItem';
import { RoutesOverviewListItem as routeLinkProps } from '../../types';
import { ServiceModel } from '../../models';
import KSRoutes from './KSRoutes';

export type RoutesOverviewListProps = {
Expand All @@ -19,11 +21,25 @@ const RoutesOverviewList: React.FC<RoutesOverviewListProps> = ({ ksroutes, resou
) : (
<ul className="list-group">
{_.map(ksroutes, (route) => {
const routeLinks = getKnativeRoutesLinks(route, resource);
if (routeLinks.length === 1) {
return <RoutesOverviewListItem key={route.metadata.uid} routeLink={routeLinks[0]} />;
const routeLinks: routeLinkProps[] = getKnativeRoutesLinks(route, resource);
if (resource.kind === ServiceModel.kind) {
return <KSRoutes key={route.metadata.uid} route={route} />;
}
return <KSRoutes key={route.metadata.uid} route={route} routeLinks={routeLinks} />;
if (routeLinks.length > 0) {
const { urls: uniqueRoutes, percent: totalPercentage } = groupTrafficByRevision(
route,
resource,
);
return (
<RoutesOverviewListItem
key={route.metadata.uid}
uniqueRoutes={uniqueRoutes}
totalPercent={totalPercentage}
routeLink={routeLinks[0]}
/>
);
}
return null;
})}
</ul>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import * as React from 'react';
import { referenceForModel } from '@console/internal/module/k8s';
import { ResourceLink, ExternalLink } from '@console/internal/components/utils';
import { ResourceLink } from '@console/internal/components/utils';
import { RouteModel } from '../../models';
import { RoutesOverviewListItem } from '../../types';
import RoutesUrlLink from './RoutesUrlLink';

export type RoutesOverviewListItemProps = {
routeLink: RoutesOverviewListItem;
uniqueRoutes?: string[];
totalPercent?: string;
};

const RoutesOverviewListItem: React.FC<RoutesOverviewListItemProps> = ({
routeLink: { url, name, namespace, percent },
totalPercent,
uniqueRoutes,
}) => (
<li className="list-group-item">
<div className="row">
<div className="col-xs-10">
<ResourceLink kind={referenceForModel(RouteModel)} name={name} namespace={namespace} />
{url.length > 0 && (
<>
<span className="text-muted">Location: </span>
<ExternalLink href={url} additionalClassName="co-external-link--block" text={url} />
</>
)}
{url.length > 0 && <RoutesUrlLink urls={[url]} title="Location" />}
{uniqueRoutes?.length > 0 && <RoutesUrlLink urls={uniqueRoutes} title="Unique Route" />}
</div>
{percent.length > 0 && <span className="col-xs-2 text-right">{percent}</span>}
{percent.length > 0 && <span className="col-xs-2 text-right">{totalPercent || percent}</span>}
</div>
</li>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react';
import { ExternalLink } from '@console/internal/components/utils';

export type RoutesUrlLinkProps = {
urls: string[];
title?: string;
};

const RoutesUrlLink: React.FC<RoutesUrlLinkProps> = ({ urls = [], title }) =>
urls.length > 0 && (
<>
{title && <span className="text-muted">{title}: </span>}
{urls.length > 0 &&
urls.map((url) => (
<ExternalLink href={url} additionalClassName="co-external-link--block" text={url} />
))}
</>
);

export default RoutesUrlLink;
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as utils from '@console/internal/components/utils';
import { MockKnativeResources } from '../../../topology/__tests__/topology-knative-test-data';
import RoutesOverviewList from '../RoutesOverviewList';
import RoutesOverviewListItem from '../RoutesOverviewListItem';
import { K8sResourceKind } from '@console/internal/module/k8s/types';

type RoutesOverviewListProps = React.ComponentProps<typeof RoutesOverviewList>;

Expand All @@ -30,4 +31,63 @@ describe('RoutesOverviewList', () => {
it('should render RoutesOverviewListItem', () => {
expect(wrapper.find(RoutesOverviewListItem)).toHaveLength(1);
});

it('should render RoutesOverviewListItem without unique routes', () => {
const routesOverviewListItemProps = wrapper.find(RoutesOverviewListItem).props();
expect(routesOverviewListItemProps.uniqueRoutes).toHaveLength(0);
});

it('should render RoutesOverviewListItem with unique routes', () => {
const mockRouteData: K8sResourceKind = {
...MockKnativeResources.ksroutes.data[0],
status: {
...MockKnativeResources.ksroutes.data[0].status,
traffic: [
{
...MockKnativeResources.ksroutes.data[0].status.traffic[0],
tag: 'tag1',
url: 'http://tag1.test.com',
},
],
},
};

wrapper.setProps({ ksroutes: [mockRouteData] });
const routesOverviewListItemProps = wrapper.find(RoutesOverviewListItem).props();
expect(routesOverviewListItemProps.uniqueRoutes).toHaveLength(1);
expect(routesOverviewListItemProps.uniqueRoutes).toEqual(['http://tag1.test.com']);
});

it('should handle multiple traffic splitting for the same revision', () => {
const mockRouteData: K8sResourceKind = {
...MockKnativeResources.ksroutes.data[0],
status: {
...MockKnativeResources.ksroutes.data[0].status,
traffic: [
{
...MockKnativeResources.ksroutes.data[0].status.traffic[0],
tag: 'tag1',
url: 'http://tag1.test.com',
percent: 20,
},
{
...MockKnativeResources.ksroutes.data[0].status.traffic[0],
tag: 'tag2',
url: 'http://tag2.test.com',
percent: 30,
},
],
},
};

wrapper.setProps({ ksroutes: [mockRouteData] });

const routesOverviewListItemProps = wrapper.find(RoutesOverviewListItem).props();
expect(routesOverviewListItemProps.uniqueRoutes).toHaveLength(2);
expect(routesOverviewListItemProps.uniqueRoutes).toEqual([
'http://tag1.test.com',
'http://tag2.test.com',
]);
expect(routesOverviewListItemProps.totalPercent).toEqual('50%');
});
});
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import * as React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import { referenceForModel } from '@console/internal/module/k8s';
import { ResourceLink, ExternalLink } from '@console/internal/components/utils';
import { ResourceLink } from '@console/internal/components/utils';
import { MockKnativeResources } from '../../../topology/__tests__/topology-knative-test-data';
import { RouteModel } from '../../../models';
import RoutesOverviewListItem from '../RoutesOverviewListItem';
import { getKnativeRoutesLinks } from '../../../utils/resource-overview-utils';
import RoutesUrlLink, { RoutesUrlLinkProps } from '../RoutesUrlLink';

type RoutesOverviewListItemProps = React.ComponentProps<typeof RoutesOverviewListItem>;

describe('RoutesOverviewListItem', () => {
let wrapper: ShallowWrapper<RoutesOverviewListItemProps>;

const getRouteUrlLinkProps = (pos: number): RoutesUrlLinkProps =>
wrapper
.find(RoutesUrlLink)
.at(pos)
.props();

beforeEach(() => {
const [routeLink] = getKnativeRoutesLinks(
MockKnativeResources.ksroutes.data[0],
Expand Down Expand Up @@ -40,16 +48,16 @@ describe('RoutesOverviewListItem', () => {
});

it('should have route ExternalLink with proper href', () => {
expect(wrapper.find(ExternalLink)).toHaveLength(1);
expect(wrapper.find(RoutesUrlLink)).toHaveLength(1);
expect(
wrapper
.find(ExternalLink)
.find(RoutesUrlLink)
.at(0)
.props().href,
).toEqual('http://overlayimage.knativeapps.apps.bpetersen-june-23.devcluster.openshift.com');
.props().urls,
).toEqual(['http://overlayimage.knativeapps.apps.bpetersen-june-23.devcluster.openshift.com']);
});

it('should have route of specific revision as ExternalLink with proper url', () => {
it('should have route of specific revision as RoutesUrlLink with tag url and base url', () => {
const mockRouteData = {
...MockKnativeResources.ksroutes.data[0],
status: {
Expand All @@ -68,17 +76,46 @@ describe('RoutesOverviewListItem', () => {
mockRouteData,
MockKnativeResources.revisions.data[0],
);
wrapper.setProps({ routeLink });
expect(wrapper.find(ExternalLink)).toHaveLength(1);
expect(
wrapper
.find(ExternalLink)
.at(0)
.props().href,
).toEqual(

wrapper.setProps({ routeLink, uniqueRoutes: [mockRouteData.status.traffic[0].url] });
const { urls: baseUrl, title: baseTitle }: RoutesUrlLinkProps = getRouteUrlLinkProps(0);
const { urls, title }: RoutesUrlLinkProps = getRouteUrlLinkProps(1);

expect(wrapper.find(RoutesUrlLink)).toHaveLength(2);
expect(baseTitle).toEqual('Location');
expect(baseUrl).toEqual([
'http://overlayimage.knativeapps.apps.bpetersen-june-23.devcluster.openshift.com',
]);
expect(title).toEqual('Unique Route');
expect(urls).toEqual([
'http://abc-overlayimage.knativeapps.apps.bpetersen-june-23.devcluster.openshift.com',
]);
});

it('should have route of specific revision as RoutesUrlLink with multiple tag urls and total percent', () => {
const [routeLink] = getKnativeRoutesLinks(
MockKnativeResources.ksroutes.data[0],
MockKnativeResources.revisions.data[0],
);

wrapper.setProps({
routeLink,
uniqueRoutes: ['https://tag1.test.com', 'https://tag2.test.com'],
totalPercent: '50%',
});
expect(wrapper.find(RoutesUrlLink)).toHaveLength(2);

const { urls: baseUrl, title: baseTitle }: RoutesUrlLinkProps = getRouteUrlLinkProps(0);
const { urls, title }: RoutesUrlLinkProps = getRouteUrlLinkProps(1);
expect(baseTitle).toEqual('Location');
expect(baseUrl).toEqual([
'http://overlayimage.knativeapps.apps.bpetersen-june-23.devcluster.openshift.com',
]);
expect(title).toEqual('Unique Route');
expect(urls).toEqual(['https://tag1.test.com', 'https://tag2.test.com']);
expect(wrapper.find('span.text-right').text()).toBe('50%');
});

it('should not show the route url and traffic percentage section, if there are not available', () => {
const mockRouteData = {
...MockKnativeResources.ksroutes.data[0],
Expand All @@ -100,7 +137,7 @@ describe('RoutesOverviewListItem', () => {
);
wrapper.setProps({ routeLink });
expect(wrapper.find(ResourceLink)).toHaveLength(1);
expect(wrapper.find(ExternalLink)).toHaveLength(0);
expect(wrapper.find(RoutesUrlLink)).toHaveLength(0);
expect(wrapper.find('span.text-right')).toHaveLength(0);
});
});

0 comments on commit d54f1c3

Please sign in to comment.