github.com/hernad/nomad@v1.6.112/ui/app/controllers/exec.js (about)

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