Merge pull request #14879 from hashicorp/mnomitch/job-purge-ui
Adds purge job button to UI
This commit is contained in:
commit
91d32bb8df
|
@ -29,6 +29,11 @@ export default class JobAdapter extends WatchableNamespaceIDs {
|
||||||
return this.ajax(url, 'DELETE');
|
return this.ajax(url, 'DELETE');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
purge(job) {
|
||||||
|
const url = this.urlForFindRecord(job.get('id'), 'job') + '?purge=true';
|
||||||
|
return this.ajax(url, 'DELETE');
|
||||||
|
}
|
||||||
|
|
||||||
parse(spec) {
|
parse(spec) {
|
||||||
const url = addToPath(this.urlForFindAll('job'), '/parse?namespace=*');
|
const url = addToPath(this.urlForFindAll('job'), '/parse?namespace=*');
|
||||||
return this.ajax(url, 'POST', {
|
return this.ajax(url, 'POST', {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import Component from '@ember/component';
|
import Component from '@ember/component';
|
||||||
import { task } from 'ember-concurrency';
|
import { task } from 'ember-concurrency';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
import messageFromAdapterError from 'nomad-ui/utils/message-from-adapter-error';
|
import messageFromAdapterError from 'nomad-ui/utils/message-from-adapter-error';
|
||||||
import { tagName } from '@ember-decorators/component';
|
import { tagName } from '@ember-decorators/component';
|
||||||
import classic from 'ember-classic-decorator';
|
import classic from 'ember-classic-decorator';
|
||||||
|
@ -7,6 +8,8 @@ import classic from 'ember-classic-decorator';
|
||||||
@classic
|
@classic
|
||||||
@tagName('')
|
@tagName('')
|
||||||
export default class Title extends Component {
|
export default class Title extends Component {
|
||||||
|
@service router;
|
||||||
|
|
||||||
job = null;
|
job = null;
|
||||||
title = null;
|
title = null;
|
||||||
|
|
||||||
|
@ -27,6 +30,27 @@ export default class Title extends Component {
|
||||||
})
|
})
|
||||||
stopJob;
|
stopJob;
|
||||||
|
|
||||||
|
@task(function* () {
|
||||||
|
try {
|
||||||
|
const job = this.job;
|
||||||
|
yield job.purge();
|
||||||
|
this.flashMessages.add({
|
||||||
|
title: 'Job Purged',
|
||||||
|
message: `You have purged ${this.job.name}`,
|
||||||
|
type: 'success',
|
||||||
|
destroyOnClick: false,
|
||||||
|
timeout: 5000,
|
||||||
|
});
|
||||||
|
this.router.transitionTo('jobs');
|
||||||
|
} catch (err) {
|
||||||
|
this.handleError({
|
||||||
|
title: 'Error purging job',
|
||||||
|
description: messageFromAdapterError(err, 'purge jobs'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
purgeJob;
|
||||||
|
|
||||||
@task(function* () {
|
@task(function* () {
|
||||||
const job = this.job;
|
const job = this.job;
|
||||||
const definition = yield job.fetchRawDefinition();
|
const definition = yield job.fetchRawDefinition();
|
||||||
|
|
|
@ -227,6 +227,10 @@ export default class Job extends Model {
|
||||||
return this.store.adapterFor('job').stop(this);
|
return this.store.adapterFor('job').stop(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
purge() {
|
||||||
|
return this.store.adapterFor('job').purge(this);
|
||||||
|
}
|
||||||
|
|
||||||
plan() {
|
plan() {
|
||||||
assert('A job must be parsed before planned', this._newDefinitionJSON);
|
assert('A job must be parsed before planned', this._newDefinitionJSON);
|
||||||
return this.store.adapterFor('job').plan(this);
|
return this.store.adapterFor('job').plan(this);
|
||||||
|
|
|
@ -25,6 +25,15 @@
|
||||||
@awaitingConfirmation={{this.stopJob.isRunning}}
|
@awaitingConfirmation={{this.stopJob.isRunning}}
|
||||||
@onConfirm={{perform this.stopJob}} />
|
@onConfirm={{perform this.stopJob}} />
|
||||||
{{else}}
|
{{else}}
|
||||||
|
<TwoStepButton
|
||||||
|
data-test-purge
|
||||||
|
@alignRight={{true}}
|
||||||
|
@idleText="Purge Job"
|
||||||
|
@cancelText="Cancel"
|
||||||
|
@confirmText="Yes, Purge Job"
|
||||||
|
@confirmationMessage="Are you sure? You cannot undo this action."
|
||||||
|
@awaitingConfirmation={{this.purgeJob.isRunning}}
|
||||||
|
@onConfirm={{perform this.purgeJob}} />
|
||||||
<TwoStepButton
|
<TwoStepButton
|
||||||
data-test-start
|
data-test-start
|
||||||
@alignRight={{true}}
|
@alignRight={{true}}
|
||||||
|
|
|
@ -102,10 +102,12 @@ export default function moduleForJob(
|
||||||
test('the title buttons are dependent on job status', async function (assert) {
|
test('the title buttons are dependent on job status', async function (assert) {
|
||||||
if (job.status === 'dead') {
|
if (job.status === 'dead') {
|
||||||
assert.ok(JobDetail.start.isPresent);
|
assert.ok(JobDetail.start.isPresent);
|
||||||
|
assert.ok(JobDetail.purge.isPresent);
|
||||||
assert.notOk(JobDetail.stop.isPresent);
|
assert.notOk(JobDetail.stop.isPresent);
|
||||||
assert.notOk(JobDetail.execButton.isPresent);
|
assert.notOk(JobDetail.execButton.isPresent);
|
||||||
} else {
|
} else {
|
||||||
assert.notOk(JobDetail.start.isPresent);
|
assert.notOk(JobDetail.start.isPresent);
|
||||||
|
assert.notOk(JobDetail.purge.isPresent);
|
||||||
assert.ok(JobDetail.stop.isPresent);
|
assert.ok(JobDetail.stop.isPresent);
|
||||||
assert.ok(JobDetail.execButton.isPresent);
|
assert.ok(JobDetail.execButton.isPresent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,11 @@ export async function startJob() {
|
||||||
await click('[data-test-start] [data-test-confirm-button]');
|
await click('[data-test-start] [data-test-confirm-button]');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function purgeJob() {
|
||||||
|
await click('[data-test-purge] [data-test-idle-button]');
|
||||||
|
await click('[data-test-purge] [data-test-confirm-button]');
|
||||||
|
}
|
||||||
|
|
||||||
export function expectStartRequest(assert, server, job) {
|
export function expectStartRequest(assert, server, job) {
|
||||||
const expectedURL = jobURL(job);
|
const expectedURL = jobURL(job);
|
||||||
const request = server.pretender.handledRequests
|
const request = server.pretender.handledRequests
|
||||||
|
@ -63,3 +68,14 @@ export function expectDeleteRequest(assert, server, job) {
|
||||||
'DELETE URL was made correctly'
|
'DELETE URL was made correctly'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function expectPurgeRequest(assert, server, job) {
|
||||||
|
const expectedURL = jobURL(job) + '?purge=true';
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
server.pretender.handledRequests
|
||||||
|
.filterBy('method', 'DELETE')
|
||||||
|
.find((req) => req.url === expectedURL),
|
||||||
|
'DELETE URL was made correctly'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -11,9 +11,11 @@ import {
|
||||||
jobURL,
|
jobURL,
|
||||||
stopJob,
|
stopJob,
|
||||||
startJob,
|
startJob,
|
||||||
|
purgeJob,
|
||||||
expectError,
|
expectError,
|
||||||
expectDeleteRequest,
|
expectDeleteRequest,
|
||||||
expectStartRequest,
|
expectStartRequest,
|
||||||
|
expectPurgeRequest,
|
||||||
} from './helpers';
|
} from './helpers';
|
||||||
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
|
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
|
||||||
|
|
||||||
|
@ -226,6 +228,25 @@ module('Integration | Component | job-page/periodic', function (hooks) {
|
||||||
await expectError(assert, 'Could Not Start Job');
|
await expectError(assert, 'Could Not Start Job');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Purging a job sends a purge request for the job', async function (assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
const mirageJob = this.server.create('job', 'periodic', {
|
||||||
|
childrenCount: 0,
|
||||||
|
createAllocations: false,
|
||||||
|
status: 'dead',
|
||||||
|
});
|
||||||
|
await this.store.findAll('job');
|
||||||
|
|
||||||
|
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
|
||||||
|
|
||||||
|
this.setProperties(commonProperties(job));
|
||||||
|
await render(commonTemplate);
|
||||||
|
|
||||||
|
await purgeJob();
|
||||||
|
expectPurgeRequest(assert, this.server, job);
|
||||||
|
});
|
||||||
|
|
||||||
test('Each job row includes the submitted time', async function (assert) {
|
test('Each job row includes the submitted time', async function (assert) {
|
||||||
this.server.create('job', 'periodic', {
|
this.server.create('job', 'periodic', {
|
||||||
id: 'parent',
|
id: 'parent',
|
||||||
|
|
|
@ -7,9 +7,11 @@ import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
|
||||||
import {
|
import {
|
||||||
startJob,
|
startJob,
|
||||||
stopJob,
|
stopJob,
|
||||||
|
purgeJob,
|
||||||
expectError,
|
expectError,
|
||||||
expectDeleteRequest,
|
expectDeleteRequest,
|
||||||
expectStartRequest,
|
expectStartRequest,
|
||||||
|
expectPurgeRequest,
|
||||||
} from './helpers';
|
} from './helpers';
|
||||||
import Job from 'nomad-ui/tests/pages/jobs/detail';
|
import Job from 'nomad-ui/tests/pages/jobs/detail';
|
||||||
import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
|
import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
|
||||||
|
@ -128,6 +130,21 @@ module('Integration | Component | job-page/service', function (hooks) {
|
||||||
await expectError(assert, 'Could Not Start Job');
|
await expectError(assert, 'Could Not Start Job');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Purging a job sends a purge request for the job', async function (assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
const mirageJob = makeMirageJob(this.server, { status: 'dead' });
|
||||||
|
await this.store.findAll('job');
|
||||||
|
|
||||||
|
const job = this.store.peekAll('job').findBy('plainId', mirageJob.id);
|
||||||
|
|
||||||
|
this.setProperties(commonProperties(job));
|
||||||
|
await render(commonTemplate);
|
||||||
|
|
||||||
|
await purgeJob();
|
||||||
|
expectPurgeRequest(assert, this.server, job);
|
||||||
|
});
|
||||||
|
|
||||||
test('Recent allocations shows allocations in the job context', async function (assert) {
|
test('Recent allocations shows allocations in the job context', async function (assert) {
|
||||||
assert.expect(3);
|
assert.expect(3);
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ export default create({
|
||||||
|
|
||||||
stop: twoStepButton('[data-test-stop]'),
|
stop: twoStepButton('[data-test-stop]'),
|
||||||
start: twoStepButton('[data-test-start]'),
|
start: twoStepButton('[data-test-start]'),
|
||||||
|
purge: twoStepButton('[data-test-purge]'),
|
||||||
|
|
||||||
packTag: isPresent('[data-test-pack-tag]'),
|
packTag: isPresent('[data-test-pack-tag]'),
|
||||||
metaTable: isPresent('[data-test-meta]'),
|
metaTable: isPresent('[data-test-meta]'),
|
||||||
|
|
|
@ -515,6 +515,20 @@ module('Unit | Adapter | Job', function (hooks) {
|
||||||
assert.equal(request.method, 'DELETE');
|
assert.equal(request.method, 'DELETE');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('purge requests include the activeRegion', async function (assert) {
|
||||||
|
const region = 'region-2';
|
||||||
|
const job = await this.initializeWithJob({ region });
|
||||||
|
|
||||||
|
await this.subject().purge(job);
|
||||||
|
|
||||||
|
const request = this.server.pretender.handledRequests[0];
|
||||||
|
assert.equal(
|
||||||
|
request.url,
|
||||||
|
`/v1/job/${job.plainId}?purge=true®ion=${region}`
|
||||||
|
);
|
||||||
|
assert.equal(request.method, 'DELETE');
|
||||||
|
});
|
||||||
|
|
||||||
test('parse requests include the activeRegion', async function (assert) {
|
test('parse requests include the activeRegion', async function (assert) {
|
||||||
const region = 'region-2';
|
const region = 'region-2';
|
||||||
await this.initializeUI({ region });
|
await this.initializeUI({ region });
|
||||||
|
|
Loading…
Reference in a new issue