github.com/hernad/nomad@v1.6.112/ui/mirage/factories/allocation.js (about)

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