From 94e3356fed21d4c6ecf740d4f2ec1522b17cbe84 Mon Sep 17 00:00:00 2001 From: Juntao Wang Date: Wed, 30 Oct 2024 15:03:35 -0400 Subject: [PATCH] Show pipeline server error on project pipelines card and tab section --- .../cypress/cypress/pages/projects.ts | 4 ++ .../mocked/projects/projectDetails.cy.ts | 27 +++++++- .../pipelines/context/PipelinesContext.tsx | 68 ++++++++++--------- .../overview/trainModels/PipelinesCard.tsx | 14 +++- .../detail/pipelines/PipelinesSection.tsx | 2 +- 5 files changed, 81 insertions(+), 34 deletions(-) diff --git a/frontend/src/__tests__/cypress/cypress/pages/projects.ts b/frontend/src/__tests__/cypress/cypress/pages/projects.ts index 8e8b63cf20..e423371770 100644 --- a/frontend/src/__tests__/cypress/cypress/pages/projects.ts +++ b/frontend/src/__tests__/cypress/cypress/pages/projects.ts @@ -307,6 +307,10 @@ class ProjectDetails { return cy.findByTestId('unsupported-pipeline-version-alert'); } + findPipelineTimeoutErrorMessage() { + return cy.findByTestId('timeout-pipeline-error-message'); + } + private findKserveModelsTable() { return cy.findByTestId('kserve-inference-service-table'); } diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/projects/projectDetails.cy.ts b/frontend/src/__tests__/cypress/cypress/tests/mocked/projects/projectDetails.cy.ts index ae45a52d2f..d9a354bb35 100644 --- a/frontend/src/__tests__/cypress/cypress/tests/mocked/projects/projectDetails.cy.ts +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/projects/projectDetails.cy.ts @@ -50,6 +50,8 @@ type HandlersProps = { imageStreamPythonDependencies?: string; v1PipelineServer?: boolean; pipelineServerInstalled?: boolean; + pipelineServerInitializing?: boolean; + pipelineServerErrorMessage?: string; }; const initIntercepts = ({ @@ -65,6 +67,8 @@ const initIntercepts = ({ templates = false, v1PipelineServer = false, pipelineServerInstalled = true, + pipelineServerInitializing, + pipelineServerErrorMessage, }: HandlersProps) => { cy.interceptK8sList( { model: SecretModel, ns: 'test-project' }, @@ -118,12 +122,18 @@ const initIntercepts = ({ mockK8sResourceList([ mockDataSciencePipelineApplicationK8sResource({ dspVersion: v1PipelineServer ? 'v1' : 'v2', + message: pipelineServerErrorMessage, + initializing: pipelineServerInitializing, }), ]), ); cy.interceptK8s( DataSciencePipelineApplicationModel, - mockDataSciencePipelineApplicationK8sResource({ dspVersion: v1PipelineServer ? 'v1' : 'v2' }), + mockDataSciencePipelineApplicationK8sResource({ + dspVersion: v1PipelineServer ? 'v1' : 'v2', + message: pipelineServerErrorMessage, + initializing: pipelineServerInitializing, + }), ); } cy.interceptK8sList(PodModel, mockK8sResourceList([mockPodK8sResource({})])); @@ -272,6 +282,21 @@ describe('Project Details', () => { projectDetails.findProjectResourceKindText().should('have.text', 'Project'); }); + it('Should show pipeline server error when the server has errors', () => { + initIntercepts({ + pipelineServerInitializing: true, + pipelineServerErrorMessage: 'Data connection unsuccessfully verified', + }); + projectDetails.visit('test-project'); + projectDetails + .findPipelineTimeoutErrorMessage() + .should('have.text', 'Data connection unsuccessfully verified'); + projectDetails.findTab('Pipelines').click(); + projectDetails + .findPipelineTimeoutErrorMessage() + .should('have.text', 'Data connection unsuccessfully verified'); + }); + it('Should not allow actions for non-provisioning users', () => { asProjectAdminUser({ isSelfProvisioner: false }); initIntercepts({ disableKServeConfig: true, disableModelConfig: true }); diff --git a/frontend/src/concepts/pipelines/context/PipelinesContext.tsx b/frontend/src/concepts/pipelines/context/PipelinesContext.tsx index 6739198949..3737ec3026 100644 --- a/frontend/src/concepts/pipelines/context/PipelinesContext.tsx +++ b/frontend/src/concepts/pipelines/context/PipelinesContext.tsx @@ -16,7 +16,6 @@ import { ConfigurePipelinesServerModal } from '~/concepts/pipelines/content/conf import ViewPipelineServerModal from '~/concepts/pipelines/content/ViewPipelineServerModal'; import useSyncPreferredProject from '~/concepts/projects/useSyncPreferredProject'; import useManageElyraSecret from '~/concepts/pipelines/context/useManageElyraSecret'; -import { deleteServer } from '~/concepts/pipelines/utils'; import { conditionalArea, SupportedArea } from '~/concepts/areas'; import { DEV_MODE } from '~/utilities/const'; import { MetadataStoreServicePromiseClient } from '~/third_party/mlmd'; @@ -273,38 +272,45 @@ export const ViewServerModal = ({ onClose }: { onClose: () => void }): React.JSX }; export const PipelineServerTimedOut: React.FC = () => { - const { namespace, crName, crStatus, refreshState, ignoreTimedOut } = - React.useContext(PipelinesContext); + const { crStatus, ignoreTimedOut } = React.useContext(PipelinesContext); + const [deleteOpen, setDeleteOpen] = React.useState(false); const errorMessage = crStatus?.conditions?.find((condition) => condition.type === 'Ready')?.message || ''; return ( - ignoreTimedOut()} />} - actionLinks={ - <> - deleteServer(namespace, crName).then(() => refreshState())} - > - Delete pipeline server - - ignoreTimedOut()}>Close - - } - > - - {errorMessage && ( - {errorMessage} - )} - - We encountered an error creating or loading your pipeline server. To continue, delete this - pipeline server and create a new one. Deleting this pipeline server will delete all of its - resources, including pipelines, runs, and jobs. - - To get help contact your administrator. - - + <> + ignoreTimedOut()} />} + actionLinks={ + <> + setDeleteOpen(true)}> + Delete pipeline server + + ignoreTimedOut()}>Close + + } + > + + {errorMessage && ( + {errorMessage} + )} + + We encountered an error creating or loading your pipeline server. To continue, delete + this pipeline server and create a new one. Deleting this pipeline server will delete all + of its resources, including pipelines, runs, and jobs. + + To get help contact your administrator. + + + {deleteOpen ? ( + { + setDeleteOpen(false); + }} + /> + ) : null} + ); }; diff --git a/frontend/src/pages/projects/screens/detail/overview/trainModels/PipelinesCard.tsx b/frontend/src/pages/projects/screens/detail/overview/trainModels/PipelinesCard.tsx index 0f164cf76e..c31fbae642 100644 --- a/frontend/src/pages/projects/screens/detail/overview/trainModels/PipelinesCard.tsx +++ b/frontend/src/pages/projects/screens/detail/overview/trainModels/PipelinesCard.tsx @@ -14,7 +14,11 @@ import { TextContent, } from '@patternfly/react-core'; import { ProjectDetailsContext } from '~/pages/projects/ProjectDetailsContext'; -import { CreatePipelineServerButton, usePipelinesAPI } from '~/concepts/pipelines/context'; +import { + CreatePipelineServerButton, + PipelineServerTimedOut, + usePipelinesAPI, +} from '~/concepts/pipelines/context'; import { useSafePipelines } from '~/concepts/pipelines/apiHooks/usePipelines'; import EnsureAPIAvailability from '~/concepts/pipelines/EnsureAPIAvailability'; import EnsureCompatiblePipelineServer from '~/concepts/pipelines/EnsureCompatiblePipelineServer'; @@ -80,6 +84,14 @@ const PipelinesCard: React.FC = () => { ); } + if (pipelinesServer.timedOut) { + return ( + + + + ); + } + return ( diff --git a/frontend/src/pages/projects/screens/detail/pipelines/PipelinesSection.tsx b/frontend/src/pages/projects/screens/detail/pipelines/PipelinesSection.tsx index 9ba4bdae1b..ee8977b8c4 100644 --- a/frontend/src/pages/projects/screens/detail/pipelines/PipelinesSection.tsx +++ b/frontend/src/pages/projects/screens/detail/pipelines/PipelinesSection.tsx @@ -63,7 +63,7 @@ const PipelinesSection: React.FC = () => { ) : null } actions={actions} - isLoading={(compatible && !apiAvailable && installed) || initializing} + isLoading={(!timedOut && compatible && !apiAvailable && installed) || initializing} isEmpty={!installed} emptyState={} showDivider={isPipelinesEmpty}