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