Files
nomad/ui/app/controllers/exec.js
Buck Doyle 90ec5e6457 UI: add exec handling for dead jobs/task states (#7637)
This closes #7456. It hides the terminal when the job is dead and
displays an error when trying to open an exec session for a task
that isn’t running. There’s a skipped test for the latter behaviour
that I’ll have to come back for.
2020-04-06 14:08:22 -05:00

138 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { inject as service } from '@ember/service';
import Controller from '@ember/controller';
import { computed } from '@ember/object';
import { alias, mapBy, sort, uniq } from '@ember/object/computed';
import escapeTaskName from 'nomad-ui/utils/escape-task-name';
import ExecCommandEditorXtermAdapter from 'nomad-ui/utils/classes/exec-command-editor-xterm-adapter';
import ExecSocketXtermAdapter from 'nomad-ui/utils/classes/exec-socket-xterm-adapter';
import localStorageProperty from 'nomad-ui/utils/properties/local-storage';
import { Terminal } from 'xterm-vendor';
const ANSI_UI_GRAY_400 = '\x1b[38;2;142;150;163m';
const ANSI_WHITE = '\x1b[0m';
export default Controller.extend({
sockets: service(),
system: service(),
token: service(),
queryParams: ['allocation'],
command: localStorageProperty('nomadExecCommand', '/bin/bash'),
socketOpen: false,
pendingAndRunningAllocations: computed('model.allocations.@each.clientStatus', function() {
return this.model.allocations.filter(
allocation => allocation.clientStatus === 'pending' || allocation.clientStatus === 'running'
);
}),
pendingAndRunningTaskGroups: mapBy('pendingAndRunningAllocations', 'taskGroup'),
uniquePendingAndRunningTaskGroups: uniq('pendingAndRunningTaskGroups'),
taskGroupSorting: Object.freeze(['name']),
sortedTaskGroups: sort('uniquePendingAndRunningTaskGroups', 'taskGroupSorting'),
init() {
this._super(...arguments);
this.terminal = new Terminal({ fontFamily: 'monospace', fontWeight: '400' });
window.execTerminal = this.terminal; // Issue to improve: https://github.com/hashicorp/nomad/issues/7457
this.terminal.write(ANSI_UI_GRAY_400);
this.terminal.writeln('Select a task to start your session.');
},
allocations: alias('model.allocations'),
taskState: computed(
'allocations.[]',
'allocationShortId',
'allocations.@each.isActive',
'taskName',
'taskGroupName',
'allocation',
'allocation.states.@each.name',
'allocation.states.@each.isRunning',
function() {
if (!this.allocations) {
return false;
}
let allocation;
if (this.allocationShortId) {
allocation = this.allocations.findBy('shortId', this.allocationShortId);
} else {
allocation = this.allocations.find(allocation =>
allocation.states
.filterBy('isActive')
.mapBy('name')
.includes(this.taskName)
);
}
if (allocation) {
return allocation.states.find(state => state.name === this.taskName);
}
}
),
actions: {
setTaskProperties({ allocationShortId, taskName, taskGroupName }) {
this.setProperties({
allocationShortId,
taskName,
taskGroupName,
});
if (this.taskState) {
this.terminal.write(ANSI_UI_GRAY_400);
this.terminal.writeln('');
if (!allocationShortId) {
this.terminal.writeln(
'Multiple instances of this task are running. The allocation below was selected by random draw.'
);
this.terminal.writeln('');
}
this.terminal.writeln('Customize your command, then hit return to run.');
this.terminal.writeln('');
this.terminal.write(
`$ nomad alloc exec -i -t -task ${escapeTaskName(taskName)} ${
this.taskState.allocation.shortId
} `
);
this.terminal.write(ANSI_WHITE);
this.terminal.write(this.command);
if (this.commandEditorAdapter) {
this.commandEditorAdapter.destroy();
}
this.commandEditorAdapter = new ExecCommandEditorXtermAdapter(
this.terminal,
this.openAndConnectSocket.bind(this),
this.command
);
}
},
},
openAndConnectSocket(command) {
if (this.taskState) {
this.set('socketOpen', true);
this.set('command', command);
this.socket = this.sockets.getTaskStateSocket(this.taskState, command);
new ExecSocketXtermAdapter(this.terminal, this.socket, this.token.secret);
} else {
this.terminal.writeln(`Failed to open a socket because task ${this.taskName} is not active.`);
}
},
});