Skip to content

Commit

Permalink
Merge branch '2.x' into feat-merge-2.x-to-model-registry
Browse files Browse the repository at this point in the history
Signed-off-by: Lin Wang <[email protected]>
  • Loading branch information
wanglam committed Nov 15, 2023
2 parents 34c7157 + 080f8e3 commit d82a06b
Show file tree
Hide file tree
Showing 43 changed files with 1,402 additions and 320 deletions.
40 changes: 19 additions & 21 deletions .github/workflows/unit-tests-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,39 @@ on:
env:
OPENSEARCH_DASHBOARDS_VERSION: '2.x'
jobs:
Get-CI-Image-Tag:
uses: opensearch-project/opensearch-build/.github/workflows/get-ci-image-tag.yml@main
with:
product: opensearch-dashboards

tests:
name: Run unit tests
runs-on: ubuntu-latest
needs: Get-CI-Image-Tag
container:
# using the same image which is used by opensearch-build team to build the OpenSearch Distribution
# this image tag is subject to change as more dependencies and updates will arrive over time
image: ${{ needs.Get-CI-Image-Tag.outputs.ci-image-version-linux }}
# need to switch to root so that github actions can install runner binary on container without permission issues.
options: --user root

steps:
- name: Checkout OpenSearch Dashboards
uses: actions/checkout@v2
with:
repository: opensearch-project/OpenSearch-Dashboards
ref: ${{ env.OPENSEARCH_DASHBOARDS_VERSION }}
path: OpenSearch-Dashboards
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version-file: './OpenSearch-Dashboards/.nvmrc'
registry-url: 'https://registry.npmjs.org'
- name: Install Yarn
# Need to use bash to avoid having a windows/linux specific step
shell: bash
run: |
YARN_VERSION=$(node -p "require('./OpenSearch-Dashboards/package.json').engines.yarn")
echo "Installing yarn@$YARN_VERSION"
npm i -g yarn@$YARN_VERSION
- run: node -v
- run: yarn -v
- name: Checkout ML Commons OpenSearch Dashboards plugin
uses: actions/checkout@v2
with:
path: OpenSearch-Dashboards/plugins/ml-commons-dashboards
- name: Bootstrap plugin/opensearch-dashboards
run: |
cd OpenSearch-Dashboards/plugins/ml-commons-dashboards
yarn osd bootstrap
- name: Run tests with coverage
- name: Bootstrap / build / unittest
run: |
cd OpenSearch-Dashboards/plugins/ml-commons-dashboards
yarn run test:jest --silent --coverage
chown -R 1000:1000 `pwd`
cd ./OpenSearch-Dashboards/
su `id -un 1000` -c "source $NVM_DIR/nvm.sh && nvm use && node -v && yarn -v &&
cd ./plugins/ml-commons-dashboards &&
whoami && yarn osd bootstrap && yarn run test:jest --silent --coverage"
- name: Uploads coverage
uses: codecov/codecov-action@v1
4 changes: 2 additions & 2 deletions opensearch_dashboards.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "mlCommonsDashboards",
"version": "2.8.0.0",
"opensearchDashboardsVersion": "2.8.0",
"version": "2.12.0.0",
"opensearchDashboardsVersion": "2.12.0",
"server": true,
"ui": true,
"requiredPlugins": [
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"config": {
"id": "mlCommonsDashboards"
},
"version": "2.8.0.0",
"version": "2.12.0.0",
"scripts": {
"build": "yarn plugin-helpers build",
"plugin-helpers": "node ../../scripts/plugin_helpers",
Expand Down
24 changes: 24 additions & 0 deletions public/apis/__mocks__/connector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export class Connector {
public async getAll() {
return {
data: [
{
id: 'external-connector-1-id',
name: 'External Connector 1',
},
],
total_connectors: 1,
};
}

public async getAllInternal() {
return {
data: ['Internal Connector 1', 'Common Connector'],
};
}
}
9 changes: 9 additions & 0 deletions public/apis/api_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import { ModelVersion } from './model_version';
import { ModelAggregate } from './model_aggregate';
import { Connector } from './connector';
import { Model } from './model';
import { ModelRepository } from './model_repository';
import { Profile } from './profile';
Expand All @@ -19,6 +20,7 @@ const apiInstanceStore: {
task: Task | undefined;
modelRepository: ModelRepository | undefined;
model: Model | undefined;
connector: Connector | undefined;
} = {
modelVersion: undefined,
modelAggregate: undefined,
Expand All @@ -27,6 +29,7 @@ const apiInstanceStore: {
task: undefined,
modelRepository: undefined,
model: undefined,
connector: undefined,
};

export class APIProvider {
Expand All @@ -37,6 +40,7 @@ export class APIProvider {
public static getAPI(type: 'security'): Security;
public static getAPI(type: 'modelRepository'): ModelRepository;
public static getAPI(type: 'model'): Model;
public static getAPI(type: 'connector'): Connector;
public static getAPI(type: keyof typeof apiInstanceStore) {
if (apiInstanceStore[type]) {
return apiInstanceStore[type]!;
Expand Down Expand Up @@ -77,6 +81,11 @@ export class APIProvider {
apiInstanceStore.model = newInstance;
return newInstance;
}
case 'connector': {
const newInstance = new Connector();
apiInstanceStore.connector = newInstance;
return newInstance;
}
}
}
public static clear() {
Expand Down
35 changes: 35 additions & 0 deletions public/apis/connector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
CONNECTOR_API_ENDPOINT,
INTERNAL_CONNECTOR_API_ENDPOINT,
} from '../../server/routes/constants';
import { InnerHttpProvider } from './inner_http_provider';

export interface GetAllConnectorResponse {
data: Array<{
id: string;
name: string;
description?: string;
}>;
total_connectors: number;
}

interface GetAllInternalConnectorResponse {
data: string[];
}

export class Connector {
public getAll() {
return InnerHttpProvider.getHttp().get<GetAllConnectorResponse>(CONNECTOR_API_ENDPOINT);
}

public getAllInternal() {
return InnerHttpProvider.getHttp().get<GetAllInternalConnectorResponse>(
INTERNAL_CONNECTOR_API_ENDPOINT
);
}
}
9 changes: 8 additions & 1 deletion public/apis/model_version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ export interface ModelVersionSearchItem {
last_registered_time?: number;
last_deployed_time?: number;
last_undeployed_time?: number;
connector_id?: string;
connector?: {
name: string;
description?: string;
};
}

export interface ModelVersionDetail extends ModelVersionSearchItem {
Expand Down Expand Up @@ -106,9 +111,11 @@ export class ModelVersion {
nameOrId?: string;
versionOrKeyword?: string;
modelIds?: string[];
extraQuery?: Record<string, any>;
}) {
const { extraQuery, ...restQuery } = query;
return InnerHttpProvider.getHttp().get<ModelVersionSearchResponse>(MODEL_VERSION_API_ENDPOINT, {
query,
query: extraQuery ? { ...restQuery, extra_query: JSON.stringify(extraQuery) } : restQuery,
});
}

Expand Down
27 changes: 14 additions & 13 deletions public/components/common/options_filter/options_filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useCallback, useMemo, useRef, useState } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import {
EuiPopover,
EuiPopoverTitle,
Expand All @@ -16,6 +16,7 @@ import {
import { OptionsFilterItem } from './options_filter_item';

export interface OptionsFilterProps<T extends string | number = string> {
id?: string;
name: string;
searchPlaceholder: string;
searchWidth?: number;
Expand All @@ -33,11 +34,8 @@ export const OptionsFilter = <T extends string | number = string>({
searchPlaceholder,
searchWidth,
onChange,
...restProps
}: OptionsFilterProps<T>) => {
const valueRef = useRef(value);
valueRef.current = value;
const onChangeRef = useRef(onChange);
onChangeRef.current = onChange;
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const [searchText, setSearchText] = useState<string>();

Expand All @@ -61,17 +59,19 @@ export const OptionsFilter = <T extends string | number = string>({
setIsPopoverOpen(false);
}, []);

const handleFilterItemClick = useCallback((clickItemValue: T) => {
onChangeRef.current(
valueRef.current.includes(clickItemValue)
? valueRef.current.filter((item) => item !== clickItemValue)
: valueRef.current.concat(clickItemValue)
);
}, []);
const handleFilterItemClick = useCallback(
(clickItemValue: T) => {
onChange(
value.includes(clickItemValue)
? value.filter((item) => item !== clickItemValue)
: value.concat(clickItemValue)
);
},
[value, onChange]
);

return (
<EuiPopover
id="popoverExampleMultiSelect"
button={
<EuiFilterButton
iconType="arrowDown"
Expand All @@ -85,6 +85,7 @@ export const OptionsFilter = <T extends string | number = string>({
isOpen={isPopoverOpen}
closePopover={closePopover}
panelPaddingSize="none"
{...restProps}
>
<EuiPopoverTitle style={{ padding: 12 }}>
<EuiFieldSearch
Expand Down
25 changes: 0 additions & 25 deletions public/components/experiment_warning/__tests__/index.test.tsx

This file was deleted.

27 changes: 0 additions & 27 deletions public/components/experiment_warning/index.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import React from 'react';
import userEvent from '@testing-library/user-event';
import { within } from '@testing-library/dom';
import { within, fireEvent } from '@testing-library/dom';

import { render, screen, waitFor } from '../../../../../test/test_utils';
import { ModelVersionTable } from '../model_version_table';
Expand Down Expand Up @@ -45,7 +45,6 @@ describe('<ModelVersionTable />', () => {
it(
'should render sorted column and call onSort after sort change',
async () => {
const user = userEvent.setup();
const onSortMock = jest.fn();
render(
<ModelVersionTable
Expand All @@ -66,31 +65,38 @@ describe('<ModelVersionTable />', () => {
timeout: 2000,
}
);
await user.click(screen.getByText('Version'));

await waitFor(async () => {
fireEvent.click(screen.getByText('Version'));
expect(screen.getByText('Sort A-Z').closest('li')).toHaveClass(
'euiDataGridHeader__action--selected'
);
});

expect(onSortMock).not.toHaveBeenCalled();
await user.click(screen.getByText('Sort Z-A'));
expect(onSortMock).toHaveBeenCalledWith([{ direction: 'desc', id: 'version' }]);
await waitFor(() => {
fireEvent.click(screen.getByText('Sort Z-A'));
expect(onSortMock).toHaveBeenCalledWith([{ direction: 'desc', id: 'version' }]);
});
},
40 * 1000
);

it(
'should NOT render sort button for state and status column',
async () => {
const user = userEvent.setup();
render(<ModelVersionTable versions={[]} tags={[]} />);

await user.click(screen.getByText('State'));
expect(screen.queryByTitle('Sort A-Z')).toBeNull();
expect(screen.getByTestId('dataGridHeaderCell-state')).toBeInTheDocument();
await waitFor(() => {
fireEvent.click(screen.getByTestId('dataGridHeaderCell-state'));
expect(screen.queryByTitle('Sort A-Z')).toBeNull();
});

await user.click(screen.getByText('Status'));
expect(screen.queryByTitle('Sort A-Z')).toBeNull();
await waitFor(() => {
fireEvent.click(screen.getByTestId('dataGridHeaderCell-status'));
expect(screen.queryByTitle('Sort A-Z')).toBeNull();
});
},
20 * 1000
);
Expand Down
Loading

0 comments on commit d82a06b

Please sign in to comment.