From b0999761a87b69d7d6d1ac6441e5e808c4d2e030 Mon Sep 17 00:00:00 2001 From: David Crespo Date: Thu, 12 Sep 2024 15:56:35 -0500 Subject: [PATCH 1/2] allow user to start failed instance --- app/api/util.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/api/util.ts b/app/api/util.ts index 59b9f37f9..5d997c02c 100644 --- a/app/api/util.ts +++ b/app/api/util.ts @@ -90,8 +90,8 @@ export const genName = (...parts: [string, ...string[]]) => { } const instanceActions: Record = { - // https://github.com/oxidecomputer/omicron/blob/6dd9802/nexus/src/app/instance.rs#L1960-L1963 - start: ['stopped'], + // https://github.com/oxidecomputer/omicron/blob/0496637/nexus/src/app/instance.rs#L2064 + start: ['stopped', 'failed'], // https://github.com/oxidecomputer/omicron/blob/6dd9802/nexus/db-queries/src/db/datastore/instance.rs#L865 delete: ['stopped', 'failed'], From 50aa2eaf2552f4d5ef038e6b5da55f7806f2d936 Mon Sep 17 00:00:00 2001 From: David Crespo Date: Thu, 12 Sep 2024 16:25:09 -0500 Subject: [PATCH 2/2] let's write a test. why not --- test/e2e/instance.e2e.ts | 45 ++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/test/e2e/instance.e2e.ts b/test/e2e/instance.e2e.ts index 34e88fd86..ff2eda9e1 100644 --- a/test/e2e/instance.e2e.ts +++ b/test/e2e/instance.e2e.ts @@ -12,15 +12,48 @@ test('can delete a failed instance', async ({ page }) => { await expect(page).toHaveTitle('Instances / mock-project / Oxide Console') - const row = page.getByRole('row', { name: 'you-fail', exact: false }) - await expect(row).toBeVisible() - await expect(row.getByRole('cell', { name: /failed/ })).toBeVisible() + const cell = page.getByRole('cell', { name: 'you-fail' }) + await expect(cell).toBeVisible() // just to match hidden check at the end - await row.getByRole('button', { name: 'Row actions' }).click() - await page.getByRole('menuitem', { name: 'Delete' }).click() + const table = page.getByRole('table') + await expectRowVisible(table, { + name: 'you-fail', + state: expect.stringContaining('failed'), + }) + + await clickRowAction(page, 'you-fail', 'Delete') await page.getByRole('button', { name: 'Confirm' }).click() - await expect(row).toBeHidden() // bye + await expect(cell).toBeHidden() // bye +}) + +test('can start a failed instance', async ({ page }) => { + await page.goto('/projects/mock-project/instances') + + // check the start button disabled message on a running instance + await page + .getByRole('row', { name: 'db1', exact: false }) + .getByRole('button', { name: 'Row actions' }) + .click() + await page.getByRole('menuitem', { name: 'Start' }).hover() + await expect( + page.getByText('Only stopped or failed instances can be started') + ).toBeVisible() + await page.keyboard.press('Escape') // get out of the menu + + // now start the failed one + const table = page.getByRole('table') + await expectRowVisible(table, { + name: 'you-fail', + state: expect.stringContaining('failed'), + }) + + await clickRowAction(page, 'you-fail', 'Start') + + await expectRowVisible(table, { + name: 'you-fail', + state: expect.stringContaining('starting'), + }) }) test('can stop and delete a running instance', async ({ page }) => {