github.com/zoomfoo/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/ui/app/models/allocation.js (about) 1 import { inject as service } from '@ember/service'; 2 import { computed } from '@ember/object'; 3 import Model from 'ember-data/model'; 4 import attr from 'ember-data/attr'; 5 import { belongsTo } from 'ember-data/relationships'; 6 import { fragment, fragmentArray } from 'ember-data-model-fragments/attributes'; 7 import intersection from 'lodash.intersection'; 8 import shortUUIDProperty from '../utils/properties/short-uuid'; 9 import AllocationStats from '../utils/classes/allocation-stats'; 10 11 const STATUS_ORDER = { 12 pending: 1, 13 running: 2, 14 complete: 3, 15 failed: 4, 16 lost: 5, 17 }; 18 19 export default Model.extend({ 20 token: service(), 21 22 shortId: shortUUIDProperty('id'), 23 job: belongsTo('job'), 24 node: belongsTo('node'), 25 name: attr('string'), 26 taskGroupName: attr('string'), 27 resources: fragment('resources'), 28 jobVersion: attr('number'), 29 30 modifyIndex: attr('number'), 31 modifyTime: attr('date'), 32 33 createIndex: attr('number'), 34 createTime: attr('date'), 35 36 clientStatus: attr('string'), 37 desiredStatus: attr('string'), 38 statusIndex: computed('clientStatus', function() { 39 return STATUS_ORDER[this.get('clientStatus')] || 100; 40 }), 41 42 // When allocations are server-side rescheduled, a paper trail 43 // is left linking all reschedule attempts. 44 previousAllocation: belongsTo('allocation', { inverse: 'nextAllocation' }), 45 nextAllocation: belongsTo('allocation', { inverse: 'previousAllocation' }), 46 47 followUpEvaluation: belongsTo('evaluation'), 48 49 statusClass: computed('clientStatus', function() { 50 const classMap = { 51 pending: 'is-pending', 52 running: 'is-primary', 53 complete: 'is-complete', 54 failed: 'is-error', 55 lost: 'is-light', 56 }; 57 58 return classMap[this.get('clientStatus')] || 'is-dark'; 59 }), 60 61 taskGroup: computed('taskGroupName', 'job.taskGroups.[]', function() { 62 const taskGroups = this.get('job.taskGroups'); 63 return taskGroups && taskGroups.findBy('name', this.get('taskGroupName')); 64 }), 65 66 unhealthyDrivers: computed('taskGroup.drivers.[]', 'node.unhealthyDriverNames.[]', function() { 67 const taskGroupUnhealthyDrivers = this.get('taskGroup.drivers'); 68 const nodeUnhealthyDrivers = this.get('node.unhealthyDriverNames'); 69 70 if (taskGroupUnhealthyDrivers && nodeUnhealthyDrivers) { 71 return intersection(taskGroupUnhealthyDrivers, nodeUnhealthyDrivers); 72 } 73 74 return []; 75 }), 76 77 fetchStats() { 78 return this.get('token') 79 .authorizedRequest(`/v1/client/allocation/${this.get('id')}/stats`) 80 .then(res => res.json()) 81 .then(json => { 82 return new AllocationStats({ 83 stats: json, 84 allocation: this, 85 }); 86 }); 87 }, 88 89 states: fragmentArray('task-state'), 90 rescheduleEvents: fragmentArray('reschedule-event'), 91 92 hasRescheduleEvents: computed('rescheduleEvents.length', 'nextAllocation', function() { 93 return this.get('rescheduleEvents.length') > 0 || this.get('nextAllocation'); 94 }), 95 96 hasStoppedRescheduling: computed( 97 'nextAllocation', 98 'clientStatus', 99 'followUpEvaluation', 100 function() { 101 return ( 102 !this.get('nextAllocation.content') && 103 !this.get('followUpEvaluation.content') && 104 this.get('clientStatus') === 'failed' 105 ); 106 } 107 ), 108 });