Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
dchourasia committed Oct 17, 2024
2 parents f8bae04 + 4d29174 commit 1fb5ecd
Show file tree
Hide file tree
Showing 34 changed files with 990 additions and 114 deletions.
2 changes: 1 addition & 1 deletion docs/dev-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ODH requires the following to run:
- [NodeJS and NPM](https://nodejs.org/)
- Node recommended version -> `18.18.2`
- NPM recommended version -> `9.8.1`
- [OpenShift CLI](https://docs.openshift.com/container-platform/latest/cli_reference/openshift_cli/getting-started-cli.html)
- [OpenShift CLI](https://docs.redhat.com/en/documentation/openshift_container_platform/4.16/html/cli_tools/openshift-cli-oc)
- [kustomize](https://github.com/kubernetes-sigs/kustomize) (if you need to do deployment)

### Additional tooling
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/__mocks__/mockComponents.ts

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions frontend/src/__mocks__/mockDocs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const mockDocs = (): OdhDocument[] => [
displayName: 'How to install Python packages on your notebook server',
durationMinutes: 15,
type: 'how-to',
url: 'https://access.redhat.com/documentation/en-us/red_hat_openshift_data_science/1/html-single/working_on_data_science_projects/index#installing-python-packages-on-your-notebook-server_nb-server/index',
url: 'https://docs.redhat.com/en/documentation/red_hat_openshift_ai_cloud_service/1/html/working_with_connected_applications/using_the_jupyter_application#installing-python-packages-on-your-notebook-server_connected-apps',
},
},
{
Expand All @@ -32,11 +32,11 @@ export const mockDocs = (): OdhDocument[] => [
},
spec: {
appName: 'jupyter',
description: 'Update the settings or the notebook image on your notebook server.',
displayName: 'How to update notebook server settings',
description: 'Manage the settings or the notebook image on your notebook server.',
displayName: 'How to manage notebook server settings',
durationMinutes: 15,
type: 'how-to',
url: 'https://access.redhat.com/documentation/en-us/red_hat_openshift_data_science/1/html-single/how_to_update_notebook_server_settings/index',
url: 'https://docs.redhat.com/en/documentation/red_hat_openshift_ai_cloud_service/1/html/managing_resources/managing-notebook-servers_notebook-mgmt',
},
},
{
Expand All @@ -51,11 +51,11 @@ export const mockDocs = (): OdhDocument[] => [
},
spec: {
appName: 'jupyter',
description: 'Connect to data in S3 Storage using environment variables.',
displayName: 'How to use data from Amazon S3 buckets',
description: 'Connect to data in S3 Storage.',
displayName: 'How to use data from an S3-compatible object store',
durationMinutes: 15,
type: 'how-to',
url: 'https://access.redhat.com/documentation/en-us/red_hat_openshift_data_science/1/html-single/how_to_use_data_from_amazon_s3_buckets/index',
url: 'https://docs.redhat.com/en/documentation/red_hat_openshift_ai_cloud_service/1/html/working_with_data_in_an_s3-compatible_object_store/index',
},
},
{
Expand All @@ -74,7 +74,7 @@ export const mockDocs = (): OdhDocument[] => [
displayName: 'How to view installed packages on your notebook server',
durationMinutes: 15,
type: 'how-to',
url: 'https://access.redhat.com/documentation/en-us/red_hat_openshift_data_science/1/html-single/how_to_view_installed_packages_on_your_notebook_server/index',
url: 'https://docs.redhat.com/en/documentation/red_hat_openshift_ai_cloud_service/1/html/working_with_connected_applications/using_the_jupyter_application#viewing-python-packages-installed-on-your-notebook-server_connected-apps',
},
},
];
30 changes: 30 additions & 0 deletions frontend/src/__tests__/cypress/cypress/pages/workbench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,22 @@ class NotebookRow extends TableRow {
}
}

class AttachConnectionModal extends Modal {
constructor() {
super('Attach existing connections');
}

selectConnectionOption(name: string) {
this.find().findByRole('button', { name: 'Connections' }).click();
this.find().findByRole('option', { name }).click();
this.find().findByRole('button', { name: 'Connections' }).click();
}

findAttachButton() {
return this.find().findByTestId('attach-button');
}
}

class CreateSpawnerPage {
k8sNameDescription = new K8sNameDescriptionField('workbench');

Expand Down Expand Up @@ -309,6 +325,19 @@ class CreateSpawnerPage {
findContainerSizeInput(name: string) {
return cy.findByTestId('container-size-group').contains(name);
}

findAttachConnectionButton() {
return cy.findByTestId('attach-existing-connection-button');
}

findConnectionsTable() {
return cy.findByTestId('connections-table');
}

findConnectionsTableRow(name: string, type: string) {
this.findConnectionsTable().find(`[data-label=Name]`).contains(name);
this.findConnectionsTable().find(`[data-label=Type]`).contains(type);
}
}

class EditSpawnerPage extends CreateSpawnerPage {
Expand Down Expand Up @@ -373,3 +402,4 @@ export const notebookConfirmModal = new NotebookConfirmModal();
export const editSpawnerPage = new EditSpawnerPage();
export const storageModal = new StorageModal();
export const notFoundSpawnerPage = new NotFoundSpawnerPage();
export const attachConnectionModal = new AttachConnectionModal();
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { mockImageStreamK8sResource } from '~/__mocks__/mockImageStreamK8sResour
import { mockPVCK8sResource } from '~/__mocks__/mockPVCK8sResource';
import { mockPodK8sResource } from '~/__mocks__/mockPodK8sResource';
import {
attachConnectionModal,
createSpawnerPage,
editSpawnerPage,
notFoundSpawnerPage,
Expand All @@ -37,6 +38,7 @@ import {
import { mock200Status } from '~/__mocks__/mockK8sStatus';
import type { NotebookSize } from '~/types';
import { mockAcceleratorProfile } from '~/__mocks__/mockAcceleratorProfile';
import { mockConnectionTypeConfigMap } from '~/__mocks__/mockConnectionType';

const configYamlPath = '../../__mocks__/mock-upload-configmap.yaml';

Expand Down Expand Up @@ -407,6 +409,74 @@ describe('Workbench page', () => {
verifyRelativeURL('/projects/test-project?section=workbenches');
});

it('Create workbench with connection', () => {
initIntercepts({ isEmpty: true });
cy.interceptOdh('GET /api/config', mockDashboardConfig({ disableConnectionTypes: false }));
cy.interceptOdh('GET /api/connection-types', [mockConnectionTypeConfigMap({})]);
cy.interceptK8sList(
{ model: SecretModel, ns: 'test-project' },
mockK8sResourceList([
mockSecretK8sResource({ name: 'test1', displayName: 'test1' }),
mockSecretK8sResource({ name: 'test2', displayName: 'test2' }),
]),
);

workbenchPage.visit('test-project');
workbenchPage.findCreateButton().click();
createSpawnerPage.findSubmitButton().should('be.disabled');
verifyRelativeURL('/projects/test-project/spawner');
createSpawnerPage.k8sNameDescription.findDisplayNameInput().fill('1234');
createSpawnerPage.findNotebookImage('test-9').click();

createSpawnerPage.findAttachConnectionButton().click();
attachConnectionModal.shouldBeOpen();
attachConnectionModal.findAttachButton().should('be.disabled');
attachConnectionModal.selectConnectionOption('test1');
attachConnectionModal.findAttachButton().should('be.enabled');
attachConnectionModal.selectConnectionOption('test2');
attachConnectionModal.findAttachButton().click();

createSpawnerPage.findConnectionsTableRow('test1', 's3');
createSpawnerPage.findConnectionsTableRow('test2', 's3');

createSpawnerPage.findSubmitButton().click();
cy.wait('@createWorkbench').then((interception) => {
expect(interception.request.body).to.containSubset({
metadata: {
annotations: {
'openshift.io/display-name': '1234',
},
name: 'wb-1234',
namespace: 'test-project',
},
spec: {
template: {
spec: {
affinity: {},
containers: [
{
envFrom: [
{
secretRef: {
name: 'test1',
},
},
{
secretRef: {
name: 'test2',
},
},
],
},
],
},
},
},
});
});
verifyRelativeURL('/projects/test-project?section=workbenches');
});

it('list workbench and table sorting', () => {
initIntercepts({
notebookSizes: [
Expand Down
24 changes: 15 additions & 9 deletions frontend/src/components/MultiSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import {
HelperTextItem,
SelectGroup,
Divider,
SelectOptionProps,
} from '@patternfly/react-core';
import { TimesIcon } from '@patternfly/react-icons/dist/esm/icons/times-icon';

export type SelectionOptions = {
export type SelectionOptions = Omit<SelectOptionProps, 'id'> & {
id: number | string;
name: string;
selected?: boolean;
Expand Down Expand Up @@ -49,9 +50,12 @@ type MultiSelectionProps = {
isCreateOptionOnTop?: boolean;
/** Message to display to create a new option */
createOptionMessage?: string | ((newValue: string) => string);
filterFunction?: (filterText: string, options: SelectionOptions[]) => SelectionOptions[];
};

const defaultCreateOptionMessage = (newValue: string) => `Create "${newValue}"`;
const defaultFilterFunction = (filterText: string, options: SelectionOptions[]) =>
options.filter((o) => !filterText || o.name.toLowerCase().includes(filterText.toLowerCase()));

export const MultiSelection: React.FC<MultiSelectionProps> = ({
value = [],
Expand All @@ -69,6 +73,7 @@ export const MultiSelection: React.FC<MultiSelectionProps> = ({
isCreatable = false,
isCreateOptionOnTop = false,
createOptionMessage = defaultCreateOptionMessage,
filterFunction = defaultFilterFunction,
}) => {
const [isOpen, setIsOpen] = React.useState(false);
const [inputValue, setInputValue] = React.useState<string>('');
Expand All @@ -80,16 +85,14 @@ export const MultiSelection: React.FC<MultiSelectionProps> = ({
let counter = 0;
return groupedValues
.map((g) => {
const values = g.values.filter(
(v) => !inputValue || v.name.toLowerCase().includes(inputValue.toLowerCase()),
);
const values = filterFunction(inputValue, g.values);
return {
...g,
values: values.map((v) => ({ ...v, index: counter++ })),
};
})
.filter((g) => g.values.length);
}, [inputValue, groupedValues]);
}, [filterFunction, groupedValues, inputValue]);

const setOpen = (open: boolean) => {
setIsOpen(open);
Expand All @@ -104,10 +107,11 @@ export const MultiSelection: React.FC<MultiSelectionProps> = ({

const selectOptions = React.useMemo(
() =>
value
.filter((v) => !inputValue || v.name.toLowerCase().includes(inputValue.toLowerCase()))
.map((v, index) => ({ ...v, index: groupOptions.length + index })),
[groupOptions, inputValue, value],
filterFunction(inputValue, value).map((v, index) => ({
...v,
index: groupOptions.length + index,
})),
[filterFunction, groupOptions, inputValue, value],
);

const allValues = React.useMemo(() => {
Expand Down Expand Up @@ -340,6 +344,7 @@ export const MultiSelection: React.FC<MultiSelectionProps> = ({
value={option.id}
ref={null}
isSelected={option.selected}
description={option.description}
>
{option.name}
</SelectOption>
Expand All @@ -363,6 +368,7 @@ export const MultiSelection: React.FC<MultiSelectionProps> = ({
value={option.id}
ref={null}
isSelected={option.selected}
description={option.description}
>
{option.name}
</SelectOption>
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/table/TableRowTitleDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import TruncatedText from '~/components/TruncatedText';
type TableRowTitleDescriptionProps = {
title: React.ReactNode;
boldTitle?: boolean;
titleIcon?: React.ReactNode;
resource?: K8sResourceCommon;
subtitle?: React.ReactNode;
description?: React.ReactNode;
Expand All @@ -19,6 +20,7 @@ type TableRowTitleDescriptionProps = {
const TableRowTitleDescription: React.FC<TableRowTitleDescriptionProps> = ({
title,
boldTitle = true,
titleIcon,
description,
resource,
subtitle,
Expand Down Expand Up @@ -56,6 +58,7 @@ const TableRowTitleDescription: React.FC<TableRowTitleDescriptionProps> = ({
) : (
title
)}
{titleIcon}
</div>
{subtitle}
{descriptionNode}
Expand Down
14 changes: 14 additions & 0 deletions frontend/src/concepts/connectionTypes/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,17 @@ export const parseConnectionSecretValues = (

return response;
};

export const getConnectionTypeDisplayName = (
connection: Connection,
connectionTypes: ConnectionTypeConfigMapObj[],
): string => {
const matchingType = connectionTypes.find(
(type) =>
type.metadata.name === connection.metadata.annotations['opendatahub.io/connection-type'],
);
return (
matchingType?.metadata.annotations?.['openshift.io/display-name'] ||
connection.metadata.annotations['opendatahub.io/connection-type']
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { useIsAreaAvailable, SupportedArea } from '~/concepts/areas';
import { ODH_PRODUCT_NAME } from '~/utilities/const';

const INVALID_ARGO_DEPLOYMENT_SELF_DOCUMENTATION_URL =
'https://access.redhat.com/documentation/en-us/red_hat_openshift_ai_self-managed/2.9/html/release_notes/new-features-and-enhancements_relnotes';
'https://docs.redhat.com/en/documentation/red_hat_openshift_ai_self-managed/2-latest/html/working_with_data_science_pipelines/enabling-data-science-pipelines-2_ds-pipelines';

const INVALID_ARGO_DEPLOYMENT_CLOUD_DOCUMENTATION_URL =
'https://access.redhat.com/documentation/en-us/red_hat_openshift_ai_cloud_service/1/html/release_notes/new-features-and-enhancements_relnotes';
'https://docs.redhat.com/en/documentation/red_hat_openshift_ai_cloud_service/1/html/working_with_data_science_pipelines/enabling-data-science-pipelines-2_ds-pipelines';

export const InvalidArgoDeploymentAlert: React.FC = () => {
const [invalidArgoDeploymentAlertDismissed, setInvalidArgoDeploymentAlertDismissed] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ import {
DrawerHead,
DrawerPanelBody,
DrawerPanelContent,
Text,
Flex,
Popover,
Title,
} from '@patternfly/react-core';
import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
import PipelineRunDrawerRightTabs from '~/concepts/pipelines/content/pipelinesDetails/pipelineRun/PipelineRunDrawerRightTabs';
import './PipelineRunDrawer.scss';
import { PipelineTask } from '~/concepts/pipelines/topology';
import { Execution } from '~/third_party/mlmd';
import DashboardPopupIconButton from '~/concepts/dashboard/DashboardPopupIconButton';
import InlineTruncatedClipboardCopy from '~/components/InlineTruncatedClipboardCopy';
import { ArtifactNodeDrawerContent } from './artifacts';

type PipelineRunDrawerRightContentProps = {
Expand Down Expand Up @@ -48,7 +52,24 @@ const PipelineRunDrawerRightContent: React.FC<PipelineRunDrawerRightContentProps
<Title headingLevel="h2" size="xl">
{task.name}
</Title>
{task.status?.podName && <Text component="small">{task.status.podName}</Text>}
{task.status?.podName && (
<Flex
display={{ default: 'inlineFlex' }}
spaceItems={{ default: 'spaceItemsXs' }}
flexWrap={{ default: 'nowrap' }}
>
<InlineTruncatedClipboardCopy
testId="podname-copy"
textToCopy={task.status.podName}
/>
<Popover bodyContent="This is the pod name of the run execution in OpenShift">
<DashboardPopupIconButton
icon={<OutlinedQuestionCircleIcon />}
aria-label="More info"
/>
</Popover>
</Flex>
)}
<DrawerActions>
<DrawerCloseButton onClick={onClose} />
</DrawerActions>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/clusterSettings/TelemetrySettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const TelemetrySettings: React.FC<TelemetrySettingsProps> = ({
For more information see the{' '}
<Text
component={TextVariants.a}
href="https://access.redhat.com/documentation/en-us/red_hat_openshift_data_science/1/html/managing_users_and_user_resources/usage-data-collection#usage-data-collection-notice-for-openshift-data-science"
href="https://docs.redhat.com/en/documentation/red_hat_openshift_ai_cloud_service/1/html/managing_resources/usage-data-collection"
target="_blank"
>
documentation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const NotebookAdminControl: React.FC = () => {
Create, delete, and manage permissions for {ODH_PRODUCT_NAME} users in OpenShift.{' '}
<ExternalLink
text="Learn more about OpenShift user management"
to="https://access.redhat.com/documentation/en-us/red_hat_openshift_data_science/1/html/managing_users_and_user_resources/index"
to="https://docs.redhat.com/en/documentation/red_hat_openshift_ai_cloud_service/1/html/managing_openshift_ai/managing-users-and-groups"
/>
</Alert>
</StackItem>
Expand Down
Loading

0 comments on commit 1fb5ecd

Please sign in to comment.