2017-12-15 21:39:18 +00:00
|
|
|
import { run } from '@ember/runloop';
|
2019-03-13 00:04:16 +00:00
|
|
|
import { module, test } from 'qunit';
|
|
|
|
import { setupRenderingTest } from 'ember-qunit';
|
2019-07-23 19:40:32 +00:00
|
|
|
import { find, click, render, settled } from '@ember/test-helpers';
|
2017-11-17 00:31:18 +00:00
|
|
|
import hbs from 'htmlbars-inline-precompile';
|
|
|
|
import Pretender from 'pretender';
|
|
|
|
import { logEncode } from '../../mirage/data/logs';
|
|
|
|
|
|
|
|
const HOST = '1.1.1.1:1111';
|
2018-02-27 21:38:31 +00:00
|
|
|
const allowedConnectionTime = 100;
|
2017-11-17 00:31:18 +00:00
|
|
|
const commonProps = {
|
2018-05-24 22:46:55 +00:00
|
|
|
interval: 200,
|
2017-11-17 00:31:18 +00:00
|
|
|
allocation: {
|
|
|
|
id: 'alloc-1',
|
|
|
|
node: {
|
|
|
|
httpAddr: HOST,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
task: 'task-name',
|
2018-02-27 21:38:31 +00:00
|
|
|
clientTimeout: allowedConnectionTime,
|
|
|
|
serverTimeout: allowedConnectionTime,
|
2017-11-17 00:31:18 +00:00
|
|
|
};
|
|
|
|
|
2019-06-26 21:52:41 +00:00
|
|
|
const logHead = [logEncode(['HEAD'], 0)];
|
|
|
|
const logTail = [logEncode(['TAIL'], 0)];
|
2017-11-17 00:31:18 +00:00
|
|
|
const streamFrames = ['one\n', 'two\n', 'three\n', 'four\n', 'five\n'];
|
|
|
|
let streamPointer = 0;
|
2019-06-26 21:52:41 +00:00
|
|
|
let logMode = null;
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
module('Integration | Component | task log', function(hooks) {
|
|
|
|
setupRenderingTest(hooks);
|
|
|
|
|
|
|
|
hooks.beforeEach(function() {
|
2018-02-26 20:23:01 +00:00
|
|
|
const handler = ({ queryParams }) => {
|
|
|
|
let frames;
|
|
|
|
let data;
|
|
|
|
|
2019-06-26 21:52:41 +00:00
|
|
|
if (logMode === 'head') {
|
2018-02-26 20:23:01 +00:00
|
|
|
frames = logHead;
|
2019-06-26 21:52:41 +00:00
|
|
|
} else if (logMode === 'tail') {
|
2018-02-26 20:23:01 +00:00
|
|
|
frames = logTail;
|
|
|
|
} else {
|
|
|
|
frames = streamFrames;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frames === streamFrames) {
|
|
|
|
data = queryParams.plain ? frames[streamPointer] : logEncode(frames, streamPointer);
|
|
|
|
streamPointer++;
|
|
|
|
} else {
|
|
|
|
data = queryParams.plain ? frames.join('') : logEncode(frames, frames.length - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return [200, {}, data];
|
|
|
|
};
|
|
|
|
|
2017-11-17 00:31:18 +00:00
|
|
|
this.server = new Pretender(function() {
|
2018-02-26 20:23:01 +00:00
|
|
|
this.get(`http://${HOST}/v1/client/fs/logs/:allocation_id`, handler);
|
|
|
|
this.get('/v1/client/fs/logs/:allocation_id', handler);
|
2018-08-09 22:35:25 +00:00
|
|
|
this.get('/v1/regions', () => [200, {}, '[]']);
|
2017-11-17 00:31:18 +00:00
|
|
|
});
|
2019-03-13 00:04:16 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
hooks.afterEach(function() {
|
2017-11-17 00:31:18 +00:00
|
|
|
this.server.shutdown();
|
|
|
|
streamPointer = 0;
|
2019-06-26 21:52:41 +00:00
|
|
|
logMode = null;
|
2019-03-13 00:04:16 +00:00
|
|
|
});
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
test('Basic appearance', async function(assert) {
|
2019-03-14 06:45:15 +00:00
|
|
|
run.later(run, run.cancelTimers, commonProps.interval);
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
this.setProperties(commonProps);
|
|
|
|
await render(hbs`{{task-log allocation=allocation task=task}}`);
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
assert.ok(find('[data-test-log-action="stdout"]'), 'Stdout button');
|
|
|
|
assert.ok(find('[data-test-log-action="stderr"]'), 'Stderr button');
|
|
|
|
assert.ok(find('[data-test-log-action="head"]'), 'Head button');
|
|
|
|
assert.ok(find('[data-test-log-action="tail"]'), 'Tail button');
|
|
|
|
assert.ok(find('[data-test-log-action="toggle-stream"]'), 'Stream toggle button');
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
assert.ok(find('[data-test-log-box].is-full-bleed.is-dark'), 'Body is full-bleed and dark');
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-14 06:45:15 +00:00
|
|
|
assert.ok(
|
|
|
|
find('pre.cli-window'),
|
|
|
|
'Cli is preformatted and using the cli-window component class'
|
|
|
|
);
|
2017-11-17 00:31:18 +00:00
|
|
|
});
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
test('Streaming starts on creation', async function(assert) {
|
|
|
|
run.later(run, run.cancelTimers, commonProps.interval);
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
this.setProperties(commonProps);
|
|
|
|
await render(hbs`{{task-log allocation=allocation task=task}}`);
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
const logUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
|
2017-11-17 00:31:18 +00:00
|
|
|
assert.ok(
|
2019-03-13 00:04:16 +00:00
|
|
|
this.server.handledRequests.filter(req => logUrlRegex.test(req.url)).length,
|
|
|
|
'Log requests were made'
|
2017-11-17 00:31:18 +00:00
|
|
|
);
|
2019-03-13 00:04:16 +00:00
|
|
|
|
2019-03-14 06:45:15 +00:00
|
|
|
await settled();
|
|
|
|
assert.equal(
|
|
|
|
find('[data-test-log-cli]').textContent,
|
|
|
|
streamFrames[0],
|
|
|
|
'First chunk of streaming log is shown'
|
|
|
|
);
|
2017-11-17 00:31:18 +00:00
|
|
|
});
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
test('Clicking Head loads the log head', async function(assert) {
|
2019-06-26 21:52:41 +00:00
|
|
|
logMode = 'head';
|
2019-03-14 06:45:15 +00:00
|
|
|
run.later(run, run.cancelTimers, commonProps.interval);
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
this.setProperties(commonProps);
|
|
|
|
await render(hbs`{{task-log allocation=allocation task=task}}`);
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
click('[data-test-log-action="head"]');
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-14 06:45:15 +00:00
|
|
|
await settled();
|
|
|
|
assert.ok(
|
|
|
|
this.server.handledRequests.find(
|
2019-06-26 21:52:41 +00:00
|
|
|
({ queryParams: qp }) => qp.origin === 'start' && qp.offset === '0'
|
2019-03-14 06:45:15 +00:00
|
|
|
),
|
|
|
|
'Log head request was made'
|
|
|
|
);
|
|
|
|
assert.equal(find('[data-test-log-cli]').textContent, logHead[0], 'Head of the log is shown');
|
2017-11-17 00:31:18 +00:00
|
|
|
});
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
test('Clicking Tail loads the log tail', async function(assert) {
|
2019-06-26 21:52:41 +00:00
|
|
|
logMode = 'tail';
|
2019-03-14 06:45:15 +00:00
|
|
|
run.later(run, run.cancelTimers, commonProps.interval);
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
this.setProperties(commonProps);
|
|
|
|
await render(hbs`{{task-log allocation=allocation task=task}}`);
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
click('[data-test-log-action="tail"]');
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-14 06:45:15 +00:00
|
|
|
await settled();
|
|
|
|
assert.ok(
|
2019-06-26 21:52:41 +00:00
|
|
|
this.server.handledRequests.find(({ queryParams: qp }) => qp.origin === 'end'),
|
2019-03-14 06:45:15 +00:00
|
|
|
'Log tail request was made'
|
|
|
|
);
|
|
|
|
assert.equal(find('[data-test-log-cli]').textContent, logTail[0], 'Tail of the log is shown');
|
2019-03-13 00:04:16 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
test('Clicking toggleStream starts and stops the log stream', async function(assert) {
|
2019-03-14 06:45:15 +00:00
|
|
|
run.later(run, run.cancelTimers, commonProps.interval);
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
const { interval } = commonProps;
|
|
|
|
this.setProperties(commonProps);
|
|
|
|
await render(hbs`{{task-log allocation=allocation task=task interval=interval}}`);
|
2017-11-17 00:31:18 +00:00
|
|
|
|
|
|
|
run.later(() => {
|
2018-01-08 21:08:14 +00:00
|
|
|
click('[data-test-log-action="toggle-stream"]');
|
2019-03-13 00:04:16 +00:00
|
|
|
}, interval);
|
|
|
|
|
2019-03-14 06:45:15 +00:00
|
|
|
await settled();
|
|
|
|
assert.equal(find('[data-test-log-cli]').textContent, streamFrames[0], 'First frame loaded');
|
|
|
|
|
|
|
|
run.later(() => {
|
|
|
|
assert.equal(
|
|
|
|
find('[data-test-log-cli]').textContent,
|
|
|
|
streamFrames[0],
|
|
|
|
'Still only first frame'
|
|
|
|
);
|
|
|
|
click('[data-test-log-action="toggle-stream"]');
|
|
|
|
run.later(run, run.cancelTimers, interval * 2);
|
|
|
|
}, interval * 2);
|
|
|
|
|
|
|
|
await settled();
|
|
|
|
assert.equal(
|
|
|
|
find('[data-test-log-cli]').textContent,
|
|
|
|
streamFrames[0] + streamFrames[0] + streamFrames[1],
|
|
|
|
'Now includes second frame'
|
|
|
|
);
|
2017-11-17 00:31:18 +00:00
|
|
|
});
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
test('Clicking stderr switches the log to standard error', async function(assert) {
|
2019-03-14 06:45:15 +00:00
|
|
|
run.later(run, run.cancelTimers, commonProps.interval);
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
this.setProperties(commonProps);
|
|
|
|
await render(hbs`{{task-log allocation=allocation task=task}}`);
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
click('[data-test-log-action="stderr"]');
|
|
|
|
run.later(run, run.cancelTimers, commonProps.interval);
|
2017-11-17 00:31:18 +00:00
|
|
|
|
2019-03-14 06:45:15 +00:00
|
|
|
await settled();
|
|
|
|
assert.ok(
|
|
|
|
this.server.handledRequests.filter(req => req.queryParams.type === 'stderr').length,
|
|
|
|
'stderr log requests were made'
|
|
|
|
);
|
2017-11-17 00:31:18 +00:00
|
|
|
});
|
2018-02-26 20:23:01 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
test('When the client is inaccessible, task-log falls back to requesting logs through the server', async function(assert) {
|
|
|
|
run.later(run, run.cancelTimers, allowedConnectionTime * 2);
|
2018-02-26 20:23:01 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
// override client response to timeout
|
|
|
|
this.server.get(
|
|
|
|
`http://${HOST}/v1/client/fs/logs/:allocation_id`,
|
|
|
|
() => [400, {}, ''],
|
|
|
|
allowedConnectionTime * 2
|
|
|
|
);
|
2018-02-26 20:23:01 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
this.setProperties(commonProps);
|
|
|
|
await render(hbs`{{task-log
|
2018-02-27 21:38:31 +00:00
|
|
|
allocation=allocation
|
|
|
|
task=task
|
|
|
|
clientTimeout=clientTimeout
|
2019-03-13 00:04:16 +00:00
|
|
|
serverTimeout=serverTimeout}}`);
|
2018-02-26 20:23:01 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
const clientUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
|
2018-02-26 20:23:01 +00:00
|
|
|
assert.ok(
|
2019-03-13 00:04:16 +00:00
|
|
|
this.server.handledRequests.filter(req => clientUrlRegex.test(req.url)).length,
|
|
|
|
'Log request was initially made directly to the client'
|
2018-02-26 20:23:01 +00:00
|
|
|
);
|
2019-03-13 00:04:16 +00:00
|
|
|
|
2019-03-14 06:45:15 +00:00
|
|
|
await settled();
|
|
|
|
const serverUrl = `/v1/client/fs/logs/${commonProps.allocation.id}`;
|
|
|
|
assert.ok(
|
|
|
|
this.server.handledRequests.filter(req => req.url.startsWith(serverUrl)).length,
|
|
|
|
'Log request was later made to the server'
|
|
|
|
);
|
2020-04-28 04:03:33 +00:00
|
|
|
|
|
|
|
assert.ok(
|
|
|
|
this.server.handledRequests.filter(req => clientUrlRegex.test(req.url))[0].aborted,
|
|
|
|
'Client log request was aborted'
|
|
|
|
);
|
2018-02-26 20:23:01 +00:00
|
|
|
});
|
2018-02-27 21:38:31 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
test('When both the client and the server are inaccessible, an error message is shown', async function(assert) {
|
|
|
|
run.later(run, run.cancelTimers, allowedConnectionTime * 5);
|
|
|
|
|
|
|
|
// override client and server responses to timeout
|
|
|
|
this.server.get(
|
|
|
|
`http://${HOST}/v1/client/fs/logs/:allocation_id`,
|
|
|
|
() => [400, {}, ''],
|
|
|
|
allowedConnectionTime * 2
|
|
|
|
);
|
|
|
|
this.server.get(
|
|
|
|
'/v1/client/fs/logs/:allocation_id',
|
|
|
|
() => [400, {}, ''],
|
|
|
|
allowedConnectionTime * 2
|
|
|
|
);
|
|
|
|
|
|
|
|
this.setProperties(commonProps);
|
|
|
|
await render(hbs`{{task-log
|
2018-02-27 21:38:31 +00:00
|
|
|
allocation=allocation
|
|
|
|
task=task
|
|
|
|
clientTimeout=clientTimeout
|
2019-03-13 00:04:16 +00:00
|
|
|
serverTimeout=serverTimeout}}`);
|
2018-02-27 21:38:31 +00:00
|
|
|
|
2019-03-14 06:45:15 +00:00
|
|
|
await settled();
|
|
|
|
const clientUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
|
|
|
|
assert.ok(
|
|
|
|
this.server.handledRequests.filter(req => clientUrlRegex.test(req.url)).length,
|
|
|
|
'Log request was initially made directly to the client'
|
|
|
|
);
|
|
|
|
const serverUrl = `/v1/client/fs/logs/${commonProps.allocation.id}`;
|
|
|
|
assert.ok(
|
|
|
|
this.server.handledRequests.filter(req => req.url.startsWith(serverUrl)).length,
|
|
|
|
'Log request was later made to the server'
|
|
|
|
);
|
|
|
|
assert.ok(find('[data-test-connection-error]'), 'An error message is shown');
|
2018-02-27 21:38:31 +00:00
|
|
|
});
|
|
|
|
});
|