Skip to content

Commit e46216a

Browse files
authored
Allow user to stop failed instances from console (#2482)
1 parent 0d897ef commit e46216a

File tree

2 files changed

+31
-54
lines changed

2 files changed

+31
-54
lines changed

app/api/util.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ const instanceActions: Record<string, InstanceState[]> = {
101101
// https://github.com/oxidecomputer/propolis/blob/b278193/bin/propolis-server/src/lib/vm/request_queue.rs
102102
// https://github.com/oxidecomputer/console/pull/2387#discussion_r1722368236
103103
reboot: ['running'], // technically rebooting allowed but too weird to say it
104-
stop: ['running', 'starting', 'rebooting'],
104+
// stopping a failed disk: https://github.com/oxidecomputer/omicron/blob/f0b804818b898bebdb317ac2b000618944c02457/nexus/src/app/instance.rs#L818-L830
105+
stop: ['running', 'starting', 'rebooting', 'failed'],
105106

106107
// NoVmm maps to to Stopped:
107108
// https://github.com/oxidecomputer/omicron/blob/6dd9802/nexus/db-model/src/instance_state.rs#L55

test/e2e/instance.e2e.ts

Lines changed: 29 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8-
import { clickRowAction, expect, expectRowVisible, test } from './utils'
8+
import { clickRowAction, expect, expectRowVisible, test, type Page } from './utils'
9+
10+
const expectInstanceState = async (page: Page, instance: string, state: string) => {
11+
await expectRowVisible(page.getByRole('table'), {
12+
name: instance,
13+
state: expect.stringContaining(state),
14+
})
15+
}
916

1017
test('can delete a failed instance', async ({ page }) => {
1118
await page.goto('/projects/mock-project/instances')
@@ -14,12 +21,7 @@ test('can delete a failed instance', async ({ page }) => {
1421

1522
const cell = page.getByRole('cell', { name: 'you-fail' })
1623
await expect(cell).toBeVisible() // just to match hidden check at the end
17-
18-
const table = page.getByRole('table')
19-
await expectRowVisible(table, {
20-
name: 'you-fail',
21-
state: expect.stringContaining('failed'),
22-
})
24+
expectInstanceState(page, 'you-fail', 'failed')
2325

2426
await clickRowAction(page, 'you-fail', 'Delete')
2527
await page.getByRole('button', { name: 'Confirm' }).click()
@@ -42,28 +44,25 @@ test('can start a failed instance', async ({ page }) => {
4244
await page.keyboard.press('Escape') // get out of the menu
4345

4446
// now start the failed one
45-
const table = page.getByRole('table')
46-
await expectRowVisible(table, {
47-
name: 'you-fail',
48-
state: expect.stringContaining('failed'),
49-
})
50-
47+
await expectInstanceState(page, 'you-fail', 'failed')
5148
await clickRowAction(page, 'you-fail', 'Start')
49+
await expectInstanceState(page, 'you-fail', 'starting')
50+
})
5251

53-
await expectRowVisible(table, {
54-
name: 'you-fail',
55-
state: expect.stringContaining('starting'),
56-
})
52+
test('can stop a failed instance', async ({ page }) => {
53+
await page.goto('/projects/mock-project/instances')
54+
await expect(page).toHaveTitle('Instances / mock-project / Oxide Console')
55+
await expectInstanceState(page, 'you-fail', 'failed')
56+
await clickRowAction(page, 'you-fail', 'Stop')
57+
await page.getByRole('button', { name: 'Confirm' }).click()
58+
await expectInstanceState(page, 'you-fail', 'stopping')
59+
await expectInstanceState(page, 'you-fail', 'stopped')
5760
})
5861

5962
test('can stop and delete a running instance', async ({ page }) => {
6063
await page.goto('/projects/mock-project/instances')
6164

62-
const table = page.getByRole('table')
63-
await expectRowVisible(table, {
64-
name: 'db1',
65-
state: expect.stringContaining('running'),
66-
})
65+
await expectInstanceState(page, 'db1', 'running')
6766
const row = page.getByRole('row', { name: 'db1', exact: false })
6867

6968
// can't delete, can stop
@@ -73,14 +72,8 @@ test('can stop and delete a running instance', async ({ page }) => {
7372
await page.getByRole('button', { name: 'Confirm' }).click()
7473

7574
// polling makes it go stopping and then stopped
76-
await expectRowVisible(table, {
77-
name: 'db1',
78-
state: expect.stringContaining('stopping'),
79-
})
80-
await expectRowVisible(table, {
81-
name: 'db1',
82-
state: expect.stringContaining('stopped'),
83-
})
75+
await expectInstanceState(page, 'db1', 'stopping')
76+
await expectInstanceState(page, 'db1', 'stopped')
8477

8578
// now delete
8679
await clickRowAction(page, 'db1', 'Delete')
@@ -91,34 +84,17 @@ test('can stop and delete a running instance', async ({ page }) => {
9184

9285
test('can stop a starting instance, then start it again', async ({ page }) => {
9386
await page.goto('/projects/mock-project/instances')
87+
await expect(page).toHaveTitle('Instances / mock-project / Oxide Console')
9488

95-
const table = page.getByRole('table')
96-
await expectRowVisible(table, {
97-
name: 'not-there-yet',
98-
state: expect.stringContaining('starting'),
99-
})
100-
89+
await expectInstanceState(page, 'not-there-yet', 'starting')
10190
await clickRowAction(page, 'not-there-yet', 'Stop')
10291
await page.getByRole('button', { name: 'Confirm' }).click()
103-
104-
await expectRowVisible(table, {
105-
name: 'not-there-yet',
106-
state: expect.stringContaining('stopping'),
107-
})
108-
await expectRowVisible(table, {
109-
name: 'not-there-yet',
110-
state: expect.stringContaining('stopped'),
111-
})
92+
await expectInstanceState(page, 'not-there-yet', 'stopping')
93+
await expectInstanceState(page, 'not-there-yet', 'stopped')
11294

11395
await clickRowAction(page, 'not-there-yet', 'Start')
114-
await expectRowVisible(table, {
115-
name: 'not-there-yet',
116-
state: expect.stringContaining('starting'),
117-
})
118-
await expectRowVisible(table, {
119-
name: 'not-there-yet',
120-
state: expect.stringContaining('running'),
121-
})
96+
await expectInstanceState(page, 'not-there-yet', 'starting')
97+
await expectInstanceState(page, 'not-there-yet', 'running')
12298
})
12399

124100
test('delete from instance detail', async ({ page }) => {

0 commit comments

Comments
 (0)