diff --git a/.changelog/14223.txt b/.changelog/14223.txt
new file mode 100644
index 00000000000..e8fceaa7c1c
--- /dev/null
+++ b/.changelog/14223.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: Add button to restart all tasks in an allocation.
+```
diff --git a/ui/app/adapters/allocation.js b/ui/app/adapters/allocation.js
index 20cb6d4f5a5..63477d80c22 100644
--- a/ui/app/adapters/allocation.js
+++ b/ui/app/adapters/allocation.js
@@ -14,6 +14,12 @@ export default class AllocationAdapter extends Watchable {
});
}
+ restartAll(allocation) {
+ const prefix = `${this.host || '/'}${this.urlPrefix()}`;
+ const url = `${prefix}/client/allocation/${allocation.id}/restart`;
+ return this.ajax(url, 'PUT', { data: { AllTasks: true } });
+ }
+
ls(model, path) {
return this.token
.authorizedRequest(
diff --git a/ui/app/components/lifecycle-chart-row.js b/ui/app/components/lifecycle-chart-row.js
index 25203683b32..8da916203ec 100644
--- a/ui/app/components/lifecycle-chart-row.js
+++ b/ui/app/components/lifecycle-chart-row.js
@@ -15,9 +15,9 @@ export default class LifecycleChartRow extends Component {
return undefined;
}
- @computed('taskState.finishedAt')
+ @computed('taskState.state')
get finishedClass() {
- if (this.taskState && this.taskState.finishedAt) {
+ if (this.taskState && this.taskState.state === 'dead') {
return 'is-finished';
}
diff --git a/ui/app/controllers/allocations/allocation/index.js b/ui/app/controllers/allocations/allocation/index.js
index 7df114346a4..85bc72e12e6 100644
--- a/ui/app/controllers/allocations/allocation/index.js
+++ b/ui/app/controllers/allocations/allocation/index.js
@@ -109,6 +109,19 @@ export default class IndexController extends Controller.extend(Sortable) {
})
restartAllocation;
+ @task(function* () {
+ try {
+ yield this.model.restartAll();
+ } catch (err) {
+ this.set('error', {
+ title: 'Could Not Restart All Tasks',
+ description: messageForError(err, 'manage allocation lifecycle'),
+ });
+ console.error(err);
+ }
+ })
+ restartAll;
+
@action
gotoTask(allocation, task) {
this.transitionToRoute('allocations.allocation.task', task);
diff --git a/ui/app/models/allocation.js b/ui/app/models/allocation.js
index 777ab40b519..6c66dd46e11 100644
--- a/ui/app/models/allocation.js
+++ b/ui/app/models/allocation.js
@@ -157,6 +157,10 @@ export default class Allocation extends Model {
return this.store.adapterFor('allocation').restart(this, taskName);
}
+ restartAll() {
+ return this.store.adapterFor('allocation').restartAll(this);
+ }
+
ls(path) {
return this.store.adapterFor('allocation').ls(this, path);
}
diff --git a/ui/app/templates/allocations/allocation/index.hbs b/ui/app/templates/allocations/allocation/index.hbs
index 7ebec44e7c5..8ccb11d87d1 100644
--- a/ui/app/templates/allocations/allocation/index.hbs
+++ b/ui/app/templates/allocations/allocation/index.hbs
@@ -61,7 +61,7 @@
@idleText="Restart Alloc"
@cancelText="Cancel Restart"
@confirmText="Yes, Restart Alloc"
- @confirmationMessage="Are you sure? This will restart the allocation in-place."
+ @confirmationMessage="Are you sure? This will restart the tasks that are currently running in-place."
@awaitingConfirmation={{this.restartAllocation.isRunning}}
@disabled={{or
this.stopAllocation.isRunning
@@ -69,6 +69,20 @@
}}
@onConfirm={{perform this.restartAllocation}}
/>
+
{{/if}}
@@ -184,7 +198,7 @@
{
assert.ok(Allocation.stop.isRunning, 'Stop is loading');
assert.ok(Allocation.restart.isDisabled, 'Restart is disabled');
+ assert.ok(Allocation.restartAll.isDisabled, 'Restart All is disabled');
server.pretender.resolve(server.pretender.requestReferences[0].request);
}, 500);
@@ -478,6 +492,7 @@ module('Acceptance | allocation detail (not running)', function (hooks) {
assert.notOk(Allocation.execButton.isPresent);
assert.notOk(Allocation.stop.isPresent);
assert.notOk(Allocation.restart.isPresent);
+ assert.notOk(Allocation.restartAll.isPresent);
});
});
diff --git a/ui/tests/integration/components/lifecycle-chart-test.js b/ui/tests/integration/components/lifecycle-chart-test.js
index d9ab57a27c6..f5cc8c41157 100644
--- a/ui/tests/integration/components/lifecycle-chart-test.js
+++ b/ui/tests/integration/components/lifecycle-chart-test.js
@@ -146,6 +146,7 @@ module('Integration | Component | lifecycle-chart', function (hooks) {
);
this.set('taskStates.4.finishedAt', new Date());
+ this.set('taskStates.4.state', 'dead');
await settled();
assert.ok(Chart.tasks[5].isFinished);
diff --git a/ui/tests/pages/allocations/detail.js b/ui/tests/pages/allocations/detail.js
index 5ad69151f35..bd1f95b8dfb 100644
--- a/ui/tests/pages/allocations/detail.js
+++ b/ui/tests/pages/allocations/detail.js
@@ -19,6 +19,7 @@ export default create({
stop: twoStepButton('[data-test-stop]'),
restart: twoStepButton('[data-test-restart]'),
+ restartAll: twoStepButton('[data-test-restart-all]'),
execButton: {
scope: '[data-test-exec-button]',