open-nomad/ui/app/adapters/job.js
Nicholas Cioli 4d9fa38a5e
ui: add parameterized dispatch interface (#10675)
* ui: add parameterized dispatch interface

This commit adds a new interface for dispatching parameteried jobs, if
the user has the right permissions. The UI can be accessed by viewing a
parameterized job and clicking on the "Dispatch Job" button located in
the "Job Launches" section.

* fix failing lint test

* clean up dispatch and remove meta

This commit cleans up a few things that had typos and
inconsistent naming. In line with this, the custom
`meta` view was removed in favor of using the
included `AttributesTable`.

* ui: encode dispatch job payload and start adding tests

* ui: remove unused test imports

* ui: redesign job dispatch form

* ui: initial acceptance tests for dispatch job

* ui: generate parameterized job children with correct id format

* ui: fix job dispatch breadcrumb link

* ui: refactor job dispatch component into glimmer component and add form validation

* ui: remove unused CSS class

* ui: align job dispatch button

* ui: handle namespace-specific requests on job dispatch

* ui: rename payloadMissing to payloadHasError

* ui: don't re-fetch job spec on dispatch job

* ui: keep overview tab selected on job dispatch page

* ui: fix task and task-group linting

* ui: URL encode job id on dispatch job tests

* ui: fix error when job meta is null

* ui: handle job dispatch from adapter

* ui: add more tests for dispatch job page

* ui: add "job dispatch" capability check

* ui: update job dispatch from code review

Co-authored-by: Luiz Aoqui <luiz@hashicorp.com>
2021-07-20 18:27:41 -04:00

99 lines
2.5 KiB
JavaScript

import WatchableNamespaceIDs from './watchable-namespace-ids';
import addToPath from 'nomad-ui/utils/add-to-path';
import { base64EncodeString } from 'nomad-ui/utils/encode';
export default class JobAdapter extends WatchableNamespaceIDs {
relationshipFallbackLinks = {
summary: '/summary',
};
fetchRawDefinition(job) {
const url = this.urlForFindRecord(job.get('id'), 'job');
return this.ajax(url, 'GET');
}
forcePeriodic(job) {
if (job.get('periodic')) {
const url = addToPath(this.urlForFindRecord(job.get('id'), 'job'), '/periodic/force');
return this.ajax(url, 'POST');
}
}
stop(job) {
const url = this.urlForFindRecord(job.get('id'), 'job');
return this.ajax(url, 'DELETE');
}
parse(spec) {
const url = addToPath(this.urlForFindAll('job'), '/parse');
return this.ajax(url, 'POST', {
data: {
JobHCL: spec,
Canonicalize: true,
},
});
}
plan(job) {
const jobId = job.get('id') || job.get('_idBeforeSaving');
const store = this.store;
const url = addToPath(this.urlForFindRecord(jobId, 'job'), '/plan');
return this.ajax(url, 'POST', {
data: {
Job: job.get('_newDefinitionJSON'),
Diff: true,
},
}).then(json => {
json.ID = jobId;
store.pushPayload('job-plan', { jobPlans: [json] });
return store.peekRecord('job-plan', jobId);
});
}
// Running a job doesn't follow REST create semantics so it's easier to
// treat it as an action.
run(job) {
return this.ajax(this.urlForCreateRecord('job'), 'POST', {
data: {
Job: job.get('_newDefinitionJSON'),
},
});
}
update(job) {
const jobId = job.get('id') || job.get('_idBeforeSaving');
return this.ajax(this.urlForUpdateRecord(jobId, 'job'), 'POST', {
data: {
Job: job.get('_newDefinitionJSON'),
},
});
}
scale(job, group, count, message) {
const url = addToPath(this.urlForFindRecord(job.get('id'), 'job'), '/scale');
return this.ajax(url, 'POST', {
data: {
Count: count,
Message: message,
Target: {
Group: group,
},
Meta: {
Source: 'nomad-ui',
},
},
});
}
dispatch(job, meta, payload) {
const url = addToPath(this.urlForFindRecord(job.get('id'), 'job'), '/dispatch');
return this.ajax(url, 'POST', {
data: {
Payload: base64EncodeString(payload),
Meta: meta,
},
});
}
}