open-nomad/ui/app/templates/allocations/allocation/index.hbs
Luiz Aoqui 31ab7964bd
ui: task lifecycle restart all tasks (#14223)
Now that tasks that have finished running can be restarted, the UI needs
to use the actual task state to determine which CSS class to use when
rendering the task lifecycle chart element.
2022-08-24 18:43:44 -04:00

486 lines
14 KiB
Handlebars

{{page-title "Allocation " this.model.name}}
<AllocationSubnav @allocation={{this.model}} />
<section class="section">
{{#if this.error}}
<div data-test-inline-error class="notification is-danger">
<div class="columns">
<div class="column">
<h3 data-test-inline-error-title class="title is-4">
{{this.error.title}}
</h3>
<p data-test-inline-error-body>
{{this.error.description}}
</p>
</div>
<div class="column is-centered is-minimum">
<button
data-test-inline-error-close
class="button is-danger"
onclick={{action this.onDismiss}}
type="button"
>
Okay
</button>
</div>
</div>
</div>
{{/if}}
<h1 data-test-title class="title with-headroom with-flex">
<div>
Allocation
{{this.model.name}}
<span class="bumper-left tag {{this.model.statusClass}}">
{{this.model.clientStatus}}
</span>
</div>
<div>
{{#if this.model.isRunning}}
<div class="two-step-button">
<Exec::OpenButton
@job={{this.model.job}}
@allocation={{this.model}}
/>
</div>
<TwoStepButton
data-test-stop
@alignRight={{true}}
@idleText="Stop Alloc"
@cancelText="Cancel Stop"
@confirmText="Yes, Stop Alloc"
@confirmationMessage="Are you sure? This will reschedule the allocation on a different client."
@awaitingConfirmation={{this.stopAllocation.isRunning}}
@disabled={{or
this.stopAllocation.isRunning
this.restartAllocation.isRunning
}}
@onConfirm={{perform this.stopAllocation}}
/>
<TwoStepButton
data-test-restart
@alignRight={{true}}
@idleText="Restart Alloc"
@cancelText="Cancel Restart"
@confirmText="Yes, Restart Alloc"
@confirmationMessage="Are you sure? This will restart the tasks that are currently running in-place."
@awaitingConfirmation={{this.restartAllocation.isRunning}}
@disabled={{or
this.stopAllocation.isRunning
this.restartAllocation.isRunning
}}
@onConfirm={{perform this.restartAllocation}}
/>
<TwoStepButton
data-test-restart-all
@alignRight={{true}}
@idleText="Restart All Tasks"
@cancelText="Cancel Restart"
@confirmText="Yes, Restart All Tasks"
@confirmationMessage="Are you sure? This will restart all tasks in-place."
@awaitingConfirmation={{this.restartAllocation.isRunning}}
@disabled={{or
this.stopAllocation.isRunning
this.restartAllocation.isRunning
}}
@onConfirm={{perform this.restartAll}}
/>
{{/if}}
</div>
</h1>
<span class="tag is-hollow is-small is-alone no-text-transform">
{{this.model.id}}
<CopyButton @clipboardText={{this.model.id}} />
</span>
<div class="boxed-section is-small">
<div
data-test-allocation-details
class="boxed-section-body inline-definitions"
>
<span class="label">
Allocation Details
</span>
<span class="pair job-link">
<span class="term">
Job
</span>
<LinkTo
@route="jobs.job"
@model={{format-job-id this.model.job.id}}
data-test-job-link
>
{{this.model.job.name}}
</LinkTo>
</span>
<span class="pair node-link">
<span class="term">
Client
</span>
<LinkTo
@route="clients.client"
@model={{this.model.node}}
data-test-client-link
>
{{this.model.node.shortId}}
</LinkTo>
</span>
</div>
</div>
<div class="boxed-section">
<div class="boxed-section-head is-hollow">
Resource Utilization
</div>
<div class="boxed-section-body">
{{#if this.model.isRunning}}
<div class="columns">
<div class="column">
<PrimaryMetric::Allocation
@allocation={{this.model}}
@metric="cpu"
/>
</div>
<div class="column">
<PrimaryMetric::Allocation
@allocation={{this.model}}
@metric="memory"
/>
</div>
</div>
{{else}}
<div data-test-resource-error class="empty-message">
<h3 data-test-resource-error-headline class="empty-message-headline">
Allocation isn't running
</h3>
<p class="empty-message-body">
Only running allocations utilize
resources.
</p>
</div>
{{/if}}
</div>
</div>
<LifecycleChart @taskStates={{this.model.states}} />
<div class="boxed-section">
<div class="boxed-section-head">
Tasks
</div>
<div
class="boxed-section-body {{if this.sortedStates.length "is-full-bleed"}}"
>
{{#if this.sortedStates.length}}
<ListTable
@source={{this.sortedStates}}
@sortProperty={{this.sortProperty}}
@sortDescending={{this.sortDescending}}
@class="is-striped" as |t|
>
<t.head>
<th class="is-narrow"></th>
<t.sort-by @prop="name">
Name
</t.sort-by>
<t.sort-by @prop="state">
State
</t.sort-by>
<th>
Last Event
</th>
<t.sort-by @prop="events.lastObject.time">
Time
</t.sort-by>
<th>
Volumes
</th>
<th>
CPU
</th>
<th>
Memory
</th>
</t.head>
<t.body as |row|>
<TaskRow
{{keyboard-shortcut
enumerated=true
action=(action "taskClick" row.model.allocation row.model)
}}
@data-test-task-row={{row.model.name}}
@task={{row.model}}
@onClick={{action "taskClick" row.model.allocation row.model}}
/>
</t.body>
</ListTable>
{{else}}
<div data-test-empty-tasks-list class="empty-message">
<h3
data-test-empty-tasks-list-headline
class="empty-message-headline"
>
No Tasks
</h3>
<p data-test-empty-tasks-list-body class="empty-message-body">
Allocations will not have tasks until they are in a running state.
</p>
</div>
{{/if}}
</div>
</div>
{{#if this.ports.length}}
<div class="boxed-section" data-test-allocation-ports>
<div class="boxed-section-head">
Ports
</div>
<div class="boxed-section-body is-full-bleed">
<ListTable @source={{this.ports}} as |t|>
<t.head>
<th>
Name
</th>
<th>
Host Address
</th>
<th>
Mapped Port
</th>
</t.head>
<t.body as |row|>
<tr data-test-allocation-port>
<td data-test-allocation-port-name>
{{row.model.label}}
</td>
<td data-test-allocation-port-address>
<a
href="http://{{row.model.hostIp}}:{{row.model.value}}"
target="_blank"
rel="noopener noreferrer"
>
{{row.model.hostIp}}:{{row.model.value}}
</a>
</td>
<td data-test-allocation-port-to>
{{row.model.to}}
</td>
</tr>
</t.body>
</ListTable>
</div>
</div>
{{/if}}
{{#if this.services.length}}
<div class="boxed-section">
<div class="boxed-section-head">
Services
</div>
<div class="boxed-section-body is-full-bleed">
<ListTable @source={{this.services}} as |t|>
<t.head>
<th class="is-2">
Name
</th>
<th class="is-1">
Port
</th>
<td>
Tags
</td>
<td>
On Update
</td>
<td>
Connect?
</td>
<td>
Upstreams
</td>
</t.head>
<t.body as |row|>
<tr data-test-service>
<td data-test-service-name>
{{row.model.name}}
</td>
<td data-test-service-port>
{{row.model.portLabel}}
</td>
<td data-test-service-tags class="is-long-text">
{{join ", " row.model.tags}}
</td>
<td data-test-service-onupdate>
{{row.model.onUpdate}}
</td>
<td data-test-service-connect>
{{if row.model.connect "Yes" "No"}}
</td>
<td data-test-service-upstreams>
{{#each
row.model.connect.sidecarService.proxy.upstreams as |upstream|
}}
{{upstream.destinationName}}:{{upstream.localBindPort}}
{{/each}}
</td>
</tr>
</t.body>
</ListTable>
</div>
</div>
{{/if}}
{{#if this.model.hasRescheduleEvents}}
<div class="boxed-section" data-test-reschedule-events>
<div class="boxed-section-head is-hollow">
Reschedule Events
</div>
<div class="boxed-section-body">
<RescheduleEventTimeline @allocation={{this.model}} />
</div>
</div>
{{/if}}
{{#if this.model.wasPreempted}}
<div class="boxed-section is-warning" data-test-was-preempted>
<div class="boxed-section-head">
Preempted By
</div>
<div class="boxed-section-body">
{{#if this.preempter}}
<div class="boxed-section is-small">
<div class="boxed-section-body inline-definitions">
<span class="pair">
<span
data-test-allocation-status
class="tag {{this.preempter.statusClass}}"
>
{{this.preempter.clientStatus}}
</span>
</span>
<span class="pair">
<span class="term" data-test-allocation-name>
{{this.preempter.name}}
</span>
<LinkTo
@route="allocations.allocation"
@model={{this.preempter}}
data-test-allocation-id
>
{{this.preempter.shortId}}
</LinkTo>
</span>
<span class="pair job-link">
<span class="term">
Job
</span>
<LinkTo
@route="jobs.job"
@model={{this.preempter.job}}
data-test-job-link
>
{{this.preempter.job.name}}
</LinkTo>
</span>
<span class="pair job-priority">
<span class="term">
Priority
</span>
<span data-test-job-priority>
{{this.preempter.job.priority}}
</span>
</span>
<span class="pair node-link">
<span class="term">
Client
</span>
<LinkTo
@route="clients.client"
@model={{this.preempter.node}}
data-test-client-link
>
{{this.preempter.node.shortId}}
</LinkTo>
</span>
<span class="pair">
<span class="term">
Reserved CPU
</span>
<span data-test-allocation-cpu>
{{format-scheduled-hertz this.preempter.resources.cpu}}
</span>
</span>
<span class="pair">
<span class="term">
Reserved Memory
</span>
<span data-test-allocation-memory>
{{format-scheduled-bytes
this.preempter.resources.memory
start="MiB"
}}
</span>
</span>
</div>
</div>
{{else}}
<div class="empty-message">
<h3 class="empty-message-headline">
Allocation is gone
</h3>
<p class="empty-message-body">
This allocation has been stopped and
garbage collected.
</p>
</div>
{{/if}}
</div>
</div>
{{/if}}
{{#if
(and
this.model.preemptedAllocations.isFulfilled
this.model.preemptedAllocations.length
)
}}
<div class="boxed-section" data-test-preemptions>
<div class="boxed-section-head">
Preempted Allocations
</div>
<div class="boxed-section-body">
<ListTable
@source={{this.model.preemptedAllocations}}
@class="allocations is-isolated" as |t|
>
<t.head>
<th class="is-narrow"></th>
<th>
ID
</th>
<th>
Task Group
</th>
<th>
Created
</th>
<th>
Modified
</th>
<th>
Status
</th>
<th>
Version
</th>
<th>
Node
</th>
<th>
CPU
</th>
<th>
Memory
</th>
</t.head>
<t.body as |row|>
<AllocationRow
@allocation={{row.model}}
@context="job"
@data-test-allocation={{row.model.id}}
/>
</t.body>
</ListTable>
</div>
</div>
{{/if}}
</section>