github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/mirage/factories/allocation.js (about) 1 import Ember from 'ember'; 2 import moment from 'moment'; 3 import { Factory, trait } from 'ember-cli-mirage'; 4 import faker from 'nomad-ui/mirage/faker'; 5 import { provide, pickOne } from '../utils'; 6 import { generateResources } from '../common'; 7 8 const UUIDS = provide(100, faker.random.uuid.bind(faker.random)); 9 const CLIENT_STATUSES = ['pending', 'running', 'complete', 'failed', 'lost']; 10 const DESIRED_STATUSES = ['run', 'stop', 'evict']; 11 const REF_TIME = new Date(); 12 13 export default Factory.extend({ 14 id: (i) => (i >= 100 ? `${UUIDS[i % 100]}-${i}` : UUIDS[i]), 15 16 jobVersion: 1, 17 18 modifyIndex: () => faker.random.number({ min: 10, max: 2000 }), 19 modifyTime: () => faker.date.past(2 / 365, REF_TIME) * 1000000, 20 21 createIndex: () => faker.random.number({ min: 10, max: 2000 }), 22 createTime() { 23 return ( 24 faker.date.past(2 / 365, new Date(this.modifyTime / 1000000)) * 1000000 25 ); 26 }, 27 28 namespace: null, 29 30 clientStatus() { 31 return this.forceRunningClientStatus 32 ? 'running' 33 : faker.helpers.randomize(CLIENT_STATUSES); 34 }, 35 36 desiredStatus: () => faker.helpers.randomize(DESIRED_STATUSES), 37 38 // When true, doesn't create any resources, state, or events 39 shallow: false, 40 41 // When true, sets the client status to running 42 forceRunningClientStatus: false, 43 44 withTaskWithPorts: trait({ 45 afterCreate(allocation, server) { 46 const taskGroup = server.db.taskGroups.findBy({ 47 name: allocation.taskGroup, 48 }); 49 const resources = taskGroup.taskIds.map((id) => { 50 const task = server.db.tasks.find(id); 51 return server.create('task-resource', { 52 allocation, 53 name: task.name, 54 resources: generateResources({ 55 CPU: task.resources.CPU, 56 MemoryMB: task.resources.MemoryMB, 57 DiskMB: task.resources.DiskMB, 58 networks: { minPorts: 1 }, 59 }), 60 }); 61 }); 62 63 allocation.update({ taskResourceIds: resources.mapBy('id') }); 64 }, 65 }), 66 67 withoutTaskWithPorts: trait({ 68 afterCreate(allocation, server) { 69 const taskGroup = server.db.taskGroups.findBy({ 70 name: allocation.taskGroup, 71 }); 72 const resources = taskGroup.taskIds.map((id) => { 73 const task = server.db.tasks.find(id); 74 return server.create('task-resource', { 75 allocation, 76 name: task.name, 77 resources: generateResources({ 78 CPU: task.resources.CPU, 79 MemoryMB: task.resources.MemoryMB, 80 DiskMB: task.resources.DiskMB, 81 networks: { minPorts: 0, maxPorts: 0 }, 82 }), 83 }); 84 }); 85 86 allocation.update({ taskResourceIds: resources.mapBy('id') }); 87 }, 88 }), 89 90 rescheduleAttempts: 0, 91 rescheduleSuccess: false, 92 93 rescheduled: trait({ 94 // Create another allocation carrying the events of this as well as the reschduleSuccess state. 95 // Pass along rescheduleAttempts after decrementing. 96 // After rescheduleAttempts hits zero, a final allocation is made with no nextAllocation and 97 // a clientStatus of failed or running, depending on rescheduleSuccess 98 afterCreate(allocation, server) { 99 const attempts = allocation.rescheduleAttempts - 1; 100 const previousEvents = 101 (allocation.rescheduleTracker && allocation.rescheduleTracker.Events) || 102 []; 103 104 let rescheduleTime; 105 if (previousEvents.length) { 106 const lastEvent = previousEvents[previousEvents.length - 1]; 107 rescheduleTime = moment(lastEvent.RescheduleTime / 1000000).add( 108 5, 109 'minutes' 110 ); 111 } else { 112 rescheduleTime = faker.date.past(2 / 365, REF_TIME); 113 } 114 115 rescheduleTime *= 1000000; 116 117 const rescheduleTracker = { 118 Events: previousEvents.concat([ 119 { 120 PrevAllocID: allocation.id, 121 PrevNodeID: null, //allocation.node.id, 122 RescheduleTime: rescheduleTime, 123 }, 124 ]), 125 }; 126 127 let nextAllocation; 128 if (attempts > 0) { 129 nextAllocation = server.create('allocation', 'rescheduled', { 130 rescheduleAttempts: Math.max(attempts, 0), 131 rescheduleSuccess: allocation.rescheduleSuccess, 132 previousAllocation: allocation.id, 133 shallow: allocation.shallow, 134 clientStatus: 'failed', 135 rescheduleTracker, 136 followupEvalId: server.create('evaluation', { 137 waitUntil: rescheduleTime, 138 }).id, 139 }); 140 } else { 141 nextAllocation = server.create('allocation', { 142 previousAllocation: allocation.id, 143 clientStatus: allocation.rescheduleSuccess ? 'running' : 'failed', 144 shallow: allocation.shallow, 145 rescheduleTracker, 146 }); 147 } 148 149 allocation.update({ 150 nextAllocation: nextAllocation.id, 151 clientStatus: 'failed', 152 }); 153 }, 154 }), 155 156 preempted: trait({ 157 afterCreate(allocation, server) { 158 const preempter = server.create('allocation', { 159 preemptedAllocations: [allocation.id], 160 }); 161 allocation.update({ preemptedByAllocation: preempter.id }); 162 }, 163 }), 164 165 preempter: trait({ 166 afterCreate(allocation, server) { 167 const preempted = server.create('allocation', { 168 preemptedByAllocation: allocation.id, 169 }); 170 allocation.update({ preemptedAllocations: [preempted.id] }); 171 }, 172 }), 173 174 afterCreate(allocation, server) { 175 Ember.assert( 176 '[Mirage] No jobs! make sure jobs are created before allocations', 177 server.db.jobs.length 178 ); 179 Ember.assert( 180 '[Mirage] No nodes! make sure nodes are created before allocations', 181 server.db.nodes.length 182 ); 183 184 const job = allocation.jobId 185 ? server.db.jobs.find(allocation.jobId) 186 : pickOne(server.db.jobs); 187 const namespace = allocation.namespace || job.namespace; 188 const node = allocation.nodeId 189 ? server.db.nodes.find(allocation.nodeId) 190 : pickOne(server.db.nodes); 191 const taskGroup = allocation.taskGroup 192 ? server.db.taskGroups.findBy({ name: allocation.taskGroup }) 193 : pickOne(server.db.taskGroups.where({ jobId: job.id })); 194 195 allocation.update({ 196 namespace, 197 jobId: job.id, 198 nodeId: node.id, 199 taskStateIds: [], 200 taskResourceIds: [], 201 taskGroup: taskGroup.name, 202 name: allocation.name || `${taskGroup.name}.[${faker.random.number(10)}]`, 203 }); 204 205 if (!allocation.shallow) { 206 const states = taskGroup.taskIds.map((id) => 207 server.create('task-state', { 208 allocation, 209 name: server.db.tasks.find(id).name, 210 }) 211 ); 212 213 const resources = taskGroup.taskIds.map((id) => { 214 const task = server.db.tasks.find(id); 215 return server.create('task-resource', { 216 allocation, 217 name: task.name, 218 resources: task.originalResources, 219 }); 220 }); 221 222 allocation.update({ 223 taskStateIds: 224 allocation.clientStatus === 'pending' ? [] : states.mapBy('id'), 225 taskResourceIds: resources.mapBy('id'), 226 }); 227 228 // Each allocation has a corresponding allocation stats running on some client. 229 // Create that record, even though it's not a relationship. 230 server.create('client-allocation-stat', { 231 id: allocation.id, 232 _taskNames: states.mapBy('name'), 233 }); 234 } 235 }, 236 });