diff --git a/e2e/use-cases/delete/function-delete.test.ts b/e2e/use-cases/delete/function-delete.test.ts
index b0601cf..eeeea24 100644
--- a/e2e/use-cases/delete/function-delete.test.ts
+++ b/e2e/use-cases/delete/function-delete.test.ts
@@ -18,7 +18,7 @@ test.describe('Delete function', () => {
await deleteFunction(page, PRESEEDED_FUNC_NAME, PRESEEDED_FUNC_NAMESPACE);
});
- test('delete button is disabled for not deployed functions', async ({ page }) => {
+ test('undeploy button is disabled for not deployed functions', async ({ page }) => {
await navigateToFunctionsList(page);
const grid = page.getByRole('grid', { name: 'Functions' });
@@ -26,10 +26,10 @@ test.describe('Delete function', () => {
const row = grid.locator('tbody tr').filter({ hasText: PRESEEDED_FUNC_NAME });
await expect(row.getByText('NotDeployed')).toBeVisible();
- await expect(row.getByRole('button', { name: 'Delete' })).toBeDisabled();
+ await expect(row.getByRole('button', { name: 'Undeploy' })).toBeDisabled();
});
- test('delete button removes function from cluster', async ({ page }) => {
+ test('undeploy button removes function from cluster', async ({ page }) => {
test.setTimeout(600_000);
await test.step('make sure deletion target function is deployed in cluster', async () => {
@@ -52,9 +52,9 @@ test.describe('Delete function', () => {
await test.step('undeploy function', async () => {
const grid = page.getByRole('grid', { name: 'Functions' });
const row = grid.locator(`tbody tr:has(td:text-is("${PRESEEDED_FUNC_NAME}"))`);
- const deleteBtn = row.getByRole('button', { name: 'Delete' });
- await expect(deleteBtn).toBeEnabled({ timeout: 30_000 });
- await deleteBtn.click();
+ const undeployBtn = row.getByRole('button', { name: 'Undeploy' });
+ await expect(undeployBtn).toBeEnabled({ timeout: 30_000 });
+ await undeployBtn.click();
const modal = page.getByRole('dialog');
await expect(modal).toBeVisible({ timeout: 5_000 });
diff --git a/e2e/use-cases/list/functions-list.test.ts b/e2e/use-cases/list/functions-list.test.ts
index 3eff799..e6d46d6 100644
--- a/e2e/use-cases/list/functions-list.test.ts
+++ b/e2e/use-cases/list/functions-list.test.ts
@@ -39,7 +39,7 @@ test.describe('Functions list', () => {
await expect(row).toBeVisible();
await expect(row.getByText('NotDeployed')).toBeVisible();
await expect(row.getByRole('button', { name: 'Edit' })).toBeEnabled();
- await expect(row.getByRole('button', { name: 'Delete' })).toBeDisabled();
+ await expect(row.getByRole('button', { name: 'Undeploy' })).toBeDisabled();
});
await test.step('refresh re-fetches the list', async () => {
diff --git a/locales/en/plugin__console-functions-plugin.json b/locales/en/plugin__console-functions-plugin.json
index b608da8..c6289f5 100644
--- a/locales/en/plugin__console-functions-plugin.json
+++ b/locales/en/plugin__console-functions-plugin.json
@@ -8,6 +8,7 @@
"Branch": "Branch",
"Cancel": "Cancel",
"Click \"Create new function\", choose a runtime, and add any environment variables (plain values or from a secret). Submitting creates a GitHub repository, pushes the function scaffold, and starts a GitHub Actions workflow that deploys the function to your cluster. It appears here as \"NotDeployed\" until the workflow finishes, then the status changes to \"Running\".": "Click \"Create new function\", choose a runtime, and add any environment variables (plain values or from a secret). Submitting creates a GitHub repository, pushes the function scaffold, and starts a GitHub Actions workflow that deploys the function to your cluster. It appears here as \"NotDeployed\" until the workflow finishes, then the status changes to \"Running\".",
+ "Click the undeploy button in the Actions column to remove the running function and its Knative Service from the cluster. The GitHub repository and its code remain, so you can redeploy it later.": "Click the undeploy (power off) button in the Actions column to remove the running function and its Knative Service from the cluster. The GitHub repository and its code remain, so you can redeploy it later.",
"Close": "Close",
"Coming soon": "Coming soon",
"ConfigMap": "ConfigMap",
@@ -23,7 +24,6 @@
"Create function": "Create function",
"Create new function": "Create new function",
"Create or select a project for your function. If it needs credentials such as an API key, create a secret in that namespace so you can reference it as an environment variable.": "Create or select a project for your function. If it needs credentials such as an API key, create a secret in that namespace so you can reference it as an environment variable.",
- "Delete": "Delete",
"Edit": "Edit",
"Edit and redeploy": "Edit and redeploy",
"Edit function": "Edit function",
@@ -62,12 +62,14 @@
"Select a namespace first": "Select a namespace first",
"Select...": "Select...",
"Serverless functions in your repository and deployed to your cluster. Manage lifecycle, monitor status, and scale on demand.": "Serverless functions in your repository and deployed to your cluster. Manage lifecycle, monitor status, and scale on demand.",
- "Set up guide": "Set up guide",
+ "Setup guide": "Setup guide",
"Sign in with GitHub": "Sign in with GitHub",
"Start editing": "Start editing",
"Status": "Status",
"Stay": "Stay",
"Undeploy": "Undeploy",
+ "Undeploy a function": "Undeploy a function",
+ "Undeploying removes the running function and its Knative Service from the cluster. The GitHub repository and its code remain, so you can redeploy it later.": "Undeploying removes the running function and its Knative Service from the cluster. The GitHub repository and its code remain, so you can redeploy it later.",
"Unsaved changes": "Unsaved changes",
"URL": "URL",
"Value": "Value",
diff --git a/src/pages/function-list/components/FunctionTable.test.tsx b/src/pages/function-list/components/FunctionTable.test.tsx
index ee7b7a6..b9468ec 100644
--- a/src/pages/function-list/components/FunctionTable.test.tsx
+++ b/src/pages/function-list/components/FunctionTable.test.tsx
@@ -22,7 +22,7 @@ vi.mock('@openshift-console/dynamic-plugin-sdk', () => ({
vi.mock('@patternfly/react-icons', () => ({
ExclamationTriangleIcon: () => 'WarningIcon',
PencilAltIcon: () => 'EditIcon',
- TrashIcon: () => 'DeleteIcon',
+ PowerOffIcon: () => 'UndeployIcon',
}));
const mockKnativeService = {
@@ -203,7 +203,7 @@ describe('FunctionTable', () => {
expect(onEdit).toHaveBeenCalledWith('my-repo');
});
- it('launches delete modal when delete button is clicked', async () => {
+ it('launches undeploy modal when undeploy button is clicked', async () => {
const mockLauncher = vi.fn();
mockUseDeleteModal.mockReturnValue(mockLauncher);
const user = userEvent.setup();
@@ -214,24 +214,24 @@ describe('FunctionTable', () => {
,
);
- await user.click(screen.getByRole('button', { name: 'Delete' }));
+ await user.click(screen.getByRole('button', { name: 'Undeploy' }));
expect(mockLauncher).toHaveBeenCalled();
expect(mockUseDeleteModal).toHaveBeenCalledWith(
mockKnativeService,
undefined,
- undefined,
+ expect.anything(),
'Undeploy',
);
});
- it('disables delete button for NotDeployed functions', () => {
+ it('disables undeploy button for NotDeployed functions', () => {
render(
,
);
- expect(screen.getByRole('button', { name: 'Delete' })).toBeDisabled();
+ expect(screen.getByRole('button', { name: 'Undeploy' })).toBeDisabled();
});
it('disables edit button for cluster-only functions', () => {
diff --git a/src/pages/function-list/components/FunctionTable.tsx b/src/pages/function-list/components/FunctionTable.tsx
index 5edda32..f8f4940 100644
--- a/src/pages/function-list/components/FunctionTable.tsx
+++ b/src/pages/function-list/components/FunctionTable.tsx
@@ -7,8 +7,8 @@ import {
SuccessStatus,
useDeleteModal,
} from '@openshift-console/dynamic-plugin-sdk';
-import { ActionList, ActionListItem, Button, Tooltip } from '@patternfly/react-core';
-import { ExclamationTriangleIcon, PencilAltIcon, TrashIcon } from '@patternfly/react-icons';
+import { ActionList, ActionListItem, Button, Content, Tooltip } from '@patternfly/react-core';
+import { ExclamationTriangleIcon, PencilAltIcon, PowerOffIcon } from '@patternfly/react-icons';
import { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table';
import { useTranslation } from 'react-i18next';
import { FunctionSource, FunctionStatus } from '../../../common/types';
@@ -80,7 +80,7 @@ export function FunctionTable({
-
+
@@ -154,22 +154,30 @@ function EditActionButton({
return {button};
}
-function DeleteActionButton({ mainResource }: { mainResource?: K8sResourceCommon }) {
+function UndeployActionButton({ mainResource }: { mainResource?: K8sResourceCommon }) {
const { t } = useTranslation('plugin__console-functions-plugin');
- const launchDelete = useDeleteModal(
+ const launchUndeploy = useDeleteModal(
mainResource as K8sResourceCommon,
undefined,
- undefined,
+
+ {t(
+ 'Undeploying removes the running function and its Knative Service from the cluster. The GitHub repository and its code remain, so you can redeploy it later.',
+ )}
+ ,
t('Undeploy'),
);
- return (
+ const button = (
}
+ aria-label={t('Undeploy')}
+ icon={}
isDisabled={!mainResource}
- onClick={() => launchDelete()}
+ onClick={() => launchUndeploy()}
/>
);
+
+ if (!mainResource) return button;
+
+ return {button};
}
diff --git a/src/pages/function-list/components/SetupGuide.test.tsx b/src/pages/function-list/components/SetupGuide.test.tsx
index 536e10d..e606d8c 100644
--- a/src/pages/function-list/components/SetupGuide.test.tsx
+++ b/src/pages/function-list/components/SetupGuide.test.tsx
@@ -26,10 +26,12 @@ describe('SetupGuide', () => {
await user.click(screen.getByRole('button', { name: 'View setup guide.' }));
expect(screen.getByRole('dialog')).toBeInTheDocument();
+ expect(screen.getByText('Setup guide')).toBeInTheDocument();
expect(screen.getByText('Connect GitHub')).toBeInTheDocument();
expect(screen.getByText('Create a namespace and secret')).toBeInTheDocument();
expect(screen.getByText('Create a function')).toBeInTheDocument();
expect(screen.getByText('Edit and redeploy')).toBeInTheDocument();
+ expect(screen.getByText('Undeploy a function')).toBeInTheDocument();
});
it('closes the modal when Close is clicked', async () => {
diff --git a/src/pages/function-list/components/SetupGuide.tsx b/src/pages/function-list/components/SetupGuide.tsx
index 50ca363..fe7e0bf 100644
--- a/src/pages/function-list/components/SetupGuide.tsx
+++ b/src/pages/function-list/components/SetupGuide.tsx
@@ -40,7 +40,7 @@ function SetupGuideModal({ isOpen, onClose }: SetupGuideModalProps) {
return (
-
+
{t('Follow these steps to create and deploy your serverless function.')}
@@ -96,5 +96,11 @@ function steps(t: (key: string) => string): Step[] {
'Open the function from the list to edit its files, then click "Save & Deploy". This pushes your changes to GitHub, which runs the same workflow again to redeploy the function.',
),
},
+ {
+ title: t('Undeploy a function'),
+ body: t(
+ 'Click the undeploy button in the Actions column to remove the running function and its Knative Service from the cluster. The GitHub repository and its code remain, so you can redeploy it later.',
+ ),
+ },
];
}