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

     1  /**
     2   * Copyright (c) HashiCorp, Inc.
     3   * SPDX-License-Identifier: MPL-2.0
     4   */
     5  
     6  /* eslint-disable ember/no-observers */
     7  import Controller from '@ember/controller';
     8  import { inject as service } from '@ember/service';
     9  import { action, computed } from '@ember/object';
    10  import { observes } from '@ember-decorators/object';
    11  import { computed as overridable } from 'ember-overridable-computed';
    12  import { alias } from '@ember/object/computed';
    13  import { task } from 'ember-concurrency';
    14  import Sortable from 'nomad-ui/mixins/sortable';
    15  import { lazyClick } from 'nomad-ui/helpers/lazy-click';
    16  import { watchRecord } from 'nomad-ui/utils/properties/watch';
    17  import messageForError from 'nomad-ui/utils/message-from-adapter-error';
    18  import classic from 'ember-classic-decorator';
    19  import { union } from '@ember/object/computed';
    20  import { tracked } from '@glimmer/tracking';
    21  
    22  @classic
    23  export default class IndexController extends Controller.extend(Sortable) {
    24    @service token;
    25    @service store;
    26  
    27    queryParams = [
    28      {
    29        sortProperty: 'sort',
    30      },
    31      {
    32        sortDescending: 'desc',
    33      },
    34      {
    35        activeServiceID: 'service',
    36      },
    37    ];
    38  
    39    sortProperty = 'name';
    40    sortDescending = false;
    41  
    42    @alias('model.states') listToSort;
    43    @alias('listSorted') sortedStates;
    44  
    45    // Set in the route
    46    preempter = null;
    47  
    48    @overridable(function () {
    49      // { title, description }
    50      return null;
    51    })
    52    error;
    53  
    54    @computed('model.allocatedResources.ports.@each.label')
    55    get ports() {
    56      return (this.get('model.allocatedResources.ports') || []).sortBy('label');
    57    }
    58  
    59    @computed('model.states.@each.task')
    60    get tasks() {
    61      return this.get('model.states').mapBy('task') || [];
    62    }
    63  
    64    @computed('tasks.@each.services')
    65    get taskServices() {
    66      return this.get('tasks')
    67        .map((t) => ((t && t.services) || []).toArray())
    68        .flat()
    69        .compact();
    70    }
    71  
    72    @computed('model.taskGroup.services.@each.name')
    73    get groupServices() {
    74      return (this.get('model.taskGroup.services') || []).sortBy('name');
    75    }
    76  
    77    @union('taskServices', 'groupServices') services;
    78  
    79    @computed('model.{healthChecks,id}', 'services')
    80    get servicesWithHealthChecks() {
    81      return this.services.map((service) => {
    82        if (this.model.healthChecks) {
    83          const healthChecks = Object.values(this.model.healthChecks)?.filter(
    84            (check) => {
    85              const refPrefix =
    86                check.Task || check.Group.split('.')[1].split('[')[0];
    87              const currentServiceName = `${refPrefix}-${check.Service}`;
    88              return currentServiceName === service.refID;
    89            }
    90          );
    91          healthChecks.forEach((check) => {
    92            service.healthChecks.pushObject(check);
    93          });
    94        }
    95        // Contextualize healthchecks for the allocation we're in
    96        service.healthChecks = service.healthChecks.filterBy(
    97          'Alloc',
    98          this.model.id
    99        );
   100        return service;
   101      });
   102    }
   103  
   104    onDismiss() {
   105      this.set('error', null);
   106    }
   107  
   108    @watchRecord('allocation') watchNext;
   109  
   110    @observes('model.nextAllocation.clientStatus')
   111    observeWatchNext() {
   112      const nextAllocation = this.model.nextAllocation;
   113      if (nextAllocation && nextAllocation.content) {
   114        this.watchNext.perform(nextAllocation);
   115      } else {
   116        this.watchNext.cancelAll();
   117      }
   118    }
   119  
   120    @task(function* () {
   121      try {
   122        yield this.model.stop();
   123        // Eagerly update the allocation clientStatus to avoid flickering
   124        this.model.set('clientStatus', 'complete');
   125      } catch (err) {
   126        this.set('error', {
   127          title: 'Could Not Stop Allocation',
   128          description: messageForError(err, 'manage allocation lifecycle'),
   129        });
   130      }
   131    })
   132    stopAllocation;
   133  
   134    @task(function* () {
   135      try {
   136        yield this.model.restart();
   137      } catch (err) {
   138        this.set('error', {
   139          title: 'Could Not Restart Allocation',
   140          description: messageForError(err, 'manage allocation lifecycle'),
   141        });
   142      }
   143    })
   144    restartAllocation;
   145  
   146    @task(function* () {
   147      try {
   148        yield this.model.restartAll();
   149      } catch (err) {
   150        this.set('error', {
   151          title: 'Could Not Restart All Tasks',
   152          description: messageForError(err, 'manage allocation lifecycle'),
   153        });
   154        console.error(err);
   155      }
   156    })
   157    restartAll;
   158  
   159    @action
   160    gotoTask(allocation, task) {
   161      this.transitionToRoute('allocations.allocation.task', task);
   162    }
   163  
   164    @action
   165    taskClick(allocation, task, event) {
   166      lazyClick([() => this.send('gotoTask', allocation, task), event]);
   167    }
   168  
   169    //#region Services
   170  
   171    @tracked activeServiceID = null;
   172  
   173    @action handleServiceClick(service) {
   174      this.set('activeServiceID', service.refID);
   175    }
   176  
   177    @computed('activeServiceID', 'services')
   178    get activeService() {
   179      return this.services.findBy('refID', this.activeServiceID);
   180    }
   181  
   182    @action closeSidebar() {
   183      this.set('activeServiceID', null);
   184    }
   185  
   186    keyCommands = [
   187      {
   188        label: 'Close Evaluations Sidebar',
   189        pattern: ['Escape'],
   190        action: () => this.closeSidebar(),
   191      },
   192    ];
   193  
   194    //#endregion Services
   195  }