diff --git a/ui/app/components/task-log.js b/ui/app/components/task-log.js
index fcc911a1c..2cc8617e4 100644
--- a/ui/app/components/task-log.js
+++ b/ui/app/components/task-log.js
@@ -16,8 +16,15 @@ export default Component.extend(WindowResizable, {
allocation: null,
task: null,
+ // When true, request logs from the server agent
useServer: false,
+ // When true, logs cannot be fetched from either the client or the server
+ noConnection: false,
+
+ clientTimeout: 1000,
+ serverTimeout: 5000,
+
didReceiveAttrs() {
if (this.get('allocation') && this.get('task')) {
this.send('toggleStream');
@@ -59,12 +66,17 @@ export default Component.extend(WindowResizable, {
logger: logger('logUrl', 'logParams', function logFetch() {
// If the log request can't settle in one second, the client
// must be unavailable and the server should be used instead
+ const timing = this.get('useServer') ? this.get('serverTimeout') : this.get('clientTimeout');
return url =>
- RSVP.race([this.get('token').authorizedRequest(url), timeout(1000)]).then(
+ RSVP.race([this.get('token').authorizedRequest(url), timeout(timing)]).then(
response => response,
error => {
- this.send('failoverToServer');
- this.get('stream').perform();
+ if (this.get('useServer')) {
+ this.set('noConnection', true);
+ } else {
+ this.send('failoverToServer');
+ this.get('stream').perform();
+ }
throw error;
}
);
diff --git a/ui/app/templates/components/task-log.hbs b/ui/app/templates/components/task-log.hbs
index ce0d0ae9c..6c3991a35 100644
--- a/ui/app/templates/components/task-log.hbs
+++ b/ui/app/templates/components/task-log.hbs
@@ -1,3 +1,9 @@
+{{#if noConnection}}
+
+
Cannot fetch logs
+
The logs for this task are inaccessible. Check the condition of the node the allocation is on.
+
+{{/if}}
diff --git a/ui/tests/integration/task-log-test.js b/ui/tests/integration/task-log-test.js
index cf60e5999..f6a7416fd 100644
--- a/ui/tests/integration/task-log-test.js
+++ b/ui/tests/integration/task-log-test.js
@@ -7,6 +7,7 @@ import Pretender from 'pretender';
import { logEncode } from '../../mirage/data/logs';
const HOST = '1.1.1.1:1111';
+const allowedConnectionTime = 100;
const commonProps = {
interval: 50,
allocation: {
@@ -16,6 +17,8 @@ const commonProps = {
},
},
task: 'task-name',
+ clientTimeout: allowedConnectionTime,
+ serverTimeout: allowedConnectionTime,
};
const logHead = ['HEAD'];
@@ -179,13 +182,23 @@ test('Clicking stderr switches the log to standard error', function(assert) {
});
test('When the client is inaccessible, task-log falls back to requesting logs through the server', function(assert) {
- run.later(run, run.cancelTimers, 2000);
+ run.later(run, run.cancelTimers, allowedConnectionTime * 2);
// override client response to timeout
- this.server.get(`http://${HOST}/v1/client/fs/logs/:allocation_id`, () => [400, {}, ''], 2000);
+ this.server.get(
+ `http://${HOST}/v1/client/fs/logs/:allocation_id`,
+ () => [400, {}, ''],
+ allowedConnectionTime * 2
+ );
this.setProperties(commonProps);
- this.render(hbs`{{task-log allocation=allocation task=task}}`);
+ this.render(
+ hbs`{{task-log
+ allocation=allocation
+ task=task
+ clientTimeout=clientTimeout
+ serverTimeout=serverTimeout}}`
+ );
const clientUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
assert.ok(
@@ -201,3 +214,42 @@ test('When the client is inaccessible, task-log falls back to requesting logs th
);
});
});
+
+test('When both the client and the server are inaccessible, an error message is shown', 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);
+ this.render(
+ hbs`{{task-log
+ allocation=allocation
+ task=task
+ clientTimeout=clientTimeout
+ serverTimeout=serverTimeout}}`
+ );
+
+ return wait().then(() => {
+ 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');
+ });
+});