Skip to content

Commit

Permalink
[ui] Service Discovery: provide a quick link to the Consul UI if avai…
Browse files Browse the repository at this point in the history
…lable (#14537)

* Test for aggregate service health and consul agg service health

* If a consul UI link is present, show a nice little link

* Also add to job services page

* Reallocate consul url in mock
  • Loading branch information
philrenaud committed Sep 12, 2022
1 parent 23dd158 commit a62a654
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 10 deletions.
27 changes: 18 additions & 9 deletions ui/app/components/allocation-service-sidebar.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@
<header class="detail-header">
<h1 class="title">
{{@service.name}}
<span class="aggregate-status">
{{#if (eq this.aggregateStatus 'Unhealthy')}}
<FlightIcon @name="x-square-fill" @color="#c84034" />
Unhealthy
{{else}}
<FlightIcon @name="check-square-fill" @color="#25ba81" />
Healthy
{{/if}}
</span>
{{#if (not-eq @service.provider "consul")}}
<span class="aggregate-status">
{{#if (eq this.aggregateStatus 'Unhealthy')}}
<FlightIcon @name="x-square-fill" @color="#c84034" />
Unhealthy
{{else}}
<FlightIcon @name="check-square-fill" @color="#25ba81" />
Healthy
{{/if}}
</span>
{{/if}}
</h1>
<button
data-test-close-service-sidebar
Expand Down Expand Up @@ -126,5 +128,12 @@
</t.body>
</ListTable>
{{/if}}
{{#if (and (eq @service.provider "consul") this.consulRedirectLink)}}
<div data-test-consul-link-notice class="notification is-info">
<p>
Nomad cannot read health check information from Consul services, but you can <a href={{this.consulRedirectLink}} target="_blank" rel="noopener noreferrer">view this information in your Consul UI</a>.
</p>
</div>
{{/if}}
{{/if}}
</div>
5 changes: 5 additions & 0 deletions ui/app/components/allocation-service-sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { inject as service } from '@ember/service';

export default class AllocationServiceSidebarComponent extends Component {
@service store;
@service system;

get isSideBarOpen() {
return !!this.args.service;
Expand Down Expand Up @@ -37,6 +38,10 @@ export default class AllocationServiceSidebarComponent extends Component {
: 'Healthy';
}

get consulRedirectLink() {
return this.system.agent.get('config')?.UI?.Consul?.BaseUIURL;
}

get checks() {
if (!this.args.service || !this.args.allocation) return [];
let allocID = this.args.allocation.id;
Expand Down
5 changes: 5 additions & 0 deletions ui/app/components/job-service-row.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { inject as service } from '@ember/service';

export default class JobServiceRowComponent extends Component {
@service router;
@service system;

@action
gotoService(service) {
Expand All @@ -14,4 +15,8 @@ export default class JobServiceRowComponent extends Component {
});
}
}

get consulRedirectLink() {
return this.system.agent.get('config')?.UI?.Consul?.BaseUIURL;
}
}
8 changes: 7 additions & 1 deletion ui/app/templates/components/job-service-row.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
<LinkTo class="is-primary" @route="jobs.job.services.service" @model={{@service}} @query={{hash level=@service.level}}>{{@service.name}}</LinkTo>
{{else}}
<FlightIcon @name="consul-color" />
{{@service.name}}
{{#if (and (eq @service.provider "consul") this.consulRedirectLink)}}
<a class="is-primary" href={{this.consulRedirectLink}} target="_blank" rel="noopener noreferrer">
{{@service.name}}
</a>
{{else}}
{{@service.name}}
{{/if}}
{{/if}}
</td>
<td>
Expand Down
78 changes: 78 additions & 0 deletions ui/tests/integration/components/allocation-service-sidebar-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,28 @@ import { setupRenderingTest } from 'ember-qunit';
import { click, render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
import Service from '@ember/service';
import EmberObject from '@ember/object';

module(
'Integration | Component | allocation-service-sidebar',
function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {
const mockSystem = Service.extend({
agent: EmberObject.create({
config: {
UI: {
Consul: {
BaseUIURL: '',
},
},
},
}),
});
this.owner.register('service:system', mockSystem);
this.system = this.owner.lookup('service:system');
});

test('it supports basic open/close states', async function (assert) {
assert.expect(7);
Expand All @@ -34,5 +51,66 @@ module(
assert.dom(this.element).hasText('');
assert.dom('.sidebar').doesNotHaveClass('open');
});

test('it correctly aggregates service health', async function (assert) {
const healthyService = {
name: 'Funky Service',
provider: 'nomad',
healthChecks: [
{ Check: 'one', Status: 'success', Alloc: 'myAlloc' },
{ Check: 'two', Status: 'success', Alloc: 'myAlloc' },
],
};
const unhealthyService = {
name: 'Funky Service',
provider: 'nomad',
healthChecks: [
{ Check: 'one', Status: 'failure', Alloc: 'myAlloc' },
{ Check: 'two', Status: 'success', Alloc: 'myAlloc' },
],
};

this.set('closeSidebar', () => this.set('service', null));
this.set('allocation', { id: 'myAlloc' });
this.set('service', healthyService);
await render(
hbs`<AllocationServiceSidebar @service={{this.service}} @allocation={{this.allocation}} @fns={{hash closeSidebar=this.closeSidebar}} />`
);
assert.dom('h1 .aggregate-status').includesText('Healthy');
assert
.dom('table.health-checks tbody tr')
.exists({ count: 2 }, 'has two rows');

this.set('service', unhealthyService);
await render(
hbs`<AllocationServiceSidebar @service={{this.service}} @allocation={{this.allocation}} @fns={{hash closeSidebar=this.closeSidebar}} />`
);
assert.dom('h1 .aggregate-status').includesText('Unhealthy');
});

test('it handles Consul services with reduced functionality', async function (assert) {
const consulService = {
name: 'Consul Service',
provider: 'consul',
healthChecks: [],
};

this.set('closeSidebar', () => this.set('service', null));
this.set('service', consulService);
await render(
hbs`<AllocationServiceSidebar @service={{this.service}} @fns={{hash closeSidebar=this.closeSidebar}} />`
);
assert.dom('h1 .aggregate-status').doesNotExist();
assert.dom('table.health-checks').doesNotExist();
assert.dom('[data-test-consul-link-notice]').doesNotExist();

this.system.agent.config.UI.Consul.BaseUIURL = 'http://localhost:8500';

await render(
hbs`<AllocationServiceSidebar @service={{this.service}} @fns={{hash closeSidebar=this.closeSidebar}} />`
);

assert.dom('[data-test-consul-link-notice]').exists();
});
}
);

0 comments on commit a62a654

Please sign in to comment.