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 }