import Ember from 'ember'; import { Factory, trait } from 'ember-cli-mirage'; import faker from 'nomad-ui/mirage/faker'; import { provide, pickOne } from '../utils'; import { DATACENTERS } from '../common'; const EVAL_TYPES = ['system', 'service', 'batch']; const EVAL_STATUSES = ['pending', 'complete', 'failed', 'canceled']; const EVAL_TRIGGERED_BY = [ 'job-register', 'job-deregister', 'periodic-job', 'node-update', 'scheduled', 'rolling-update', 'deployment-watcher', 'failed-follow-up', 'max-plan-attempts', ]; const REF_TIME = new Date(); const generateCountMap = (keysCount, list) => () => { const sample = Array(keysCount) .fill(null) .map(() => pickOne(list)) .uniq(); return sample.reduce((hash, key) => { hash[key] = faker.random.number({ min: 1, max: 5 }); return hash; }, {}); }; const generateNodesAvailable = generateCountMap(5, DATACENTERS); const generateClassFiltered = generateCountMap(3, provide(10, faker.hacker.abbreviation)); const generateClassExhausted = generateClassFiltered; const generateDimensionExhausted = generateCountMap(1, ['cpu', 'mem', 'disk', 'iops']); const generateQuotaExhausted = generateDimensionExhausted; const generateScores = generateCountMap(1, ['binpack', 'job-anti-affinity']); const generateConstraintFiltered = generateCountMap(2, [ 'prop = val', 'driver = docker', 'arch = x64', ]); export default Factory.extend({ id: () => faker.random.uuid(), priority: () => faker.random.number(100), type: () => faker.helpers.randomize(EVAL_TYPES), triggeredBy: () => faker.helpers.randomize(EVAL_TRIGGERED_BY), status: () => faker.helpers.randomize(EVAL_STATUSES), statusDescription: () => faker.lorem.sentence(), failedTGAllocs: null, modifyIndex: () => faker.random.number({ min: 10, max: 2000 }), modifyTime: () => faker.date.past(2 / 365, REF_TIME) * 1000000, createIndex: () => faker.random.number({ min: 10, max: 2000 }), createTime() { return faker.date.past(2 / 365, new Date(this.modifyTime / 1000000)) * 1000000; }, waitUntil: null, withPlacementFailures: trait({ status: 'blocked', afterCreate(evaluation, server) { assignJob(evaluation, server); const taskGroups = server.db.taskGroups.where({ jobId: evaluation.jobId }); const taskGroupNames = taskGroups.mapBy('name'); const failedTaskGroupsCount = faker.random.number({ min: 1, max: taskGroupNames.length }); const failedTaskGroupNames = []; for (let i = 0; i < failedTaskGroupsCount; i++) { failedTaskGroupNames.push( ...taskGroupNames.splice(faker.random.number(taskGroupNames.length - 1), 1) ); } const placementFailures = failedTaskGroupNames.reduce((hash, name) => { hash[name] = generateTaskGroupFailures(); return hash; }, {}); evaluation.update({ failedTGAllocs: placementFailures, }); }, }), afterCreate(evaluation, server) { if (!evaluation.nodeId) { assignJob(evaluation, server); } }, }); function assignJob(evaluation, server) { Ember.assert( '[Mirage] No jobs! make sure jobs are created before evaluations', server.db.jobs.length ); const job = evaluation.jobId ? server.db.jobs.find(evaluation.jobId) : pickOne(server.db.jobs); evaluation.update({ jobId: job.id, }); } export function generateTaskGroupFailures() { return { CoalescedFailures: faker.random.number({ min: 1, max: 20 }), NodesEvaluated: faker.random.number({ min: 1, max: 100 }), NodesExhausted: faker.random.number({ min: 1, max: 100 }), NodesAvailable: faker.random.number(10) >= 7 ? generateNodesAvailable() : null, ClassFiltered: faker.random.number(10) >= 7 ? generateClassFiltered() : null, ConstraintFiltered: faker.random.number(10) >= 7 ? generateConstraintFiltered() : null, ClassExhausted: faker.random.number(10) >= 7 ? generateClassExhausted() : null, DimensionExhausted: faker.random.number(10) >= 7 ? generateDimensionExhausted() : null, QuotaExhausted: faker.random.number(10) >= 7 ? generateQuotaExhausted() : null, Scores: faker.random.number(10) >= 7 ? generateScores() : null, }; }