github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/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', 'namespace'];
    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) =>
    29          allocation.clientStatus === 'pending' ||
    30          allocation.clientStatus === 'running'
    31      );
    32    }
    33  
    34    @mapBy('pendingAndRunningAllocations', 'taskGroup')
    35    pendingAndRunningTaskGroups;
    36    @uniq('pendingAndRunningTaskGroups') uniquePendingAndRunningTaskGroups;
    37  
    38    taskGroupSorting = ['name'];
    39    @sort('uniquePendingAndRunningTaskGroups', 'taskGroupSorting')
    40    sortedTaskGroups;
    41  
    42    setUpTerminal(Terminal) {
    43      this.terminal = new Terminal({
    44        fontFamily: 'monospace',
    45        fontWeight: '400',
    46      });
    47      window.execTerminal = this.terminal; // Issue to improve: https://github.com/hashicorp/nomad/issues/7457
    48  
    49      this.terminal.write(ANSI_UI_GRAY_400);
    50  
    51      if (this.sortedTaskGroups.length > 0) {
    52        this.terminal.writeln('Select a task to start your session.');
    53      } else {
    54        this.terminal.writeln(`There are no tasks running for this job.`);
    55      }
    56    }
    57  
    58    @alias('model.allocations') allocations;
    59  
    60    @computed(
    61      'allocations.{[],@each.isActive}',
    62      'allocationShortId',
    63      'taskName',
    64      'taskGroupName',
    65      'allocation',
    66      'allocation.states.@each.{name,isRunning}'
    67    )
    68    get taskState() {
    69      if (!this.allocations) {
    70        return false;
    71      }
    72  
    73      let allocation;
    74  
    75      if (this.allocationShortId) {
    76        allocation = this.allocations.findBy('shortId', this.allocationShortId);
    77      } else {
    78        allocation = this.allocations.find((allocation) =>
    79          allocation.states
    80            .filterBy('isActive')
    81            .mapBy('name')
    82            .includes(this.taskName)
    83        );
    84      }
    85  
    86      if (allocation) {
    87        return allocation.states.find((state) => state.name === this.taskName);
    88      }
    89  
    90      return undefined;
    91    }
    92  
    93    @action
    94    setTaskProperties({ allocationShortId, taskName, taskGroupName }) {
    95      this.setProperties({
    96        allocationShortId,
    97        taskName,
    98        taskGroupName,
    99      });
   100  
   101      if (this.taskState) {
   102        this.terminal.write(ANSI_UI_GRAY_400);
   103        this.terminal.writeln('');
   104  
   105        if (!allocationShortId) {
   106          this.terminal.writeln(
   107            'Multiple instances of this task are running. The allocation below was selected by random draw.'
   108          );
   109          this.terminal.writeln('');
   110        }
   111  
   112        this.terminal.writeln(
   113          'Customize your command, then hit ‘return’ to run.'
   114        );
   115        this.terminal.writeln('');
   116        this.terminal.write(
   117          `$ nomad alloc exec -i -t -task ${escapeTaskName(taskName)} ${
   118            this.taskState.allocation.shortId
   119          } `
   120        );
   121  
   122        this.terminal.write(ANSI_WHITE);
   123  
   124        this.terminal.write(this.command);
   125  
   126        if (this.commandEditorAdapter) {
   127          this.commandEditorAdapter.destroy();
   128        }
   129  
   130        this.commandEditorAdapter = new ExecCommandEditorXtermAdapter(
   131          this.terminal,
   132          this.openAndConnectSocket.bind(this),
   133          this.command
   134        );
   135      }
   136    }
   137  
   138    openAndConnectSocket(command) {
   139      if (this.taskState) {
   140        this.set('socketOpen', true);
   141        this.set('command', command);
   142        this.socket = this.sockets.getTaskStateSocket(this.taskState, command);
   143  
   144        new ExecSocketXtermAdapter(this.terminal, this.socket, this.token.secret);
   145      } else {
   146        this.terminal.writeln(
   147          `Failed to open a socket because task ${this.taskName} is not active.`
   148        );
   149      }
   150    }
   151  }