Merge pull request #3777 from johncowen/f-ui-api-task-events-messages

UI: Make task-events use the `message` from the API rather than hardcoded
This commit is contained in:
Michael Lange
2018-02-05 18:36:41 -08:00
committed by GitHub
8 changed files with 11 additions and 155 deletions

View File

@@ -1,27 +1,6 @@
import { computed } from '@ember/object';
import Fragment from 'ember-data-model-fragments/fragment';
import attr from 'ember-data/attr';
import { fragmentOwner } from 'ember-data-model-fragments/attributes';
import moment from 'moment';
const displayProps = [
'message',
'validationError',
'setupError',
'driverError',
'downloadError',
'killReason',
'killTimeout',
'killError',
'exitCode',
'signal',
'startDelay',
'restartReason',
'failedSibling',
'taskSignal',
'taskSignalReason',
'driverMessage',
];
export default Fragment.extend({
state: fragmentOwner(),
@@ -45,103 +24,5 @@ export default Fragment.extend({
taskSignal: attr('string'),
taskSignalReason: attr('string'),
validationError: attr('string'),
vaultError: attr('string'),
message: attr('string'),
failedSibling: attr('string'),
displayMessage: computed(...displayProps, function() {
let desc = '';
switch (this.get('type')) {
case 'Task Setup':
desc = this.get('message');
break;
case 'Started':
desc = 'Task started by client';
break;
case 'Received':
desc = 'Task received by client';
break;
case 'Failed Validation':
desc = this.get('validationError') || 'Validation of task failed';
break;
case 'Setup Failure':
desc = this.get('setupError') || 'Task setup failed';
break;
case 'Driver Failure':
desc = this.get('driverError') || 'Failed to start task';
break;
case 'Downloading Artifacts':
desc = 'Client is downloading artifacts';
break;
case 'Failed Artifact Download':
desc = this.get('downloadError') || 'Failed to download artifacts';
break;
case 'Killing':
desc =
this.get('killReason') ||
(this.get('killTimeout') &&
`Sent interrupt. Waiting ${this.get('killTimeout')} before force killing`);
break;
case 'Killed':
desc = this.get('killError') || 'Task successfully killed';
break;
case 'Terminated':
var parts = [`Exit Code: ${this.get('exitCode')}`];
if (this.get('signal')) {
parts.push(`Signal: ${this.get('signal')}`);
}
if (this.get('message')) {
parts.push(`Exit Message: ${this.get('message')}`);
}
desc = parts.join(', ');
break;
case 'Restarting':
var timerMessage = `Task restarting in ${moment
.duration(this.get('startDelay') / 1000000, 'ms')
.humanize()}`;
if (this.get('restartReason') && this.get('restartReason') !== 'Restart within policy') {
desc = `${this.get('restartReason')} - ${timerMessage}`;
} else {
desc = timerMessage;
}
break;
case 'Not Restarting':
desc = this.get('restartReason') || 'Task exceeded restart policy';
break;
case 'Sibling Task Failed':
desc = this.get('failedSibling')
? `Task's sibling ${this.get('failedSibling')} failed`
: "Task's sibling failed";
break;
case 'Signaling':
var signal = this.get('taskSignal');
var reason = this.get('taskSignalReason');
if (!signal && !reason) {
desc = 'Task being sent a signal';
} else if (!signal) {
desc = reason;
} else if (!reason) {
desc = `Task being sent signal ${signal}`;
} else {
desc = `Task being sent signal ${signal}: ${reason}`;
}
break;
case 'Restart Signaled':
desc = this.get('restartReason') || 'Task signaled to restart';
break;
case 'Driver':
desc = this.get('driverMessage');
break;
case 'Leader Task Dead':
desc = 'Leader Task in Group dead';
break;
case 'Generic':
desc = this.get('message');
break;
}
return desc;
}),
});

View File

@@ -50,8 +50,8 @@
</td>
<td data-test-state>{{row.model.state}}</td>
<td data-test-message>
{{#if row.model.events.lastObject.displayMessage}}
{{row.model.events.lastObject.displayMessage}}
{{#if row.model.events.lastObject.message}}
{{row.model.events.lastObject.message}}
{{else}}
<em>No message</em>
{{/if}}

View File

@@ -83,8 +83,8 @@
<td data-test-task-event-time>{{moment-format row.model.time "MM/DD/YY HH:mm:ss"}}</td>
<td data-test-task-event-type>{{row.model.type}}</td>
<td data-test-task-event-message>
{{#if row.model.displayMessage}}
{{row.model.displayMessage}}
{{#if row.model.message}}
{{row.model.message}}
{{else}}
<em>No message</em>
{{/if}}

View File

@@ -18,9 +18,6 @@ export default Factory.extend({
clientStatus: faker.list.random(...CLIENT_STATUSES),
desiredStatus: faker.list.random(...DESIRED_STATUSES),
// Meta property for hinting at task events
useMessagePassthru: false,
withTaskWithPorts: trait({
afterCreate(allocation, server) {
const taskGroup = server.db.taskGroups.findBy({ name: allocation.taskGroup });
@@ -79,7 +76,6 @@ export default Factory.extend({
server.create('task-state', {
allocation,
name: server.db.tasks.find(id).name,
useMessagePassthru: allocation.useMessagePassthru,
})
);

View File

@@ -7,12 +7,6 @@ const STATES = provide(10, faker.system.fileExt.bind(faker.system));
export default Factory.extend({
type: faker.list.random(...STATES),
// Message is a function of type, and this type uses the vanilla
// message property.
messagePassthru: trait({
type: 'Task Setup',
}),
signal: () => '',
exitCode: () => null,
time: () => faker.date.past(2 / 365, REF_TIME) * 1000000,
@@ -26,6 +20,5 @@ export default Factory.extend({
setupError: () => '',
taskSignalReason: () => '',
validationError: () => '',
vaultError: () => '',
message: () => faker.lorem.sentence(),
});

View File

@@ -14,13 +14,11 @@ export default Factory.extend({
return new Date(this.startedAt + Math.random(1000 * 60 * 3) + 50);
},
useMessagePassthru: false,
afterCreate(state, server) {
const props = [
'task-event',
faker.random.number({ min: 1, max: 10 }),
state.useMessagePassthru && 'messagePassthru',
false,
{
taskStateId: state.id,
},

View File

@@ -14,17 +14,13 @@ moduleForAcceptance('Acceptance | allocation detail', {
node = server.create('node');
job = server.create('job', { groupCount: 0 });
allocation = server.create('allocation', 'withTaskWithPorts', {
useMessagePassthru: true,
});
allocation = server.create('allocation', 'withTaskWithPorts');
visit(`/allocations/${allocation.id}`);
},
});
test('/allocation/:id should name the allocation and link to the corresponding job and node', function(
assert
) {
test('/allocation/:id should name the allocation and link to the corresponding job and node', function(assert) {
assert.ok(
find('[data-test-title]').textContent.includes(allocation.name),
'Allocation name is in the heading'
@@ -125,9 +121,7 @@ test('each task row should list high-level information for the task', function(a
});
});
test('when the allocation is not found, an error message is shown, but the URL persists', function(
assert
) {
test('when the allocation is not found, an error message is shown, but the URL persists', function(assert) {
visit('/allocations/not-a-real-allocation');
andThen(() => {

View File

@@ -12,18 +12,14 @@ moduleForAcceptance('Acceptance | task detail', {
server.create('agent');
server.create('node');
server.create('job', { createAllocations: false });
allocation = server.create('allocation', 'withTaskWithPorts', {
useMessagePassthru: true,
});
allocation = server.create('allocation', 'withTaskWithPorts');
task = server.db.taskStates.where({ allocationId: allocation.id })[0];
visit(`/allocations/${allocation.id}/${task.name}`);
},
});
test('/allocation/:id/:task_name should name the task and list high-level task information', function(
assert
) {
test('/allocation/:id/:task_name should name the task and list high-level task information', function(assert) {
assert.ok(find('[data-test-title]').textContent.includes(task.name), 'Task name');
assert.ok(find('[data-test-state]').textContent.includes(task.state), 'Task state');
@@ -119,9 +115,7 @@ test('the events table lists all recent events', function(assert) {
);
});
test('each recent event should list the time, type, and description of the event', function(
assert
) {
test('each recent event should list the time, type, and description of the event', function(assert) {
const event = server.db.taskEvents.where({ taskStateId: task.id })[0];
const recentEvent = findAll('[data-test-task-event]').get('lastObject');