From f67c5cf72b64a776722ccc6e337aa4183068b018 Mon Sep 17 00:00:00 2001 From: Kayla Washburn Date: Tue, 12 Dec 2023 11:18:04 -0700 Subject: [PATCH] fix: only show orphan option while deleting failed workspaces (#11161) --- .../WorkspaceDeleteDialog.stories.tsx | 39 ++++++---- .../WorkspaceDeleteDialog.tsx | 74 ++++++++++--------- .../WorkspacePage/WorkspacePage.test.tsx | 6 +- 3 files changed, 69 insertions(+), 50 deletions(-) diff --git a/site/src/pages/WorkspacePage/WorkspaceDeleteDialog/WorkspaceDeleteDialog.stories.tsx b/site/src/pages/WorkspacePage/WorkspaceDeleteDialog/WorkspaceDeleteDialog.stories.tsx index 3e6c4a555e..700e0f824a 100644 --- a/site/src/pages/WorkspacePage/WorkspaceDeleteDialog/WorkspaceDeleteDialog.stories.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceDeleteDialog/WorkspaceDeleteDialog.stories.tsx @@ -1,32 +1,43 @@ -import { type ComponentProps } from "react"; import { Meta, StoryObj } from "@storybook/react"; import { WorkspaceDeleteDialog } from "./WorkspaceDeleteDialog"; -import { MockWorkspace } from "testHelpers/entities"; +import { MockWorkspace, MockFailedWorkspace } from "testHelpers/entities"; const meta: Meta = { title: "pages/WorkspacePage/WorkspaceDeleteDialog", component: WorkspaceDeleteDialog, + args: { + workspace: MockWorkspace, + canUpdateTemplate: false, + isOpen: true, + onCancel: () => {}, + onConfirm: () => {}, + workspaceBuildDateStr: "2 days ago", + }, }; export default meta; type Story = StoryObj; -const args: ComponentProps = { - workspace: MockWorkspace, - canUpdateTemplate: false, - isOpen: true, - onCancel: () => {}, - onConfirm: () => {}, - workspaceBuildDateStr: "2 days ago", -}; +export const Example: Story = {}; -export const NotTemplateAdmin: Story = { - args, +// Should look the same as `Example` +export const Unhealthy: Story = { + args: { + workspace: MockFailedWorkspace, + }, }; -export const TemplateAdmin: Story = { +// Should look the same as `Example` +export const AdminView: Story = { args: { - ...args, + canUpdateTemplate: true, + }, +}; + +// Should show the `--orphan` option +export const UnhealthyAdminView: Story = { + args: { + workspace: MockFailedWorkspace, canUpdateTemplate: true, }, }; diff --git a/site/src/pages/WorkspacePage/WorkspaceDeleteDialog/WorkspaceDeleteDialog.tsx b/site/src/pages/WorkspacePage/WorkspaceDeleteDialog/WorkspaceDeleteDialog.tsx index c51c8b2b15..aa6880badd 100644 --- a/site/src/pages/WorkspacePage/WorkspaceDeleteDialog/WorkspaceDeleteDialog.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceDeleteDialog/WorkspaceDeleteDialog.tsx @@ -95,39 +95,47 @@ export const WorkspaceDeleteDialog: FC = ({ "data-testid": "delete-dialog-name-confirmation", }} /> - {canUpdateTemplate && ( -
-
- { - setOrphanWorkspace(!orphanWorkspace); - }} - className="option" - name="orphan_resources" - checked={orphanWorkspace} - data-testid="orphan-checkbox" - /> -
-
-

Orphan Resources

- - As a Template Admin, you may skip resource cleanup to force - remove a failed workspace. Resources such as volumes and - virtual machines will not be destroyed.  - - Learn more... - - -
-
- )} + { + // Orphaning is sort of a "last resort" that should really only + // be used if Terraform is failing to apply while deleting, which + // usually means that builds are failing as well. + canUpdateTemplate && + workspace.latest_build.status === "failed" && ( +
+
+ { + setOrphanWorkspace(!orphanWorkspace); + }} + className="option" + name="orphan_resources" + checked={orphanWorkspace} + data-testid="orphan-checkbox" + /> +
+
+

Orphan Resources

+ + As a Template Admin, you may skip resource cleanup to + delete a failed workspace. Resources such as volumes and + virtual machines will not be destroyed.  + + Learn more... + + +
+
+ ) + } } diff --git a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx index cdaa83a92b..393f8ab6ea 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx @@ -133,7 +133,7 @@ describe("WorkspacePage", () => { const deleteWorkspaceMock = jest .spyOn(api, "deleteWorkspace") .mockResolvedValueOnce(MockWorkspaceBuildDelete); - await renderWorkspacePage(MockWorkspace); + await renderWorkspacePage(MockFailedWorkspace); // open the workspace action popover so we have access to all available ctas const trigger = screen.getByTestId("workspace-options-button"); @@ -147,7 +147,7 @@ describe("WorkspacePage", () => { const dialog = await screen.findByTestId("dialog"); const labelText = "Workspace name"; const textField = within(dialog).getByLabelText(labelText); - await user.type(textField, MockWorkspace.name); + await user.type(textField, MockFailedWorkspace.name); // check orphan option const orphanCheckbox = within( @@ -163,7 +163,7 @@ describe("WorkspacePage", () => { }); await user.click(confirmButton); // arguments are workspace.name, log level (undefined), and orphan - expect(deleteWorkspaceMock).toBeCalledWith(MockWorkspace.id, { + expect(deleteWorkspaceMock).toBeCalledWith(MockFailedWorkspace.id, { log_level: undefined, orphan: true, });