github.com/hernad/nomad@v1.6.112/ui/app/controllers/jobs/job/task-group.js (about) 1 /** 2 * Copyright (c) HashiCorp, Inc. 3 * SPDX-License-Identifier: MPL-2.0 4 */ 5 6 /* eslint-disable ember/no-incorrect-calls-with-inline-anonymous-functions */ 7 import { inject as service } from '@ember/service'; 8 import { alias, readOnly } from '@ember/object/computed'; 9 import Controller from '@ember/controller'; 10 import { action, computed, get } from '@ember/object'; 11 import { scheduleOnce } from '@ember/runloop'; 12 import intersection from 'lodash.intersection'; 13 import Sortable from 'nomad-ui/mixins/sortable'; 14 import Searchable from 'nomad-ui/mixins/searchable'; 15 import WithNamespaceResetting from 'nomad-ui/mixins/with-namespace-resetting'; 16 import { 17 serialize, 18 deserializedQueryParam as selection, 19 } from 'nomad-ui/utils/qp-serialize'; 20 import classic from 'ember-classic-decorator'; 21 import localStorageProperty from 'nomad-ui/utils/properties/local-storage'; 22 23 @classic 24 export default class TaskGroupController extends Controller.extend( 25 Sortable, 26 Searchable, 27 WithNamespaceResetting 28 ) { 29 @service userSettings; 30 @service can; 31 32 queryParams = [ 33 { 34 currentPage: 'page', 35 }, 36 { 37 searchTerm: 'search', 38 }, 39 { 40 sortProperty: 'sort', 41 }, 42 { 43 sortDescending: 'desc', 44 }, 45 { 46 qpStatus: 'status', 47 }, 48 { 49 qpClient: 'client', 50 }, 51 'activeTask', 52 ]; 53 54 currentPage = 1; 55 @readOnly('userSettings.pageSize') pageSize; 56 57 qpStatus = ''; 58 qpClient = ''; 59 sortProperty = 'modifyIndex'; 60 sortDescending = true; 61 activeTask = null; 62 63 @computed 64 get searchProps() { 65 return ['shortId', 'name']; 66 } 67 68 @localStorageProperty('nomadShowSubTasks', true) showSubTasks; 69 70 @action 71 toggleShowSubTasks(e) { 72 e.preventDefault(); 73 this.set('showSubTasks', !this.get('showSubTasks')); 74 } 75 76 @computed('model.allocations.[]') 77 get allocations() { 78 return this.get('model.allocations') || []; 79 } 80 81 @computed('allocations.[]', 'selectionStatus', 'selectionClient') 82 get filteredAllocations() { 83 const { selectionStatus, selectionClient } = this; 84 85 return this.allocations.filter((alloc) => { 86 if ( 87 selectionStatus.length && 88 !selectionStatus.includes(alloc.clientStatus) 89 ) { 90 return false; 91 } 92 if ( 93 selectionClient.length && 94 !selectionClient.includes(alloc.get('node.shortId')) 95 ) { 96 return false; 97 } 98 99 return true; 100 }); 101 } 102 103 @alias('filteredAllocations') listToSort; 104 @alias('listSorted') listToSearch; 105 @alias('listSearched') sortedAllocations; 106 107 @selection('qpStatus') selectionStatus; 108 @selection('qpClient') selectionClient; 109 110 @computed('model.scaleState.events.@each.time', function () { 111 const events = get(this, 'model.scaleState.events'); 112 if (events) { 113 return events.sortBy('time').reverse(); 114 } 115 return []; 116 }) 117 sortedScaleEvents; 118 119 @computed('sortedScaleEvents.@each.hasCount', function () { 120 const countEventsCount = this.sortedScaleEvents.filterBy('hasCount').length; 121 return ( 122 countEventsCount > 1 && 123 countEventsCount >= this.sortedScaleEvents.length / 2 124 ); 125 }) 126 shouldShowScaleEventTimeline; 127 128 @computed('model.job.{namespace,runningDeployment}') 129 get tooltipText() { 130 if ( 131 this.can.cannot('scale job', null, { 132 namespace: this.model.job.namespace.get('name'), 133 }) 134 ) 135 return "You aren't allowed to scale task groups"; 136 if (this.model.job.runningDeployment) 137 return 'You cannot scale task groups during a deployment'; 138 return undefined; 139 } 140 141 @action 142 gotoAllocation(allocation) { 143 this.transitionToRoute('allocations.allocation', allocation.id); 144 } 145 146 @action 147 scaleTaskGroup(count) { 148 return this.model.scale(count); 149 } 150 151 get optionsAllocationStatus() { 152 return [ 153 { key: 'pending', label: 'Pending' }, 154 { key: 'running', label: 'Running' }, 155 { key: 'complete', label: 'Complete' }, 156 { key: 'failed', label: 'Failed' }, 157 { key: 'lost', label: 'Lost' }, 158 { key: 'unknown', label: 'Unknown' }, 159 ]; 160 } 161 162 @computed('model.allocations.[]', 'selectionClient') 163 get optionsClients() { 164 const clients = Array.from( 165 new Set(this.model.allocations.mapBy('node.shortId')) 166 ).compact(); 167 168 // Update query param when the list of clients changes. 169 scheduleOnce('actions', () => { 170 // eslint-disable-next-line ember/no-side-effects 171 this.set( 172 'qpClient', 173 serialize(intersection(clients, this.selectionClient)) 174 ); 175 }); 176 177 return clients.sort().map((dc) => ({ key: dc, label: dc })); 178 } 179 180 setFacetQueryParam(queryParam, selection) { 181 this.set(queryParam, serialize(selection)); 182 } 183 184 get taskGroup() { 185 return this.model; 186 } 187 188 get breadcrumb() { 189 const { job, name } = this.taskGroup; 190 return { 191 title: 'Task Group', 192 label: name, 193 args: ['jobs.job.task-group', job, name], 194 }; 195 } 196 197 @action 198 setActiveTaskQueryParam(task) { 199 if (task) { 200 this.set('activeTask', `${task.allocation.id}-${task.name}`); 201 } else { 202 this.set('activeTask', null); 203 } 204 } 205 }