github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/ui/app/controllers/exec.js (about) 1 import { inject as service } from '@ember/service'; 2 import Controller from '@ember/controller'; 3 import { computed } from '@ember/object'; 4 import { alias, mapBy, sort, uniq } from '@ember/object/computed'; 5 import escapeTaskName from 'nomad-ui/utils/escape-task-name'; 6 import ExecCommandEditorXtermAdapter from 'nomad-ui/utils/classes/exec-command-editor-xterm-adapter'; 7 import ExecSocketXtermAdapter from 'nomad-ui/utils/classes/exec-socket-xterm-adapter'; 8 import localStorageProperty from 'nomad-ui/utils/properties/local-storage'; 9 10 import { Terminal } from 'xterm-vendor'; 11 12 const ANSI_UI_GRAY_400 = '\x1b[38;2;142;150;163m'; 13 const ANSI_WHITE = '\x1b[0m'; 14 15 export default Controller.extend({ 16 sockets: service(), 17 system: service(), 18 token: service(), 19 20 queryParams: ['allocation'], 21 22 command: localStorageProperty('nomadExecCommand', '/bin/bash'), 23 socketOpen: false, 24 25 pendingAndRunningAllocations: computed('model.allocations.@each.clientStatus', function() { 26 return this.model.allocations.filter( 27 allocation => allocation.clientStatus === 'pending' || allocation.clientStatus === 'running' 28 ); 29 }), 30 31 pendingAndRunningTaskGroups: mapBy('pendingAndRunningAllocations', 'taskGroup'), 32 uniquePendingAndRunningTaskGroups: uniq('pendingAndRunningTaskGroups'), 33 34 taskGroupSorting: Object.freeze(['name']), 35 sortedTaskGroups: sort('uniquePendingAndRunningTaskGroups', 'taskGroupSorting'), 36 37 init() { 38 this._super(...arguments); 39 40 this.terminal = new Terminal({ fontFamily: 'monospace', fontWeight: '400' }); 41 window.execTerminal = this.terminal; // Issue to improve: https://github.com/hashicorp/nomad/issues/7457 42 43 this.terminal.write(ANSI_UI_GRAY_400); 44 this.terminal.writeln('Select a task to start your session.'); 45 }, 46 47 allocations: alias('model.allocations'), 48 49 taskState: computed( 50 'allocations.[]', 51 'allocationShortId', 52 'allocations.@each.isActive', 53 'taskName', 54 'taskGroupName', 55 'allocation', 56 'allocation.states.@each.name', 57 'allocation.states.@each.isRunning', 58 function() { 59 if (!this.allocations) { 60 return false; 61 } 62 63 let allocation; 64 65 if (this.allocationShortId) { 66 allocation = this.allocations.findBy('shortId', this.allocationShortId); 67 } else { 68 allocation = this.allocations.find(allocation => 69 allocation.states 70 .filterBy('isActive') 71 .mapBy('name') 72 .includes(this.taskName) 73 ); 74 } 75 76 if (allocation) { 77 return allocation.states.find(state => state.name === this.taskName); 78 } 79 } 80 ), 81 82 actions: { 83 setTaskProperties({ allocationShortId, taskName, taskGroupName }) { 84 this.setProperties({ 85 allocationShortId, 86 taskName, 87 taskGroupName, 88 }); 89 90 if (this.taskState) { 91 this.terminal.write(ANSI_UI_GRAY_400); 92 this.terminal.writeln(''); 93 94 if (!allocationShortId) { 95 this.terminal.writeln( 96 'Multiple instances of this task are running. The allocation below was selected by random draw.' 97 ); 98 this.terminal.writeln(''); 99 } 100 101 this.terminal.writeln('Customize your command, then hit ‘return’ to run.'); 102 this.terminal.writeln(''); 103 this.terminal.write( 104 `$ nomad alloc exec -i -t -task ${escapeTaskName(taskName)} ${ 105 this.taskState.allocation.shortId 106 } ` 107 ); 108 109 this.terminal.write(ANSI_WHITE); 110 111 this.terminal.write(this.command); 112 113 if (this.commandEditorAdapter) { 114 this.commandEditorAdapter.destroy(); 115 } 116 117 this.commandEditorAdapter = new ExecCommandEditorXtermAdapter( 118 this.terminal, 119 this.openAndConnectSocket.bind(this), 120 this.command 121 ); 122 } 123 }, 124 }, 125 126 openAndConnectSocket(command) { 127 if (this.taskState) { 128 this.set('socketOpen', true); 129 this.set('command', command); 130 this.socket = this.sockets.getTaskStateSocket(this.taskState, command); 131 132 new ExecSocketXtermAdapter(this.terminal, this.socket, this.token.secret); 133 } else { 134 this.terminal.writeln(`Failed to open a socket because task ${this.taskName} is not active.`); 135 } 136 }, 137 });