mirror of https://github.com/linkerd/linkerd2.git
fix inconsistent deployment count on servicemesh page (#69)
* fix inconsistent deployment count on servicemesh page. * tests added for deploy count messaging on servicemesh page * refactored code for Call To Action component to use 'instructions' in util * refactored correlating css
This commit is contained in:
parent
683b5c0dd6
commit
3591936de3
|
@ -4,24 +4,15 @@
|
|||
.call-to-action {
|
||||
padding: 16px 0;
|
||||
|
||||
& .action {
|
||||
font-size: 14px;
|
||||
font-weight: var(--font-weight-bold);
|
||||
padding: 8px 0;
|
||||
|
||||
& code {
|
||||
background-color: rgba(47, 128, 237, 1);
|
||||
color: white;
|
||||
font-size: .9rem;
|
||||
letter-spacing: 0px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
& code {
|
||||
background-color: rgba(47, 128, 237, 1);
|
||||
color: white;
|
||||
font-size: .9rem;
|
||||
letter-spacing: 0px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
& .summary {
|
||||
color: #27AE60;
|
||||
|
||||
|
|
|
@ -15,12 +15,6 @@
|
|||
width: 131px;
|
||||
}
|
||||
|
||||
.instructions {
|
||||
font-size: 14px;
|
||||
font-weight: var(--font-weight-bold);
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.incomplete-mesh-message, .complete-mesh-message {
|
||||
background-color: var(--messageblue);
|
||||
color: white;
|
||||
|
|
|
@ -137,6 +137,12 @@ tr th.numeric, .numeric {
|
|||
color: var(--subheader-grey);
|
||||
}
|
||||
|
||||
.action {
|
||||
font-size: 14px;
|
||||
font-weight: var(--font-weight-bold);
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
/* fancy borders */
|
||||
.border-container {
|
||||
padding: var(--base-width);
|
||||
|
@ -158,4 +164,4 @@ tr th.numeric, .numeric {
|
|||
}
|
||||
.border-container.border-neutral {
|
||||
background-image: url(./../img/grey_check.png);
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import { instructions } from './util/Utils.js';
|
||||
import React from 'react';
|
||||
import { Col, Row } from 'antd';
|
||||
import './../../css/cta.css';
|
||||
|
@ -39,8 +40,7 @@ export default class CallToAction extends React.Component {
|
|||
</Row>
|
||||
</div>
|
||||
|
||||
<div className="action">Next, add one or more deployments to the deployment.yml file</div>
|
||||
<div className="action">Then run <code>conduit inject deployment.yml | kubectl apply -f -</code> to add deploys to the service mesh</div>
|
||||
{instructions}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@ import ConduitSpinner from "./ConduitSpinner.jsx";
|
|||
import DeploymentSummary from './DeploymentSummary.jsx';
|
||||
import Metric from './Metric.jsx';
|
||||
import React from 'react';
|
||||
import { rowGutter } from './util/Utils.js';
|
||||
import StatusTable from './StatusTable.jsx';
|
||||
import { Col, Row, Table } from 'antd';
|
||||
import { instructions, rowGutter } from './util/Utils.js';
|
||||
import { processRollupMetrics, processTimeseriesMetrics } from './util/MetricUtils.js';
|
||||
import './../../css/service-mesh.css';
|
||||
import 'whatwg-fetch';
|
||||
|
@ -86,7 +86,7 @@ export default class ServiceMesh extends React.Component {
|
|||
let timeseriesRequest = fetch(timeseriesPath).then(r => r.json());
|
||||
let podsRequest = fetch(podsPath).then(r => r.json());
|
||||
|
||||
Promise.all([rollupRequest, timeseriesRequest, podsRequest])
|
||||
this.serverPromise = Promise.all([rollupRequest, timeseriesRequest, podsRequest])
|
||||
.then(([metrics, ts, pods]) => {
|
||||
let m = processRollupMetrics(metrics.metrics, "component");
|
||||
let tsByComponent = processTimeseriesMetrics(ts.metrics, "component");
|
||||
|
@ -108,13 +108,13 @@ export default class ServiceMesh extends React.Component {
|
|||
}
|
||||
|
||||
addedDeploymentCount() {
|
||||
return _.size(_.find(this.state.deploys, d => {
|
||||
return _.size(_.filter(this.state.deploys, d => {
|
||||
return _.every(d.pods, ["value", "good"]);
|
||||
}));
|
||||
}
|
||||
|
||||
unaddedDeploymentCount() {
|
||||
return _.size(this.state.deploys) - this.addedDeploymentCount();
|
||||
return this.deployCount() - this.addedDeploymentCount();
|
||||
}
|
||||
|
||||
proxyCount() {
|
||||
|
@ -127,6 +127,10 @@ export default class ServiceMesh extends React.Component {
|
|||
return _.size(this.state.components);
|
||||
}
|
||||
|
||||
deployCount() {
|
||||
return _.size(this.state.deploys);
|
||||
}
|
||||
|
||||
getServiceMeshDetails() {
|
||||
return [
|
||||
{ key: 1, name: "Conduit version", value: this.props.releaseVersion },
|
||||
|
@ -218,7 +222,7 @@ export default class ServiceMesh extends React.Component {
|
|||
<div className="clearfix header-with-metric">
|
||||
<div className="subsection-header">Data plane</div>
|
||||
<Metric title="Proxies" value={this.proxyCount()} className="metric-large" />
|
||||
<Metric title="Deployments" value={_.size(this.state.deploys)} className="metric-large" />
|
||||
<Metric title="Deployments" value={this.deployCount()} className="metric-large" />
|
||||
</div>
|
||||
|
||||
<StatusTable
|
||||
|
@ -249,26 +253,34 @@ export default class ServiceMesh extends React.Component {
|
|||
}
|
||||
|
||||
renderAddDeploymentsMessage() {
|
||||
return (
|
||||
<div className="mesh-message">
|
||||
{this.unaddedDeploymentCount() === 0 ?
|
||||
if (this.deployCount() === 0) {
|
||||
return (
|
||||
<div className="incomplete-mesh-message">
|
||||
No deployments detected. {instructions}
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
switch (this.unaddedDeploymentCount()) {
|
||||
case 0:
|
||||
return (
|
||||
<div className="complete-mesh-message">
|
||||
All deployments have been added to the service mesh.
|
||||
</div>
|
||||
: this.unaddedDeploymentCount() === 1 ?
|
||||
<div className="incomplete-mesh-message">
|
||||
1 deployment has not been added to the service mesh.
|
||||
<div className="instructions">Add the remaining deployment to the deployment.yml file</div>
|
||||
<div className="instructions">Then run <code>conduit inject deployment.yml | kubectl apply -f - </code> to add the deployment to the service mesh</div>
|
||||
</div>
|
||||
: <div className="incomplete-mesh-message">
|
||||
{this.unaddedDeploymentCount()} deployments have not been added to the service mesh.
|
||||
<div className="instructions">Next, add one or more deployments to the deployment.yml file</div>
|
||||
<div className="instructions">Then run <code>conduit inject deployment.yml | kubectl apply -f -</code> to add deploys to the service mesh</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
);
|
||||
case 1:
|
||||
return (
|
||||
<div className="incomplete-mesh-message">
|
||||
1 deployment has not been added to the service mesh. {instructions}
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<div className="incomplete-mesh-message">
|
||||
{this.unaddedDeploymentCount()} deployments have not been added to the service mesh. {instructions}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderControlPlane() {
|
||||
|
@ -291,7 +303,7 @@ export default class ServiceMesh extends React.Component {
|
|||
|
||||
renderOverview() {
|
||||
if (this.proxyCount() === 0) {
|
||||
return <CallToAction numDeployments={_.size(this.state.metrics)} />;
|
||||
return <CallToAction numDeployments={this.deployCount()} />;
|
||||
} else {
|
||||
return this.renderControllerHealth();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import * as d3 from 'd3';
|
||||
|
||||
/*
|
||||
|
@ -74,3 +75,11 @@ export const toClassName = name => {
|
|||
if (!name) return "";
|
||||
return _.lowerCase(name).replace(/[^a-zA-Z0-9]/g, "_");
|
||||
};
|
||||
|
||||
/*
|
||||
* Instructions for adding deployments to service mesh
|
||||
*/
|
||||
export const instructions = (
|
||||
<div className="action">Add one or more deployments to the deployment.yml file <br /><br />
|
||||
Then run <code>conduit inject deployment.yml | kubectl apply -f - </code> to add deploys to the service mesh</div>
|
||||
);
|
||||
|
|
|
@ -52,4 +52,4 @@
|
|||
"style-loader": "^0.18.2",
|
||||
"url-loader": "^0.6.2"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
import _ from 'lodash';
|
||||
import { expect } from 'chai';
|
||||
import { mount } from 'enzyme';
|
||||
import podFixtures from './fixtures/pods.json';
|
||||
import { routerWrap } from './testHelpers.jsx';
|
||||
import ServiceMesh from '../js/components/ServiceMesh.jsx';
|
||||
import sinon from 'sinon';
|
||||
import sinonStubPromise from 'sinon-stub-promise';
|
||||
|
||||
sinonStubPromise(sinon);
|
||||
|
||||
describe('ServiceMesh', () => {
|
||||
let component, fetchStub;
|
||||
|
||||
function withPromise(fn) {
|
||||
return component.find("ServiceMesh").get(0).serverPromise.then(fn);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
fetchStub = sinon.stub(window, 'fetch');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.fetch.restore();
|
||||
});
|
||||
|
||||
it("displays message for no deployments detetcted", () => {
|
||||
fetchStub.returnsPromise().resolves({
|
||||
json: () => Promise.resolve({ pods: []})
|
||||
});
|
||||
component = mount(routerWrap(ServiceMesh));
|
||||
|
||||
return withPromise(() => {
|
||||
expect(component.html()).includes("No deployments detected.");
|
||||
});
|
||||
});
|
||||
|
||||
it("displays message for more than one deployment added to servicemesh", () => {
|
||||
fetchStub.returnsPromise().resolves({
|
||||
json: () => Promise.resolve({ pods: podFixtures.pods})
|
||||
});
|
||||
component = mount(routerWrap(ServiceMesh));
|
||||
|
||||
return withPromise(() => {
|
||||
expect(component.html()).includes("deployments have not been added to the service mesh.");
|
||||
});
|
||||
});
|
||||
|
||||
it("displays message for only one deployment not added to servicemesh", () => {
|
||||
let addedPods = _.clone(podFixtures.pods);
|
||||
_.set(addedPods[0], "added", true);
|
||||
|
||||
fetchStub.returnsPromise().resolves({
|
||||
json: () => Promise.resolve({ pods: addedPods})
|
||||
});
|
||||
component = mount(routerWrap(ServiceMesh));
|
||||
|
||||
return withPromise(() => {
|
||||
expect(component.html()).includes("1 deployment has not been added to the service mesh.");
|
||||
});
|
||||
});
|
||||
|
||||
it("displays message for all deployments added to servicemesh", () => {
|
||||
let addedPods = _.clone(podFixtures.pods);
|
||||
_.forEach(addedPods, pod => {
|
||||
_.set(pod, "added", true);
|
||||
});
|
||||
|
||||
fetchStub.returnsPromise().resolves({
|
||||
json: () => Promise.resolve({ pods: addedPods})
|
||||
});
|
||||
component = mount(routerWrap(ServiceMesh));
|
||||
|
||||
return withPromise(() => {
|
||||
expect(component.html()).includes("All deployments have been added to the service mesh.");
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
import _ from 'lodash';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import React from 'react';
|
||||
import { Route, Router } from 'react-router';
|
||||
|
||||
export function routerWrap(Component, extraProps={}, route="/", currentLoc="/") {
|
||||
return (
|
||||
<Router history={createMemoryHistory(currentLoc)} createElement={(Component, props) => <Component {...(_.merge({}, props, extraProps))} />}>
|
||||
<Route path={route} component={Component} />
|
||||
</Router>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue