From b58d99f24ca014dfc531952b182801ad1ce261cb Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Wed, 13 Nov 2024 19:01:17 -0500 Subject: [PATCH 01/19] Fix index management link issue for both stacks --- .../search_inference_endpoints/kibana.jsonc | 21 ++---- .../all_inference_endpoints/constants.ts | 1 + .../actions/component/index_item.test.tsx | 48 +++++++++++++ .../{usage_item.tsx => index_item.tsx} | 27 ++++---- .../actions/component/list_usage_results.tsx | 13 ++-- ...e_item.test.tsx => pipeline_item.test.tsx} | 41 ++--------- .../actions/component/pipeline_item.tsx | 69 +++++++++++++++++++ .../public/types.ts | 5 ++ .../search_inference_endpoints/tsconfig.json | 16 ++--- 9 files changed, 162 insertions(+), 79 deletions(-) create mode 100644 x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.test.tsx rename x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/{usage_item.tsx => index_item.tsx} (79%) rename x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/{usage_item.test.tsx => pipeline_item.test.tsx} (59%) create mode 100644 x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx diff --git a/x-pack/plugins/search_inference_endpoints/kibana.jsonc b/x-pack/plugins/search_inference_endpoints/kibana.jsonc index f535a9df27e99..3d8341df35b56 100644 --- a/x-pack/plugins/search_inference_endpoints/kibana.jsonc +++ b/x-pack/plugins/search_inference_endpoints/kibana.jsonc @@ -11,22 +11,9 @@ "id": "searchInferenceEndpoints", "server": true, "browser": true, - "configPath": [ - "xpack", - "searchInferenceEndpoints" - ], - "requiredPlugins": [ - "actions", - "features", - "ml", - "share", - ], - "optionalPlugins": [ - "cloud", - "console", - ], - "requiredBundles": [ - "kibanaReact" - ] + "configPath": ["xpack", "searchInferenceEndpoints"], + "requiredPlugins": ["actions", "features", "ml", "share"], + "optionalPlugins": ["cloud", "console", "serverless"], + "requiredBundles": ["kibanaReact"] } } diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/constants.ts b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/constants.ts index 7ce1e578f1db0..931994c46afca 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/constants.ts +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/constants.ts @@ -34,3 +34,4 @@ export const DEFAULT_INFERENCE_ENDPOINTS_TABLE_STATE: AllInferenceEndpointsTable }; export const PIPELINE_URL = 'ingest/ingest_pipelines'; +export const SERVERLESS_INDEX_MANAGEMENT_URL = 'index_details'; diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.test.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.test.tsx new file mode 100644 index 0000000000000..bfdc1edd31bd6 --- /dev/null +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.test.tsx @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { render, fireEvent, screen } from '@testing-library/react'; +import React from 'react'; + +import { IndexItem } from './index_item'; +import { InferenceUsageInfo } from '../../../../types'; +import { useKibana } from '../../../../../../hooks/use_kibana'; + +jest.mock('../../../../../../hooks/use_kibana'); +const mockUseKibana = useKibana as jest.Mock; +const mockNavigateToApp = jest.fn(); + +describe('Index Item', () => { + const item: InferenceUsageInfo = { + id: 'index-1', + type: 'Index', + }; + beforeEach(() => { + mockUseKibana.mockReturnValue({ + services: { + application: { + navigateToApp: mockNavigateToApp, + }, + }, + }); + + render(); + }); + + it('renders', () => { + expect(screen.getByText('index-1')).toBeInTheDocument(); + expect(screen.getByText('Index')).toBeInTheDocument(); + }); + + it('opens index in a new tab', () => { + fireEvent.click(screen.getByRole('button')); + expect(mockNavigateToApp).toHaveBeenCalledWith('enterpriseSearchContent', { + openInNewTab: true, + path: 'search_indices/index-1', + }); + }); +}); diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.tsx similarity index 79% rename from x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.tsx rename to x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.tsx index 577b9f8aa0e29..1f19d6e4d002b 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.tsx @@ -18,28 +18,29 @@ import { } from '@elastic/eui'; import React from 'react'; import { ENTERPRISE_SEARCH_CONTENT_APP_ID } from '@kbn/deeplinks-search'; -import { MANAGEMENT_APP_ID } from '@kbn/deeplinks-management/constants'; + +import { SEARCH_INDICES } from '@kbn/deeplinks-search/constants'; import { useKibana } from '../../../../../../hooks/use_kibana'; import { InferenceUsageInfo } from '../../../../types'; -import { PIPELINE_URL } from '../../../../constants'; +import { SERVERLESS_INDEX_MANAGEMENT_URL } from '../../../../constants'; interface UsageProps { usageItem: InferenceUsageInfo; } -export const UsageItem: React.FC = ({ usageItem }) => { +export const IndexItem: React.FC = ({ usageItem }) => { const { - services: { application }, + services: { application, serverless }, } = useKibana(); - const handleNavigateToIndex = () => { - if (usageItem.type === 'Index') { - application?.navigateToApp(ENTERPRISE_SEARCH_CONTENT_APP_ID, { - path: `search_indices/${usageItem.id}`, + const navigateToIndex = async () => { + if (serverless) { + application?.navigateToApp(SEARCH_INDICES, { + path: `${SERVERLESS_INDEX_MANAGEMENT_URL}/${usageItem.id}/data`, openInNewTab: true, }); - } else if (usageItem.type === 'Pipeline') { - application?.navigateToApp(MANAGEMENT_APP_ID, { - path: `${PIPELINE_URL}?pipeline=${usageItem.id}`, + } else { + application?.navigateToApp(ENTERPRISE_SEARCH_CONTENT_APP_ID, { + path: `search_indices/${usageItem.id}`, openInNewTab: true, }); } @@ -62,9 +63,9 @@ export const UsageItem: React.FC = ({ usageItem }) => { - + - + {' '} diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/list_usage_results.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/list_usage_results.tsx index d42b0f6735252..05aaaa8bb9eaf 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/list_usage_results.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/list_usage_results.tsx @@ -10,7 +10,8 @@ import { EuiFieldSearch, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { InferenceUsageInfo } from '../../../../types'; import * as i18n from '../delete/confirm_delete_endpoint/translations'; -import { UsageItem } from './usage_item'; +import { IndexItem } from './index_item'; +import { PipelineItem } from './pipeline_item'; interface ListUsageResultsProps { list: InferenceUsageInfo[]; @@ -35,9 +36,13 @@ export const ListUsageResults: React.FC = ({ list }) => { {list .filter((item) => item.id.toLowerCase().includes(term.toLowerCase())) - .map((item, id) => ( - - ))} + .map((item, id) => { + if (item.type === 'Pipeline') { + return ; + } else { + return ; + } + })} ); diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.test.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.test.tsx similarity index 59% rename from x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.test.tsx rename to x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.test.tsx index 6c6899c71922d..8a1bc7a78cab2 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.test.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.test.tsx @@ -8,7 +8,7 @@ import { render, fireEvent, screen } from '@testing-library/react'; import React from 'react'; -import { UsageItem } from './usage_item'; +import { PipelineItem } from './pipeline_item'; import { InferenceUsageInfo } from '../../../../types'; import { useKibana } from '../../../../../../hooks/use_kibana'; @@ -16,7 +16,11 @@ jest.mock('../../../../../../hooks/use_kibana'); const mockUseKibana = useKibana as jest.Mock; const mockNavigateToApp = jest.fn(); -describe('UsageItem', () => { +describe('Pipeline item', () => { + const item: InferenceUsageInfo = { + id: 'pipeline-1', + type: 'Pipeline', + }; beforeEach(() => { mockUseKibana.mockReturnValue({ services: { @@ -25,41 +29,10 @@ describe('UsageItem', () => { }, }, }); - }); - - describe('index', () => { - const item: InferenceUsageInfo = { - id: 'index-1', - type: 'Index', - }; - - beforeEach(() => { - render(); - }); - - it('renders', () => { - expect(screen.getByText('index-1')).toBeInTheDocument(); - expect(screen.getByText('Index')).toBeInTheDocument(); - }); - - it('opens index in a new tab', () => { - fireEvent.click(screen.getByRole('button')); - expect(mockNavigateToApp).toHaveBeenCalledWith('enterpriseSearchContent', { - openInNewTab: true, - path: 'search_indices/index-1', - }); - }); + render(); }); describe('pipeline', () => { - const item: InferenceUsageInfo = { - id: 'pipeline-1', - type: 'Pipeline', - }; - - beforeEach(() => { - render(); - }); it('renders', () => { expect(screen.getByText('pipeline-1')).toBeInTheDocument(); expect(screen.getByText('Pipeline')).toBeInTheDocument(); diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx new file mode 100644 index 0000000000000..fd1017c1f5bbd --- /dev/null +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + EuiBadge, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiLink, + EuiText, + EuiTextTruncate, + EuiIcon, + EuiSpacer, +} from '@elastic/eui'; +import React from 'react'; +import { MANAGEMENT_APP_ID } from '@kbn/deeplinks-management/constants'; + +import { useKibana } from '../../../../../../hooks/use_kibana'; +import { InferenceUsageInfo } from '../../../../types'; +import { PIPELINE_URL } from '../../../../constants'; + +interface UsageProps { + usageItem: InferenceUsageInfo; +} +export const PipelineItem: React.FC = ({ usageItem }) => { + const { + services: { application }, + } = useKibana(); + const navigateToPipeline = () => { + application?.navigateToApp(MANAGEMENT_APP_ID, { + path: `${PIPELINE_URL}?pipeline=${usageItem.id}`, + openInNewTab: true, + }); + }; + + return ( + + + + + + + + + + + + {usageItem.type} + + + + + + + + + + + + + + + + ); +}; diff --git a/x-pack/plugins/search_inference_endpoints/public/types.ts b/x-pack/plugins/search_inference_endpoints/public/types.ts index 4bd83521cf8d6..ab8f6733db4d4 100644 --- a/x-pack/plugins/search_inference_endpoints/public/types.ts +++ b/x-pack/plugins/search_inference_endpoints/public/types.ts @@ -11,6 +11,8 @@ import { AppMountParameters } from '@kbn/core/public'; import { MlPluginStart } from '@kbn/ml-plugin/public'; import { SharePluginStart } from '@kbn/share-plugin/public'; import React from 'react'; + +import { ServerlessPluginStart } from '@kbn/serverless/public'; import type { App } from './components/app'; import type { InferenceEndpointsProvider } from './providers/inference_endpoints_provider'; @@ -27,12 +29,15 @@ export interface AppPluginStartDependencies { history: AppMountParameters['history']; share: SharePluginStart; console?: ConsolePluginStart; + serverless?: ServerlessPluginStart; } export interface AppServicesContext { http: HttpStart; ml?: MlPluginStart; console?: ConsolePluginStart; + serverless?: ServerlessPluginStart; + share: SharePluginStart; } export interface InferenceUsageResponse { diff --git a/x-pack/plugins/search_inference_endpoints/tsconfig.json b/x-pack/plugins/search_inference_endpoints/tsconfig.json index d454be99b65f0..e181bfbf0a540 100644 --- a/x-pack/plugins/search_inference_endpoints/tsconfig.json +++ b/x-pack/plugins/search_inference_endpoints/tsconfig.json @@ -1,14 +1,9 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "outDir": "target/types", + "outDir": "target/types" }, - "include": [ - "__mocks__/**/*", - "common/**/*", - "public/**/*", - "server/**/*" - ], + "include": ["__mocks__/**/*", "common/**/*", "public/**/*", "server/**/*"], "kbn_references": [ "@kbn/config-schema", "@kbn/core", @@ -33,9 +28,8 @@ "@kbn/features-plugin", "@kbn/ui-theme", "@kbn/deeplinks-search", - "@kbn/deeplinks-management" + "@kbn/deeplinks-management", + "@kbn/serverless" ], - "exclude": [ - "target/**/*", - ] + "exclude": ["target/**/*"] } From b16064ae33738aefbff4571137e6c8d4d9df88fc Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Thu, 14 Nov 2024 18:30:06 -0500 Subject: [PATCH 02/19] Adding FTR tests for inference management ui --- config/serverless.es.yml | 60 ++++----- .../filter/multi_select_filter.tsx | 4 +- .../filter/service_provider_filter.tsx | 1 + .../filter/task_type_filter.tsx | 1 + .../delete/confirm_delete_endpoint/index.tsx | 1 + .../all_inference_endpoints/tabular_page.tsx | 4 + .../public/components/inference_endpoints.tsx | 2 +- .../functional/page_objects/index.ts | 2 + .../svl_search_inference_management_page.ts | 110 ++++++++++++++++ .../services/svl_search_navigation.ts | 10 ++ .../functional/test_suites/search/index.ts | 35 ++--- .../search/inference_management.ts | 121 ++++++++++++++++++ .../test_suites/search/navigation.ts | 30 ++--- 13 files changed, 317 insertions(+), 64 deletions(-) create mode 100644 x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts create mode 100644 x-pack/test_serverless/functional/test_suites/search/inference_management.ts diff --git a/config/serverless.es.yml b/config/serverless.es.yml index eafa7f3113395..c4929f2c1fa45 100644 --- a/config/serverless.es.yml +++ b/config/serverless.es.yml @@ -23,42 +23,42 @@ xpack.fleet.packages: version: latest # Filter out some observability and security integrations xpack.fleet.internal.registry.excludePackages: [ - # Security integrations - 'endpoint', - 'beaconing', - 'cloud_security_posture', - 'cloud_defend', - 'security_detection_engine', - - # Oblt integrations - 'apm', - 'synthetics', - 'synthetics_dashboards', - - # Removed in 8.11 integrations - 'cisco', - 'microsoft', - 'symantec', - 'cyberark', - - # Profiling integrations - 'profiler_agent', -] + # Security integrations + 'endpoint', + 'beaconing', + 'cloud_security_posture', + 'cloud_defend', + 'security_detection_engine', + + # Oblt integrations + 'apm', + 'synthetics', + 'synthetics_dashboards', + + # Removed in 8.11 integrations + 'cisco', + 'microsoft', + 'symantec', + 'cyberark', + + # Profiling integrations + 'profiler_agent', + ] ## Fine-tune the search solution feature privileges. Also, refer to `serverless.yml` for the project-agnostic overrides. xpack.features.overrides: ### Dashboards feature is moved from Analytics category to the Search one. - dashboard.category: "enterpriseSearch" + dashboard.category: 'enterpriseSearch' ### Dev Tools feature is moved from Analytics category to the Search one. - dev_tools.category: "enterpriseSearch" + dev_tools.category: 'enterpriseSearch' ### Discover feature is moved from Analytics category to the Search one. - discover.category: "enterpriseSearch" + discover.category: 'enterpriseSearch' ### Machine Learning feature is moved from Analytics category to the Management one. - ml.category: "management" + ml.category: 'management' ### Stack Alerts feature is moved from Analytics category to the Search one renamed to simply `Alerts`. stackAlerts: - name: "Alerts" - category: "enterpriseSearch" + name: 'Alerts' + category: 'enterpriseSearch' ## Cloud settings xpack.cloud.serverless.project_type: search @@ -113,7 +113,7 @@ data_visualizer.resultLinks.fileBeat.enabled: false xpack.searchPlayground.ui.enabled: true # Search InferenceEndpoints -xpack.searchInferenceEndpoints.ui.enabled: false +xpack.searchInferenceEndpoints.ui.enabled: true # Search Notebooks xpack.search.notebooks.catalog.url: https://elastic-enterprise-search.s3.us-east-2.amazonaws.com/serverless/catalog.json @@ -126,9 +126,9 @@ xpack.index_management.dev.enableSemanticText: true xpack.observabilityAIAssistant.enabled: true xpack.searchAssistant.enabled: true xpack.searchAssistant.ui.enabled: true -xpack.observabilityAIAssistant.scope: "search" +xpack.observabilityAIAssistant.scope: 'search' xpack.observabilityAIAssistant.enableKnowledgeBase: false -aiAssistantManagementSelection.preferredAIAssistantType: "observability" +aiAssistantManagementSelection.preferredAIAssistantType: 'observability' xpack.observabilityAiAssistantManagement.logSourcesEnabled: false xpack.observabilityAiAssistantManagement.spacesEnabled: false xpack.observabilityAiAssistantManagement.visibilityEnabled: false diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/multi_select_filter.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/multi_select_filter.tsx index 790bb5ec09913..371b204e0acd6 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/multi_select_filter.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/multi_select_filter.tsx @@ -33,6 +33,7 @@ interface UseFilterParams { options: MultiSelectFilterOption[]; renderOption?: (option: MultiSelectFilterOption) => React.ReactNode; selectedOptionKeys?: string[]; + dataTestSubj?: string; } export const MultiSelectFilter: React.FC = ({ @@ -41,6 +42,7 @@ export const MultiSelectFilter: React.FC = ({ options: rawOptions, selectedOptionKeys = [], renderOption, + dataTestSubj, }) => { const { euiTheme } = useEuiTheme(); const [isPopoverOpen, setIsPopoverOpen] = useState(false); @@ -55,7 +57,7 @@ export const MultiSelectFilter: React.FC = ({ ); return ( - + = ({ optionKeys, onChange }) options={options} renderOption={(option) => option.label} selectedOptionKeys={optionKeys} + dataTestSubj="service-field-endpoints" /> ); }; diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/task_type_filter.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/task_type_filter.tsx index e9c32503dba73..071069a880b3c 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/task_type_filter.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/task_type_filter.tsx @@ -38,6 +38,7 @@ export const TaskTypeFilter: React.FC = ({ optionKeys, onChange }) => { options={options} renderOption={(option) => option.label} selectedOptionKeys={optionKeys} + dataTestSubj="type-field-endpoints" /> ); }; diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/delete/confirm_delete_endpoint/index.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/delete/confirm_delete_endpoint/index.tsx index 06bd585c0eb28..345f0f81b0927 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/delete/confirm_delete_endpoint/index.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/delete/confirm_delete_endpoint/index.tsx @@ -86,6 +86,7 @@ export const ConfirmDeleteEndpointModal: React.FC {inferenceEndpoint.endpoint} diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/tabular_page.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/tabular_page.tsx index 4cf4b3112396d..0ea17fa6408a0 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/tabular_page.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/tabular_page.tsx @@ -52,6 +52,7 @@ export const TabularPage: React.FC = ({ inferenceEndpoints }) { field: 'endpoint', name: i18n.ENDPOINT, + 'data-test-subj': 'endpointCell', render: (endpoint: string) => { if (endpoint) { return ; @@ -65,6 +66,7 @@ export const TabularPage: React.FC = ({ inferenceEndpoints }) { field: 'provider', name: i18n.SERVICE_PROVIDER, + 'data-test-subj': 'providerCell', render: (provider: InferenceAPIConfigResponse) => { if (provider) { return ; @@ -78,6 +80,7 @@ export const TabularPage: React.FC = ({ inferenceEndpoints }) { field: 'type', name: i18n.TASK_TYPE, + 'data-test-subj': 'typeCell', render: (type: TaskTypes) => { if (type) { return ; @@ -149,6 +152,7 @@ export const TabularPage: React.FC = ({ inferenceEndpoints }) onChange={handleTableChange} pagination={pagination} sorting={sorting} + data-test-subj="inferenceEndpointTable" /> diff --git a/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx b/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx index e1dae72d402f7..1aea8df69e0ee 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx @@ -22,7 +22,7 @@ export const InferenceEndpoints: React.FC = () => { return ( <> {inferenceEndpoints.length > 0 && } - + {inferenceEndpoints.length === 0 ? ( ) : ( diff --git a/x-pack/test_serverless/functional/page_objects/index.ts b/x-pack/test_serverless/functional/page_objects/index.ts index 2c894b28b065f..e10e98529b8bf 100644 --- a/x-pack/test_serverless/functional/page_objects/index.ts +++ b/x-pack/test_serverless/functional/page_objects/index.ts @@ -25,6 +25,7 @@ import { SvlSearchIndexDetailPageProvider } from './svl_search_index_detail_page import { SvlSearchElasticsearchStartPageProvider } from './svl_search_elasticsearch_start_page'; import { SvlApiKeysProvider } from './svl_api_keys'; import { SvlSearchCreateIndexPageProvider } from './svl_search_create_index_page'; +import { SvlSearchInferenceManagementPageProvider } from './svl_search_inference_management_page'; export const pageObjects = { ...xpackFunctionalPageObjects, @@ -47,4 +48,5 @@ export const pageObjects = { svlSearchElasticsearchStartPage: SvlSearchElasticsearchStartPageProvider, svlApiKeys: SvlApiKeysProvider, svlSearchCreateIndexPage: SvlSearchCreateIndexPageProvider, + svlSearchInferenceManagementPage: SvlSearchInferenceManagementPageProvider, }; diff --git a/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts b/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts new file mode 100644 index 0000000000000..a21e677877a63 --- /dev/null +++ b/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts @@ -0,0 +1,110 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../ftr_provider_context'; + +export function SvlSearchInferenceManagementPageProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const browser = getService('browser'); + const retry = getService('retry'); + + return { + InferenceEmptyPage: { + async expectComponentsToBeExist() { + const endpointDesc = await testSubjects.find('createFirstInferenceEndpointDescription'); + const endpointDescMsg = await endpointDesc.getVisibleText(); + expect(endpointDescMsg).to.contain( + "Inference endpoints enable you to perform inference tasks using NLP models provided by third-party services or Elastic's built-in models like ELSER and E5. Set up tasks such as text embedding, completions, reranking, and more by using the Create Inference API." + ); + await testSubjects.existOrFail('learn-how-to-create-inference-endpoints'); + await testSubjects.existOrFail('view-your-models'); + await testSubjects.existOrFail('semantic-search-with-elser'); + await testSubjects.existOrFail('semantic-search-with-e5'); + }, + }, + InferenceTabularPage: { + async expectHeaderToBeExist() { + await testSubjects.existOrFail('allInferenceEndpointsPage'); + await testSubjects.existOrFail('api-documentation'); + await testSubjects.existOrFail('view-your-models'); + }, + + async expectTabularViewToBeLoaded() { + await testSubjects.existOrFail('search-field-endpoints'); + await testSubjects.existOrFail('type-field-endpoints'); + await testSubjects.existOrFail('service-field-endpoints'); + + const table = await testSubjects.find('inferenceEndpointTable'); + const rows = await table.findAllByClassName('euiTableRow'); + expect(rows.length).to.equal(1); + + const endpointCell = await rows[0].findByTestSubject('endpointCell'); + const endpointName = await endpointCell.getVisibleText(); + expect(endpointName).to.contain('endpoint-1'); + + const providerCell = await rows[0].findByTestSubject('providerCell'); + const providerName = await providerCell.getVisibleText(); + expect(providerName).to.contain('Elasticsearch'); + expect(providerName).to.contain('.elser_model_2'); + + const typeCell = await rows[0].findByTestSubject('typeCell'); + const typeName = await typeCell.getVisibleText(); + expect(typeName).to.contain('sparse_embedding'); + }, + + async expectEndpointWithoutUsageTobeDelete() { + await testSubjects.click('inferenceUIDeleteAction'); + await testSubjects.existOrFail('deleteModalForInferenceUI'); + await testSubjects.existOrFail('deleteModalInferenceEndpointName'); + + await testSubjects.click('confirmModalConfirmButton'); + + await retry.waitForWithTimeout('delete modal to disappear', 5000, () => + testSubjects + .missingOrFail('confirmModalConfirmButton') + .then(() => true) + .catch(() => false) + ); + }, + + async expectEndpointWithUsageTobeDelete() { + await testSubjects.click('inferenceUIDeleteAction'); + await testSubjects.existOrFail('deleteModalForInferenceUI'); + await testSubjects.existOrFail('deleteModalInferenceEndpointName'); + + const items = await testSubjects.findAll('usageItem'); + expect(items.length).to.equal(2); + + const index = await items[0].getVisibleText(); + const pipeline = await items[1].getVisibleText(); + + expect(index.includes('elser_index')).to.be(true); + expect(pipeline.includes('endpoint-1')).to.be(true); + + expect(await testSubjects.isEnabled('confirmModalConfirmButton')).to.be(false); + + await testSubjects.click('warningCheckbox'); + + expect(await testSubjects.isEnabled('confirmModalConfirmButton')).to.be(true); + await testSubjects.click('confirmModalConfirmButton'); + + await retry.waitForWithTimeout('delete modal to disappear', 5000, () => + testSubjects + .missingOrFail('confirmModalConfirmButton') + .then(() => true) + .catch(() => false) + ); + }, + + async expectToCopyEndpoint() { + await testSubjects.click('inference-endpoints-action-copy-id-label'); + expect((await browser.getClipboardValue()).includes('endpoint-1')).to.be(true); + }, + }, + }; +} diff --git a/x-pack/test_serverless/functional/services/svl_search_navigation.ts b/x-pack/test_serverless/functional/services/svl_search_navigation.ts index 1f27cf18ec8cb..01e8d5d34975f 100644 --- a/x-pack/test_serverless/functional/services/svl_search_navigation.ts +++ b/x-pack/test_serverless/functional/services/svl_search_navigation.ts @@ -47,5 +47,15 @@ export function SvlSearchNavigationServiceProvider({ }); await testSubjects.existOrFail('searchIndicesDetailsPage', { timeout: 2000 }); }, + async navigateToInferenceManagementPage(expectRedirect: boolean = false) { + await retry.tryForTime(60 * 1000, async () => { + await PageObjects.common.navigateToApp('searchInferenceEndpoints', { + shouldLoginIfPrompted: false, + }); + if (!expectRedirect) { + await testSubjects.existOrFail('inferenceManagementPage', { timeout: 2000 }); + } + }); + }, }; } diff --git a/x-pack/test_serverless/functional/test_suites/search/index.ts b/x-pack/test_serverless/functional/test_suites/search/index.ts index 99190ae0cc072..4a491697c9fca 100644 --- a/x-pack/test_serverless/functional/test_suites/search/index.ts +++ b/x-pack/test_serverless/functional/test_suites/search/index.ts @@ -11,22 +11,23 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('serverless search UI', function () { this.tags(['esGate']); - loadTestFile(require.resolve('./navigation')); - loadTestFile(require.resolve('./elasticsearch_start.ts')); - loadTestFile(require.resolve('./search_index_detail.ts')); - loadTestFile(require.resolve('./getting_started')); - loadTestFile(require.resolve('./index_management')); - loadTestFile(require.resolve('./connectors/connectors_overview')); - loadTestFile(require.resolve('./default_dataview')); - loadTestFile(require.resolve('./pipelines')); - loadTestFile(require.resolve('./cases/attachment_framework')); - loadTestFile(require.resolve('./dashboards/build_dashboard')); - loadTestFile(require.resolve('./dashboards/import_dashboard')); - loadTestFile(require.resolve('./advanced_settings')); - loadTestFile(require.resolve('./rules/rule_details')); - loadTestFile(require.resolve('./console_notebooks')); - loadTestFile(require.resolve('./search_playground/playground_overview')); - loadTestFile(require.resolve('./ml')); - loadTestFile(require.resolve('./custom_role_access')); + // loadTestFile(require.resolve('./navigation')); + // loadTestFile(require.resolve('./elasticsearch_start.ts')); + // loadTestFile(require.resolve('./search_index_detail.ts')); + // loadTestFile(require.resolve('./getting_started')); + // loadTestFile(require.resolve('./index_management')); + // loadTestFile(require.resolve('./connectors/connectors_overview')); + // loadTestFile(require.resolve('./default_dataview')); + // loadTestFile(require.resolve('./pipelines')); + // loadTestFile(require.resolve('./cases/attachment_framework')); + // loadTestFile(require.resolve('./dashboards/build_dashboard')); + // loadTestFile(require.resolve('./dashboards/import_dashboard')); + // loadTestFile(require.resolve('./advanced_settings')); + // loadTestFile(require.resolve('./rules/rule_details')); + // loadTestFile(require.resolve('./console_notebooks')); + // loadTestFile(require.resolve('./search_playground/playground_overview')); + // loadTestFile(require.resolve('./ml')); + // loadTestFile(require.resolve('./custom_role_access')); + loadTestFile(require.resolve('./inference_management')); }); } diff --git a/x-pack/test_serverless/functional/test_suites/search/inference_management.ts b/x-pack/test_serverless/functional/test_suites/search/inference_management.ts new file mode 100644 index 0000000000000..bcdad28e3cb6d --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/search/inference_management.ts @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import { testHasEmbeddedConsole } from './embedded_console'; + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const pageObjects = getPageObjects([ + 'svlCommonPage', + 'embeddedConsole', + 'svlSearchInferenceManagementPage', + ]); + const svlSearchNavigation = getService('svlSearchNavigation'); + const browser = getService('browser'); + const ml = getService('ml'); + + describe('Serverless Inference Management UI', function () { + const endpoint = 'endpoint-1'; + const taskType = 'sparse_embedding'; + const modelConfig = { + service: 'elser', + service_settings: { + num_allocations: 1, + num_threads: 1, + }, + }; + + before(async () => { + await pageObjects.svlCommonPage.loginWithRole('developer'); + }); + + after(async () => {}); + + beforeEach(async () => { + await svlSearchNavigation.navigateToInferenceManagementPage(); + }); + + describe('endpoint empty view', () => { + it('is loaded successfully', async () => { + await pageObjects.svlSearchInferenceManagementPage.InferenceEmptyPage.expectComponentsToBeExist(); + }); + }); + + describe('endpoint tabular view', () => { + before(async () => { + await ml.api.createInferenceEndpoint(endpoint, taskType, modelConfig); + await browser.refresh(); + }); + + after(async () => { + await ml.api.deleteInferenceEndpoint(endpoint, taskType); + }); + + it('is loaded successfully', async () => { + await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectHeaderToBeExist(); + await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectTabularViewToBeLoaded(); + }); + }); + + describe('copy endpoint id action', () => { + beforeEach(async () => { + await ml.api.createInferenceEndpoint(endpoint, taskType, modelConfig); + await browser.refresh(); + }); + + after(async () => { + await ml.api.deleteInferenceEndpoint(endpoint, taskType); + }); + + it('can copy an endpoint id', async () => { + await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectToCopyEndpoint(); + }); + }); + + describe('delete action', () => { + beforeEach(async () => { + await ml.api.createInferenceEndpoint(endpoint, taskType, modelConfig); + await browser.refresh(); + }); + + after(async () => { + await ml.api.deleteIndices('elser_index'); + await ml.api.deleteIngestPipeline(endpoint); + await ml.api.cleanMlIndices(); + }); + + it('deletes modal successfully without any usage', async () => { + await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectEndpointWithoutUsageTobeDelete(); + }); + + it('deletes modal successfully with usage', async () => { + const indexMapping: estypes.MappingTypeMapping = { + properties: { + content: { + type: 'text', + }, + content_embedding: { + type: 'semantic_text', + inference_id: endpoint, + }, + }, + }; + await ml.api.createIngestPipeline(endpoint); + await ml.api.createIndex('elser_index', indexMapping); + + await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectEndpointWithUsageTobeDelete(); + }); + }); + + it('has embedded dev console', async () => { + await testHasEmbeddedConsole(pageObjects); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/search/navigation.ts b/x-pack/test_serverless/functional/test_suites/search/navigation.ts index 24009866b2b15..74d1c59cbc8e5 100644 --- a/x-pack/test_serverless/functional/test_suites/search/navigation.ts +++ b/x-pack/test_serverless/functional/test_suites/search/navigation.ts @@ -95,17 +95,17 @@ export default function ({ getPageObject, getService }: FtrProviderContext) { }); // check Relevance // > Inference Endpoints - // await solutionNavigation.sidenav.clickLink({ - // deepLinkId: 'searchInferenceEndpoints', - // }); - // await solutionNavigation.sidenav.expectLinkActive({ - // deepLinkId: 'searchInferenceEndpoints', - // }); - // await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Relevance' }); - // await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Inference Endpoints' }); - // await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ - // deepLinkId: 'searchInferenceEndpoints', - // }); + await solutionNavigation.sidenav.clickLink({ + deepLinkId: 'searchInferenceEndpoints', + }); + await solutionNavigation.sidenav.expectLinkActive({ + deepLinkId: 'searchInferenceEndpoints', + }); + await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Relevance' }); + await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Inference Endpoints' }); + await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ + deepLinkId: 'searchInferenceEndpoints', + }); // check Analyze // > Discover @@ -245,8 +245,8 @@ export default function ({ getPageObject, getService }: FtrProviderContext) { await solutionNavigation.sidenav.expectLinkExists({ text: 'Build' }); await solutionNavigation.sidenav.expectLinkExists({ text: 'Dev Tools' }); await solutionNavigation.sidenav.expectLinkExists({ text: 'Playground' }); - // await solutionNavigation.sidenav.expectLinkExists({ text: 'Relevance' }); - // await solutionNavigation.sidenav.expectLinkExists({ text: 'Inference Endpoints' }); + await solutionNavigation.sidenav.expectLinkExists({ text: 'Relevance' }); + await solutionNavigation.sidenav.expectLinkExists({ text: 'Inference Endpoints' }); await solutionNavigation.sidenav.expectLinkExists({ text: 'Analyze' }); await solutionNavigation.sidenav.expectLinkExists({ text: 'Discover' }); await solutionNavigation.sidenav.expectLinkExists({ text: 'Dashboards' }); @@ -270,8 +270,8 @@ export default function ({ getPageObject, getService }: FtrProviderContext) { 'build', 'dev_tools', 'searchPlayground', - // 'relevance', - // 'searchInferenceEndpoints', + 'relevance', + 'searchInferenceEndpoints', 'analyze', 'discover', 'dashboards', From aec1441dd8b68922ca30f9f45e4b4e2fd64a0a75 Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Mon, 18 Nov 2024 09:28:20 -0500 Subject: [PATCH 03/19] Updating index management link to support for ES3 --- .../actions/component/scan_usage_results.tsx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/scan_usage_results.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/scan_usage_results.tsx index 33d7a4dae891f..cab278f5e1ed9 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/scan_usage_results.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/scan_usage_results.tsx @@ -19,6 +19,7 @@ import { euiThemeVars } from '@kbn/ui-theme'; import { css } from '@emotion/react'; import { ENTERPRISE_SEARCH_CONTENT_APP_ID } from '@kbn/deeplinks-search'; +import { SEARCH_INDICES } from '@kbn/deeplinks-search/constants'; import { InferenceUsageInfo } from '../../../../types'; import { useKibana } from '../../../../../../hooks/use_kibana'; import { RenderMessageWithIcon } from './render_message_with_icon'; @@ -37,13 +38,19 @@ export const ScanUsageResults: React.FC = ({ onIgnoreWarningCheckboxChange, }) => { const { - services: { application }, + services: { application, serverless }, } = useKibana(); const handleNavigateToIndexManagement = () => { - application?.navigateToApp(ENTERPRISE_SEARCH_CONTENT_APP_ID, { - path: 'search_indices', - openInNewTab: true, - }); + if (serverless) { + application?.navigateToApp(SEARCH_INDICES, { + openInNewTab: true, + }); + } else { + application?.navigateToApp(ENTERPRISE_SEARCH_CONTENT_APP_ID, { + path: `search_indices`, + openInNewTab: true, + }); + } }; return ( From 9f9841ce7d924cea058049bd11dd0762381a2599 Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Mon, 18 Nov 2024 09:48:07 -0500 Subject: [PATCH 04/19] Updating tests --- .../svl_search_inference_management_page.ts | 4 +++ .../functional/test_suites/search/index.ts | 34 +++++++++---------- .../search/inference_management.ts | 10 +++--- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts b/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts index a21e677877a63..48c6a859de097 100644 --- a/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts +++ b/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts @@ -70,6 +70,8 @@ export function SvlSearchInferenceManagementPageProvider({ getService }: FtrProv .then(() => true) .catch(() => false) ); + + await testSubjects.existOrFail('createFirstInferenceEndpointDescription'); }, async expectEndpointWithUsageTobeDelete() { @@ -99,6 +101,8 @@ export function SvlSearchInferenceManagementPageProvider({ getService }: FtrProv .then(() => true) .catch(() => false) ); + + await testSubjects.existOrFail('createFirstInferenceEndpointDescription'); }, async expectToCopyEndpoint() { diff --git a/x-pack/test_serverless/functional/test_suites/search/index.ts b/x-pack/test_serverless/functional/test_suites/search/index.ts index 4a491697c9fca..dd7021aebe800 100644 --- a/x-pack/test_serverless/functional/test_suites/search/index.ts +++ b/x-pack/test_serverless/functional/test_suites/search/index.ts @@ -11,23 +11,23 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('serverless search UI', function () { this.tags(['esGate']); - // loadTestFile(require.resolve('./navigation')); - // loadTestFile(require.resolve('./elasticsearch_start.ts')); - // loadTestFile(require.resolve('./search_index_detail.ts')); - // loadTestFile(require.resolve('./getting_started')); - // loadTestFile(require.resolve('./index_management')); - // loadTestFile(require.resolve('./connectors/connectors_overview')); - // loadTestFile(require.resolve('./default_dataview')); - // loadTestFile(require.resolve('./pipelines')); - // loadTestFile(require.resolve('./cases/attachment_framework')); - // loadTestFile(require.resolve('./dashboards/build_dashboard')); - // loadTestFile(require.resolve('./dashboards/import_dashboard')); - // loadTestFile(require.resolve('./advanced_settings')); - // loadTestFile(require.resolve('./rules/rule_details')); - // loadTestFile(require.resolve('./console_notebooks')); - // loadTestFile(require.resolve('./search_playground/playground_overview')); - // loadTestFile(require.resolve('./ml')); - // loadTestFile(require.resolve('./custom_role_access')); + loadTestFile(require.resolve('./navigation')); + loadTestFile(require.resolve('./elasticsearch_start.ts')); + loadTestFile(require.resolve('./search_index_detail.ts')); + loadTestFile(require.resolve('./getting_started')); + loadTestFile(require.resolve('./index_management')); + loadTestFile(require.resolve('./connectors/connectors_overview')); + loadTestFile(require.resolve('./default_dataview')); + loadTestFile(require.resolve('./pipelines')); + loadTestFile(require.resolve('./cases/attachment_framework')); + loadTestFile(require.resolve('./dashboards/build_dashboard')); + loadTestFile(require.resolve('./dashboards/import_dashboard')); + loadTestFile(require.resolve('./advanced_settings')); + loadTestFile(require.resolve('./rules/rule_details')); + loadTestFile(require.resolve('./console_notebooks')); + loadTestFile(require.resolve('./search_playground/playground_overview')); + loadTestFile(require.resolve('./ml')); + loadTestFile(require.resolve('./custom_role_access')); loadTestFile(require.resolve('./inference_management')); }); } diff --git a/x-pack/test_serverless/functional/test_suites/search/inference_management.ts b/x-pack/test_serverless/functional/test_suites/search/inference_management.ts index bcdad28e3cb6d..49a0dee5cee4d 100644 --- a/x-pack/test_serverless/functional/test_suites/search/inference_management.ts +++ b/x-pack/test_serverless/functional/test_suites/search/inference_management.ts @@ -36,7 +36,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await pageObjects.svlCommonPage.loginWithRole('developer'); }); - after(async () => {}); + after(async () => { + await ml.api.cleanMlIndices(); + }); beforeEach(async () => { await svlSearchNavigation.navigateToInferenceManagementPage(); @@ -80,15 +82,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); describe('delete action', () => { + const usageIndex = 'elser_index'; beforeEach(async () => { await ml.api.createInferenceEndpoint(endpoint, taskType, modelConfig); await browser.refresh(); }); after(async () => { - await ml.api.deleteIndices('elser_index'); + await ml.api.deleteIndices(usageIndex); await ml.api.deleteIngestPipeline(endpoint); - await ml.api.cleanMlIndices(); }); it('deletes modal successfully without any usage', async () => { @@ -108,7 +110,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }, }; await ml.api.createIngestPipeline(endpoint); - await ml.api.createIndex('elser_index', indexMapping); + await ml.api.createIndex(usageIndex, indexMapping); await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectEndpointWithUsageTobeDelete(); }); From a244eee6e52efadcf54c65d54a07df9b310fe800 Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Mon, 18 Nov 2024 14:13:18 -0500 Subject: [PATCH 05/19] Fix formatting issue with yml and json file --- config/serverless.es.yml | 58 +++++++++---------- .../search_inference_endpoints/kibana.jsonc | 22 +++++-- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/config/serverless.es.yml b/config/serverless.es.yml index c4929f2c1fa45..4b0d416bacdfc 100644 --- a/config/serverless.es.yml +++ b/config/serverless.es.yml @@ -23,42 +23,42 @@ xpack.fleet.packages: version: latest # Filter out some observability and security integrations xpack.fleet.internal.registry.excludePackages: [ - # Security integrations - 'endpoint', - 'beaconing', - 'cloud_security_posture', - 'cloud_defend', - 'security_detection_engine', - - # Oblt integrations - 'apm', - 'synthetics', - 'synthetics_dashboards', - - # Removed in 8.11 integrations - 'cisco', - 'microsoft', - 'symantec', - 'cyberark', - - # Profiling integrations - 'profiler_agent', - ] + # Security integrations + 'endpoint', + 'beaconing', + 'cloud_security_posture', + 'cloud_defend', + 'security_detection_engine', + + # Oblt integrations + 'apm', + 'synthetics', + 'synthetics_dashboards', + + # Removed in 8.11 integrations + 'cisco', + 'microsoft', + 'symantec', + 'cyberark', + + # Profiling integrations + 'profiler_agent', +] ## Fine-tune the search solution feature privileges. Also, refer to `serverless.yml` for the project-agnostic overrides. xpack.features.overrides: ### Dashboards feature is moved from Analytics category to the Search one. - dashboard.category: 'enterpriseSearch' + dashboard.category: "enterpriseSearch" ### Dev Tools feature is moved from Analytics category to the Search one. - dev_tools.category: 'enterpriseSearch' + dev_tools.category: "enterpriseSearch" ### Discover feature is moved from Analytics category to the Search one. - discover.category: 'enterpriseSearch' + discover.category: "enterpriseSearch" ### Machine Learning feature is moved from Analytics category to the Management one. - ml.category: 'management' + ml.category: "management" ### Stack Alerts feature is moved from Analytics category to the Search one renamed to simply `Alerts`. stackAlerts: - name: 'Alerts' - category: 'enterpriseSearch' + name: "Alerts" + category: "enterpriseSearch" ## Cloud settings xpack.cloud.serverless.project_type: search @@ -126,9 +126,9 @@ xpack.index_management.dev.enableSemanticText: true xpack.observabilityAIAssistant.enabled: true xpack.searchAssistant.enabled: true xpack.searchAssistant.ui.enabled: true -xpack.observabilityAIAssistant.scope: 'search' +xpack.observabilityAIAssistant.scope: "search" xpack.observabilityAIAssistant.enableKnowledgeBase: false -aiAssistantManagementSelection.preferredAIAssistantType: 'observability' +aiAssistantManagementSelection.preferredAIAssistantType: "observability" xpack.observabilityAiAssistantManagement.logSourcesEnabled: false xpack.observabilityAiAssistantManagement.spacesEnabled: false xpack.observabilityAiAssistantManagement.visibilityEnabled: false diff --git a/x-pack/plugins/search_inference_endpoints/kibana.jsonc b/x-pack/plugins/search_inference_endpoints/kibana.jsonc index 3d8341df35b56..25b7b391b955a 100644 --- a/x-pack/plugins/search_inference_endpoints/kibana.jsonc +++ b/x-pack/plugins/search_inference_endpoints/kibana.jsonc @@ -11,9 +11,23 @@ "id": "searchInferenceEndpoints", "server": true, "browser": true, - "configPath": ["xpack", "searchInferenceEndpoints"], - "requiredPlugins": ["actions", "features", "ml", "share"], - "optionalPlugins": ["cloud", "console", "serverless"], - "requiredBundles": ["kibanaReact"] + "configPath": [ + "xpack", + "searchInferenceEndpoints" + ], + "requiredPlugins": [ + "actions", + "features", + "ml", + "share", + ], + "optionalPlugins": [ + "cloud", + "console", + "serverless" + ], + "requiredBundles": [ + "kibanaReact" + ] } } From 9679312a07226c53fd699b8aabbca31a4dc9f4ec Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Mon, 18 Nov 2024 15:01:55 -0500 Subject: [PATCH 06/19] Adding useCallBack to remove reinitialization --- .../render_actions/actions/component/index_item.tsx | 8 ++++---- .../render_actions/actions/component/pipeline_item.tsx | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.tsx index 1f19d6e4d002b..a62a9b9f3caed 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.tsx @@ -16,7 +16,7 @@ import { EuiIcon, EuiSpacer, } from '@elastic/eui'; -import React from 'react'; +import React, { useCallback } from 'react'; import { ENTERPRISE_SEARCH_CONTENT_APP_ID } from '@kbn/deeplinks-search'; import { SEARCH_INDICES } from '@kbn/deeplinks-search/constants'; @@ -32,7 +32,7 @@ export const IndexItem: React.FC = ({ usageItem }) => { const { services: { application, serverless }, } = useKibana(); - const navigateToIndex = async () => { + const navigateToIndex = useCallback(() => { if (serverless) { application?.navigateToApp(SEARCH_INDICES, { path: `${SERVERLESS_INDEX_MANAGEMENT_URL}/${usageItem.id}/data`, @@ -44,7 +44,7 @@ export const IndexItem: React.FC = ({ usageItem }) => { openInNewTab: true, }); } - }; + }, [application, serverless, usageItem.id]); return ( @@ -65,7 +65,7 @@ export const IndexItem: React.FC = ({ usageItem }) => { - {' '} + diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx index fd1017c1f5bbd..1a2e8ead29080 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx @@ -16,7 +16,7 @@ import { EuiIcon, EuiSpacer, } from '@elastic/eui'; -import React from 'react'; +import React, { useCallback } from 'react'; import { MANAGEMENT_APP_ID } from '@kbn/deeplinks-management/constants'; import { useKibana } from '../../../../../../hooks/use_kibana'; @@ -30,12 +30,12 @@ export const PipelineItem: React.FC = ({ usageItem }) => { const { services: { application }, } = useKibana(); - const navigateToPipeline = () => { + const navigateToPipeline = useCallback(() => { application?.navigateToApp(MANAGEMENT_APP_ID, { path: `${PIPELINE_URL}?pipeline=${usageItem.id}`, openInNewTab: true, }); - }; + }, [application, usageItem.id]); return ( From 4a7ec9411b2eb9bd49ae04617c5d1f400fe952ac Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Tue, 19 Nov 2024 21:42:52 -0500 Subject: [PATCH 07/19] Update navigation config for navigation ftr tests --- .../functional/services/svl_search_navigation.ts | 12 +++++------- .../functional/test_suites/search/config.ts | 3 +++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/x-pack/test_serverless/functional/services/svl_search_navigation.ts b/x-pack/test_serverless/functional/services/svl_search_navigation.ts index 01e8d5d34975f..efea7dc61f4ed 100644 --- a/x-pack/test_serverless/functional/services/svl_search_navigation.ts +++ b/x-pack/test_serverless/functional/services/svl_search_navigation.ts @@ -48,14 +48,12 @@ export function SvlSearchNavigationServiceProvider({ await testSubjects.existOrFail('searchIndicesDetailsPage', { timeout: 2000 }); }, async navigateToInferenceManagementPage(expectRedirect: boolean = false) { - await retry.tryForTime(60 * 1000, async () => { - await PageObjects.common.navigateToApp('searchInferenceEndpoints', { - shouldLoginIfPrompted: false, - }); - if (!expectRedirect) { - await testSubjects.existOrFail('inferenceManagementPage', { timeout: 2000 }); - } + await PageObjects.common.navigateToApp('searchInferenceEndpoints', { + shouldLoginIfPrompted: false, }); + if (!expectRedirect) { + await testSubjects.existOrFail('inferenceManagementPage', { timeout: 2000 }); + } }, }; } diff --git a/x-pack/test_serverless/functional/test_suites/search/config.ts b/x-pack/test_serverless/functional/test_suites/search/config.ts index 5c52828a11659..a58efad9a8043 100644 --- a/x-pack/test_serverless/functional/test_suites/search/config.ts +++ b/x-pack/test_serverless/functional/test_suites/search/config.ts @@ -45,5 +45,8 @@ export default createTestConfig({ elasticsearchIndices: { pathname: '/app/elasticsearch/indices', }, + searchInferenceEndpoints: { + pathname: '/app/search_inference_endpoints', + }, }, }); From 86d38d9ae1a8dfdd202e224b5622d50ff30f3353 Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Tue, 19 Nov 2024 23:16:33 -0500 Subject: [PATCH 08/19] update tests for preconfigured and other scenarios --- .../svl_search_inference_management_page.ts | 103 ++++++++++-------- .../search/inference_management.ts | 28 +---- 2 files changed, 62 insertions(+), 69 deletions(-) diff --git a/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts b/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts index 48c6a859de097..4424238a9c809 100644 --- a/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts +++ b/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts @@ -11,22 +11,8 @@ import { FtrProviderContext } from '../ftr_provider_context'; export function SvlSearchInferenceManagementPageProvider({ getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const browser = getService('browser'); - const retry = getService('retry'); return { - InferenceEmptyPage: { - async expectComponentsToBeExist() { - const endpointDesc = await testSubjects.find('createFirstInferenceEndpointDescription'); - const endpointDescMsg = await endpointDesc.getVisibleText(); - expect(endpointDescMsg).to.contain( - "Inference endpoints enable you to perform inference tasks using NLP models provided by third-party services or Elastic's built-in models like ELSER and E5. Set up tasks such as text embedding, completions, reranking, and more by using the Create Inference API." - ); - await testSubjects.existOrFail('learn-how-to-create-inference-endpoints'); - await testSubjects.existOrFail('view-your-models'); - await testSubjects.existOrFail('semantic-search-with-elser'); - await testSubjects.existOrFail('semantic-search-with-e5'); - }, - }, InferenceTabularPage: { async expectHeaderToBeExist() { await testSubjects.existOrFail('allInferenceEndpointsPage'); @@ -41,41 +27,68 @@ export function SvlSearchInferenceManagementPageProvider({ getService }: FtrProv const table = await testSubjects.find('inferenceEndpointTable'); const rows = await table.findAllByClassName('euiTableRow'); - expect(rows.length).to.equal(1); + expect(rows.length).to.equal(2); - const endpointCell = await rows[0].findByTestSubject('endpointCell'); - const endpointName = await endpointCell.getVisibleText(); - expect(endpointName).to.contain('endpoint-1'); + const elserEndpointCell = await rows[0].findByTestSubject('endpointCell'); + const elserEndpointName = await elserEndpointCell.getVisibleText(); + expect(elserEndpointName).to.contain('.elser-2-elasticsearch'); - const providerCell = await rows[0].findByTestSubject('providerCell'); - const providerName = await providerCell.getVisibleText(); - expect(providerName).to.contain('Elasticsearch'); - expect(providerName).to.contain('.elser_model_2'); + const elserProviderCell = await rows[0].findByTestSubject('providerCell'); + const elserProviderName = await elserProviderCell.getVisibleText(); + expect(elserProviderName).to.contain('Elasticsearch'); + expect(elserProviderName).to.contain('.elser_model_2'); - const typeCell = await rows[0].findByTestSubject('typeCell'); - const typeName = await typeCell.getVisibleText(); - expect(typeName).to.contain('sparse_embedding'); + const elserTypeCell = await rows[0].findByTestSubject('typeCell'); + const elserTypeName = await elserTypeCell.getVisibleText(); + expect(elserTypeName).to.contain('sparse_embedding'); + + const e5EndpointCell = await rows[1].findByTestSubject('endpointCell'); + const e5EndpointName = await e5EndpointCell.getVisibleText(); + expect(e5EndpointName).to.contain('.multilingual-e5-small-elasticsearch'); + + const e5ProviderCell = await rows[1].findByTestSubject('providerCell'); + const e5ProviderName = await e5ProviderCell.getVisibleText(); + expect(e5ProviderName).to.contain('Elasticsearch'); + expect(e5ProviderName).to.contain('.multilingual-e5-small'); + + const e5TypeCell = await rows[1].findByTestSubject('typeCell'); + const e5TypeName = await e5TypeCell.getVisibleText(); + expect(e5TypeName).to.contain('text_embedding'); + }, + + async expectPreconfiguredEndpointsCannotBeDeleted() { + const table = await testSubjects.find('inferenceEndpointTable'); + const rows = await table.findAllByClassName('euiTableRow'); + + const elserDeleteAction = await rows[0].findByTestSubject('inferenceUIDeleteAction'); + const e5DeleteAction = await rows[1].findByTestSubject('inferenceUIDeleteAction'); + + expect(await elserDeleteAction.isEnabled()).to.be(false); + expect(await e5DeleteAction.isEnabled()).to.be(false); }, async expectEndpointWithoutUsageTobeDelete() { - await testSubjects.click('inferenceUIDeleteAction'); + const table = await testSubjects.find('inferenceEndpointTable'); + const rows = await table.findAllByClassName('euiTableRow'); + + const userCreatedEndpoint = await rows[2].findByTestSubject('inferenceUIDeleteAction'); + + await userCreatedEndpoint.click(); await testSubjects.existOrFail('deleteModalForInferenceUI'); await testSubjects.existOrFail('deleteModalInferenceEndpointName'); await testSubjects.click('confirmModalConfirmButton'); - await retry.waitForWithTimeout('delete modal to disappear', 5000, () => - testSubjects - .missingOrFail('confirmModalConfirmButton') - .then(() => true) - .catch(() => false) - ); - - await testSubjects.existOrFail('createFirstInferenceEndpointDescription'); + await testSubjects.existOrFail('inferenceEndpointTable'); }, async expectEndpointWithUsageTobeDelete() { - await testSubjects.click('inferenceUIDeleteAction'); + const table = await testSubjects.find('inferenceEndpointTable'); + const rows = await table.findAllByClassName('euiTableRow'); + + const userCreatedEndpoint = await rows[2].findByTestSubject('inferenceUIDeleteAction'); + + await userCreatedEndpoint.click(); await testSubjects.existOrFail('deleteModalForInferenceUI'); await testSubjects.existOrFail('deleteModalInferenceEndpointName'); @@ -95,19 +108,19 @@ export function SvlSearchInferenceManagementPageProvider({ getService }: FtrProv expect(await testSubjects.isEnabled('confirmModalConfirmButton')).to.be(true); await testSubjects.click('confirmModalConfirmButton'); - await retry.waitForWithTimeout('delete modal to disappear', 5000, () => - testSubjects - .missingOrFail('confirmModalConfirmButton') - .then(() => true) - .catch(() => false) - ); - - await testSubjects.existOrFail('createFirstInferenceEndpointDescription'); + await testSubjects.existOrFail('inferenceEndpointTable'); }, async expectToCopyEndpoint() { - await testSubjects.click('inference-endpoints-action-copy-id-label'); - expect((await browser.getClipboardValue()).includes('endpoint-1')).to.be(true); + const table = await testSubjects.find('inferenceEndpointTable'); + const rows = await table.findAllByClassName('euiTableRow'); + + const elserCopyEndpointId = await rows[0].findByTestSubject( + 'inference-endpoints-action-copy-id-label' + ); + + await elserCopyEndpointId.click(); + expect((await browser.getClipboardValue()).includes('.elser-2-elasticsearch')).to.be(true); }, }, }; diff --git a/x-pack/test_serverless/functional/test_suites/search/inference_management.ts b/x-pack/test_serverless/functional/test_suites/search/inference_management.ts index 49a0dee5cee4d..f820b9bb08085 100644 --- a/x-pack/test_serverless/functional/test_suites/search/inference_management.ts +++ b/x-pack/test_serverless/functional/test_suites/search/inference_management.ts @@ -44,38 +44,18 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await svlSearchNavigation.navigateToInferenceManagementPage(); }); - describe('endpoint empty view', () => { - it('is loaded successfully', async () => { - await pageObjects.svlSearchInferenceManagementPage.InferenceEmptyPage.expectComponentsToBeExist(); - }); - }); - describe('endpoint tabular view', () => { - before(async () => { - await ml.api.createInferenceEndpoint(endpoint, taskType, modelConfig); - await browser.refresh(); - }); - - after(async () => { - await ml.api.deleteInferenceEndpoint(endpoint, taskType); - }); - it('is loaded successfully', async () => { await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectHeaderToBeExist(); await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectTabularViewToBeLoaded(); }); - }); - - describe('copy endpoint id action', () => { - beforeEach(async () => { - await ml.api.createInferenceEndpoint(endpoint, taskType, modelConfig); - await browser.refresh(); - }); - after(async () => { - await ml.api.deleteInferenceEndpoint(endpoint, taskType); + it('preconfigured endpoints can not be deleted', async () => { + await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectPreconfiguredEndpointsCannotBeDeleted(); }); + }); + describe('copy endpoint id action', () => { it('can copy an endpoint id', async () => { await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectToCopyEndpoint(); }); From d6d570ca1a98e8cdcf2c734ff73bb3ac17d6033e Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Wed, 20 Nov 2024 14:58:59 -0500 Subject: [PATCH 09/19] Adding locator for plugins ES3 link support --- .../field_parameters/select_inference_id.tsx | 10 ++++-- .../common/constants.ts | 4 +++ .../public/locators.ts | 33 +++++++++++++++++++ .../public/plugin.ts | 7 +++- .../public/types.ts | 10 ++++-- 5 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugins/search_inference_endpoints/public/locators.ts diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx index a9c54aee80360..321ff60998745 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx @@ -82,11 +82,17 @@ const SelectInferenceIdContent: React.FC = ({ const { core: { application, http }, docLinks, - plugins: { ml }, + plugins: { ml, share }, } = useAppContext(); const config = getFieldConfig('inference_id'); - const inferenceEndpointsPageLink = `${http.basePath.get()}/app/enterprise_search/relevance/inference_endpoints`; + // const inferenceEndpointsPageLink = `${http.basePath.get()}/app/enterprise_search/relevance/inference_endpoints`; + + const inferenceEndpointsPageLink = share?.url.locators + .get('SEARCH_INFERENCE_ENDPOINTS') + ?.useUrl({}); + + // console.log('serverless link', inferenceEndpointsPageLink); const [isInferenceFlyoutVisible, setIsInferenceFlyoutVisible] = useState(false); const [availableTrainedModels, setAvailableTrainedModels] = useState< diff --git a/x-pack/plugins/search_inference_endpoints/common/constants.ts b/x-pack/plugins/search_inference_endpoints/common/constants.ts index b76246aa53a49..0dc3c651c9e4d 100644 --- a/x-pack/plugins/search_inference_endpoints/common/constants.ts +++ b/x-pack/plugins/search_inference_endpoints/common/constants.ts @@ -5,8 +5,12 @@ * 2.0. */ +import { SearchInferenceEndpointsId } from '@kbn/deeplinks-search/deep_links'; + export const PLUGIN_ID = 'searchInferenceEndpoints'; export const PLUGIN_NAME = 'Inference Endpoints'; export const INFERENCE_ENDPOINTS_QUERY_KEY = 'inferenceEndpointsQueryKey'; export const TRAINED_MODEL_STATS_QUERY_KEY = 'trainedModelStats'; + +export const SEARCH_INFERENCE_ENDPOINTS: SearchInferenceEndpointsId = 'searchInferenceEndpoints'; diff --git a/x-pack/plugins/search_inference_endpoints/public/locators.ts b/x-pack/plugins/search_inference_endpoints/public/locators.ts new file mode 100644 index 0000000000000..18394149919b2 --- /dev/null +++ b/x-pack/plugins/search_inference_endpoints/public/locators.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { LocatorDefinition } from '@kbn/share-plugin/common'; +import type { SharePluginSetup } from '@kbn/share-plugin/public'; +import type { SerializableRecord } from '@kbn/utility-types'; + +import { SEARCH_INFERENCE_ENDPOINTS } from '../common/constants'; +import { SEARCH_INFERENCE_ENDPOINTS_PATH } from './routes'; + +export function registerLocators(share: SharePluginSetup) { + share.url.locators.create( + new CreateSearchInferenceEndpointLocatorDefinition() + ); +} + +class CreateSearchInferenceEndpointLocatorDefinition + implements LocatorDefinition +{ + public readonly getLocation = async () => { + return { + app: SEARCH_INFERENCE_ENDPOINTS, + path: SEARCH_INFERENCE_ENDPOINTS_PATH, + state: {}, + }; + }; + + public readonly id = 'SEARCH_INFERENCE_ENDPOINTS'; +} diff --git a/x-pack/plugins/search_inference_endpoints/public/plugin.ts b/x-pack/plugins/search_inference_endpoints/public/plugin.ts index a864b7c0fcdd6..10f5b9e3a776c 100644 --- a/x-pack/plugins/search_inference_endpoints/public/plugin.ts +++ b/x-pack/plugins/search_inference_endpoints/public/plugin.ts @@ -16,12 +16,14 @@ import { PLUGIN_ID, PLUGIN_NAME } from '../common/constants'; import { docLinks } from '../common/doc_links'; import { InferenceEndpoints, getInferenceEndpointsProvider } from './embeddable'; import { + AppPluginSetupDependencies, AppPluginStartDependencies, SearchInferenceEndpointsConfigType, SearchInferenceEndpointsPluginSetup, SearchInferenceEndpointsPluginStart, } from './types'; import { INFERENCE_ENDPOINTS_UI_FLAG } from '.'; +import { registerLocators } from './locators'; export class SearchInferenceEndpointsPlugin implements Plugin @@ -33,7 +35,8 @@ export class SearchInferenceEndpointsPlugin } public setup( - core: CoreSetup + core: CoreSetup, + plugins: AppPluginSetupDependencies ): SearchInferenceEndpointsPluginSetup { if ( !this.config.ui?.enabled && @@ -56,6 +59,8 @@ export class SearchInferenceEndpointsPlugin }, }); + registerLocators(plugins.share); + return {}; } diff --git a/x-pack/plugins/search_inference_endpoints/public/types.ts b/x-pack/plugins/search_inference_endpoints/public/types.ts index ab8f6733db4d4..4fa060da6cf82 100644 --- a/x-pack/plugins/search_inference_endpoints/public/types.ts +++ b/x-pack/plugins/search_inference_endpoints/public/types.ts @@ -5,11 +5,11 @@ * 2.0. */ -import type { ConsolePluginStart } from '@kbn/console-plugin/public'; +import type { ConsolePluginSetup, ConsolePluginStart } from '@kbn/console-plugin/public'; import { HttpStart } from '@kbn/core-http-browser'; import { AppMountParameters } from '@kbn/core/public'; import { MlPluginStart } from '@kbn/ml-plugin/public'; -import { SharePluginStart } from '@kbn/share-plugin/public'; +import { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public'; import React from 'react'; import { ServerlessPluginStart } from '@kbn/serverless/public'; @@ -32,6 +32,12 @@ export interface AppPluginStartDependencies { serverless?: ServerlessPluginStart; } +export interface AppPluginSetupDependencies { + history: AppMountParameters['history']; + share: SharePluginSetup; + console?: ConsolePluginSetup; +} + export interface AppServicesContext { http: HttpStart; ml?: MlPluginStart; From 690f6db8d9292725f81556c9808f0c161197bfaa Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 20 Nov 2024 20:21:47 +0000 Subject: [PATCH 10/19] [CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix' --- x-pack/plugins/search_inference_endpoints/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/search_inference_endpoints/tsconfig.json b/x-pack/plugins/search_inference_endpoints/tsconfig.json index e181bfbf0a540..8e5f55db3e0db 100644 --- a/x-pack/plugins/search_inference_endpoints/tsconfig.json +++ b/x-pack/plugins/search_inference_endpoints/tsconfig.json @@ -29,7 +29,8 @@ "@kbn/ui-theme", "@kbn/deeplinks-search", "@kbn/deeplinks-management", - "@kbn/serverless" + "@kbn/serverless", + "@kbn/utility-types" ], "exclude": ["target/**/*"] } From a33a1c0ee71a48741155203315413b1856a5eab8 Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Wed, 20 Nov 2024 17:11:16 -0500 Subject: [PATCH 11/19] Adding locator support for inference management in enterprise search --- .../enterprise_search/common/constants.ts | 2 +- .../common/locators/index.ts | 3 ++ .../common/locators/inference_locator.tsx | 30 ++++++++++++ .../field_parameters/select_inference_id.tsx | 46 +++++++++---------- .../public/locators.ts | 12 ++--- .../public/plugin.ts | 16 ++++++- 6 files changed, 76 insertions(+), 33 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/common/locators/inference_locator.tsx diff --git a/x-pack/plugins/enterprise_search/common/constants.ts b/x-pack/plugins/enterprise_search/common/constants.ts index 0c13a772862b8..2603ea3d89018 100644 --- a/x-pack/plugins/enterprise_search/common/constants.ts +++ b/x-pack/plugins/enterprise_search/common/constants.ts @@ -211,7 +211,7 @@ export const SEARCH_RELEVANCE_PLUGIN = { DESCRIPTION: i18n.translate('xpack.enterpriseSearch.inferenceEndpoints.description', { defaultMessage: 'Manage your inference endpoints for semantic search and AI use cases.', }), - URL: '/app/enterprise_search/relevance', + URL: '/app/elasticsearch/relevance', LOGO: 'logoEnterpriseSearch', SUPPORT_URL: 'https://discuss.elastic.co/c/enterprise-search/', }; diff --git a/x-pack/plugins/enterprise_search/common/locators/index.ts b/x-pack/plugins/enterprise_search/common/locators/index.ts index 0f9d2060cd829..35c1d43b3b30a 100644 --- a/x-pack/plugins/enterprise_search/common/locators/index.ts +++ b/x-pack/plugins/enterprise_search/common/locators/index.ts @@ -6,14 +6,17 @@ */ import type { SharePluginSetup } from '@kbn/share-plugin/public'; +import { SerializableRecord } from '@kbn/utility-types'; import { CreateIndexLocatorDefinition, type CreateIndexLocatorParams, } from './create_index_locator'; +import { SearchInferenceEndpointLocatorDefinition } from './inference_locator'; import { PlaygroundLocatorDefinition, type PlaygroundLocatorParams } from './playground_locator'; export function registerLocators(share: SharePluginSetup) { share.url.locators.create(new CreateIndexLocatorDefinition()); share.url.locators.create(new PlaygroundLocatorDefinition()); + share.url.locators.create(new SearchInferenceEndpointLocatorDefinition()); } diff --git a/x-pack/plugins/enterprise_search/common/locators/inference_locator.tsx b/x-pack/plugins/enterprise_search/common/locators/inference_locator.tsx new file mode 100644 index 0000000000000..f20d628bf1899 --- /dev/null +++ b/x-pack/plugins/enterprise_search/common/locators/inference_locator.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { LocatorDefinition } from '@kbn/share-plugin/common'; +import type { SharePluginSetup } from '@kbn/share-plugin/public'; +import type { SerializableRecord } from '@kbn/utility-types'; + +import { SEARCH_RELEVANCE_PLUGIN } from '../constants'; + +export function registerLocators(share: SharePluginSetup) { + share.url.locators.create(new SearchInferenceEndpointLocatorDefinition()); +} + +export class SearchInferenceEndpointLocatorDefinition + implements LocatorDefinition +{ + public readonly getLocation = async () => { + return { + app: SEARCH_RELEVANCE_PLUGIN.ID, + path: '/inference_endpoints', + state: {}, + }; + }; + + public readonly id = 'SEARCH_INFERENCE_ENDPOINTS'; +} diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx index 321ff60998745..b2b610697ca99 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx @@ -80,20 +80,16 @@ const SelectInferenceIdContent: React.FC = ({ value, }) => { const { - core: { application, http }, + core: { application }, docLinks, plugins: { ml, share }, } = useAppContext(); const config = getFieldConfig('inference_id'); - // const inferenceEndpointsPageLink = `${http.basePath.get()}/app/enterprise_search/relevance/inference_endpoints`; - const inferenceEndpointsPageLink = share?.url.locators .get('SEARCH_INFERENCE_ENDPOINTS') ?.useUrl({}); - // console.log('serverless link', inferenceEndpointsPageLink); - const [isInferenceFlyoutVisible, setIsInferenceFlyoutVisible] = useState(false); const [availableTrainedModels, setAvailableTrainedModels] = useState< TrainedModelConfigResponse[] @@ -230,24 +226,28 @@ const SelectInferenceIdContent: React.FC = ({ panelPaddingSize="m" closePopover={() => setIsInferencePopoverVisible(!isInferencePopoverVisible)} > - - { - application.navigateToUrl(inferenceEndpointsPageLink); - }} - > - {i18n.translate( - 'xpack.idxMgmt.mappingsEditor.parameters.inferenceId.popover.manageInferenceEndpointButton', - { - defaultMessage: 'Manage Inference Endpoints', - } - )} - - + {inferenceEndpointsPageLink && ( + + { + e.preventDefault(); + application.navigateToUrl(inferenceEndpointsPageLink); + }} + > + {i18n.translate( + 'xpack.idxMgmt.mappingsEditor.parameters.inferenceId.popover.manageInferenceEndpointButton', + { + defaultMessage: 'Manage Inference Endpoints', + } + )} + + + )} diff --git a/x-pack/plugins/search_inference_endpoints/public/locators.ts b/x-pack/plugins/search_inference_endpoints/public/locators.ts index 18394149919b2..5b32e5648cc7c 100644 --- a/x-pack/plugins/search_inference_endpoints/public/locators.ts +++ b/x-pack/plugins/search_inference_endpoints/public/locators.ts @@ -9,21 +9,17 @@ import type { LocatorDefinition } from '@kbn/share-plugin/common'; import type { SharePluginSetup } from '@kbn/share-plugin/public'; import type { SerializableRecord } from '@kbn/utility-types'; -import { SEARCH_INFERENCE_ENDPOINTS } from '../common/constants'; +import { PLUGIN_ID } from '../common/constants'; import { SEARCH_INFERENCE_ENDPOINTS_PATH } from './routes'; export function registerLocators(share: SharePluginSetup) { - share.url.locators.create( - new CreateSearchInferenceEndpointLocatorDefinition() - ); + share.url.locators.create(new SearchInferenceEndpointLocatorDefinition()); } -class CreateSearchInferenceEndpointLocatorDefinition - implements LocatorDefinition -{ +class SearchInferenceEndpointLocatorDefinition implements LocatorDefinition { public readonly getLocation = async () => { return { - app: SEARCH_INFERENCE_ENDPOINTS, + app: PLUGIN_ID, path: SEARCH_INFERENCE_ENDPOINTS_PATH, state: {}, }; diff --git a/x-pack/plugins/search_inference_endpoints/public/plugin.ts b/x-pack/plugins/search_inference_endpoints/public/plugin.ts index 10f5b9e3a776c..9afd22c3dc5cb 100644 --- a/x-pack/plugins/search_inference_endpoints/public/plugin.ts +++ b/x-pack/plugins/search_inference_endpoints/public/plugin.ts @@ -12,6 +12,7 @@ import { Plugin, PluginInitializerContext, } from '@kbn/core/public'; +import { i18n } from '@kbn/i18n'; import { PLUGIN_ID, PLUGIN_NAME } from '../common/constants'; import { docLinks } from '../common/doc_links'; import { InferenceEndpoints, getInferenceEndpointsProvider } from './embeddable'; @@ -24,6 +25,7 @@ import { } from './types'; import { INFERENCE_ENDPOINTS_UI_FLAG } from '.'; import { registerLocators } from './locators'; +import { INFERENCE_ENDPOINTS_PATH } from './components/routes'; export class SearchInferenceEndpointsPlugin implements Plugin @@ -45,7 +47,19 @@ export class SearchInferenceEndpointsPlugin return {}; core.application.register({ id: PLUGIN_ID, - appRoute: '/app/search_inference_endpoints', + appRoute: '/app/elasticsearch/relevance', + deepLinks: [ + { + id: 'inferenceEndpoints', + path: `/${INFERENCE_ENDPOINTS_PATH}`, + title: i18n.translate( + 'xpack.enterpriseSearch.navigation.relevanceInferenceEndpointsLinkLabel', + { + defaultMessage: 'Inference Endpoints', + } + ), + }, + ], title: PLUGIN_NAME, async mount({ element, history }: AppMountParameters) { const { renderApp } = await import('./application'); From 43c794ae08ec8318bc6e4a2c17c22760f83569ce Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Wed, 20 Nov 2024 17:16:23 -0500 Subject: [PATCH 12/19] Fix nav tests due to update plugin link --- .../public/applications/shared/layout/nav.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx index 3305e92dd8d9e..a6cbf56691735 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx @@ -101,7 +101,7 @@ const baseNavItems = [ items: [ { 'data-test-subj': 'searchSideNav-InferenceEndpoints', - href: '/app/enterprise_search/relevance/inference_endpoints', + href: '/app/elasticsearch/relevance/inference_endpoints', id: 'inference_endpoints', items: undefined, name: 'Inference Endpoints', @@ -205,7 +205,7 @@ const mockNavLinks = [ { id: 'searchInferenceEndpoints:inferenceEndpoints', title: 'Inference Endpoints', - url: '/app/enterprise_search/relevance/inference_endpoints', + url: '/app/elasticsearch/relevance/inference_endpoints', }, { id: 'appSearch:engines', From 1ab1d82cbd9e9b5f4da50f513a139e1f59317a93 Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Wed, 20 Nov 2024 17:32:59 -0500 Subject: [PATCH 13/19] Update api documentation link to create inference endpoint --- packages/kbn-doc-links/src/get_doc_links.ts | 3 +++ packages/kbn-doc-links/src/types.ts | 3 +++ .../document_fields/field_parameters/select_inference_id.tsx | 2 +- x-pack/plugins/search_inference_endpoints/common/doc_links.ts | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index a31e1f1641e8b..44bd57ed8f3d1 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -1001,5 +1001,8 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D context: `${KIBANA_DOCS}playground-context.html`, hiddenFields: `${KIBANA_DOCS}playground-query.html#playground-hidden-fields`, }, + inferenceManagement: { + inferenceAPIDocumentation: `${ELASTIC_WEBSITE_URL}docs/api/doc/elasticsearch/operation/operation-inference-put`, + }, }); }; diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index ac0f66d83b705..a344d2d694c05 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -676,6 +676,9 @@ export interface DocLinks { readonly context: string; readonly hiddenFields: string; }; + readonly inferenceManagement: { + readonly inferenceAPIDocumentation: string; + }; } export type BuildFlavor = 'serverless' | 'traditional'; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx index b2b610697ca99..51cd2b5f14789 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx @@ -298,7 +298,7 @@ const SelectInferenceIdContent: React.FC = ({ } size="s"> diff --git a/x-pack/plugins/search_inference_endpoints/common/doc_links.ts b/x-pack/plugins/search_inference_endpoints/common/doc_links.ts index bb426180a36e8..483803e970d82 100644 --- a/x-pack/plugins/search_inference_endpoints/common/doc_links.ts +++ b/x-pack/plugins/search_inference_endpoints/common/doc_links.ts @@ -15,7 +15,7 @@ class InferenceEndpointsDocLinks { constructor() {} setDocLinks(newDocLinks: DocLinks) { - this.createInferenceEndpoint = newDocLinks.enterpriseSearch.inferenceApiCreate; + this.createInferenceEndpoint = newDocLinks.inferenceManagement.inferenceAPIDocumentation; this.semanticSearchElser = newDocLinks.enterpriseSearch.elser; this.semanticSearchE5 = newDocLinks.enterpriseSearch.e5Model; } From 83da4abe6509c09bead7af1ab513b9fc72af0ac4 Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Wed, 20 Nov 2024 18:04:04 -0500 Subject: [PATCH 14/19] Remove redundant tests and added type import --- x-pack/plugins/search_inference_endpoints/public/types.ts | 2 +- .../functional/services/svl_search_navigation.ts | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/x-pack/plugins/search_inference_endpoints/public/types.ts b/x-pack/plugins/search_inference_endpoints/public/types.ts index 4fa060da6cf82..9f73d0d0033b0 100644 --- a/x-pack/plugins/search_inference_endpoints/public/types.ts +++ b/x-pack/plugins/search_inference_endpoints/public/types.ts @@ -12,7 +12,7 @@ import { MlPluginStart } from '@kbn/ml-plugin/public'; import { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public'; import React from 'react'; -import { ServerlessPluginStart } from '@kbn/serverless/public'; +import type { ServerlessPluginStart } from '@kbn/serverless/public'; import type { App } from './components/app'; import type { InferenceEndpointsProvider } from './providers/inference_endpoints_provider'; diff --git a/x-pack/test_serverless/functional/services/svl_search_navigation.ts b/x-pack/test_serverless/functional/services/svl_search_navigation.ts index efea7dc61f4ed..434a5bd4e42ab 100644 --- a/x-pack/test_serverless/functional/services/svl_search_navigation.ts +++ b/x-pack/test_serverless/functional/services/svl_search_navigation.ts @@ -51,9 +51,6 @@ export function SvlSearchNavigationServiceProvider({ await PageObjects.common.navigateToApp('searchInferenceEndpoints', { shouldLoginIfPrompted: false, }); - if (!expectRedirect) { - await testSubjects.existOrFail('inferenceManagementPage', { timeout: 2000 }); - } }, }; } From 4361cb79bc83e42bf63e4eca9942105c7ab5f96f Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Wed, 20 Nov 2024 18:32:50 -0500 Subject: [PATCH 15/19] fixing i18n issues --- .../search_inference_endpoints/common/constants.ts | 4 ---- .../plugins/search_inference_endpoints/public/plugin.ts | 9 +++------ 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/search_inference_endpoints/common/constants.ts b/x-pack/plugins/search_inference_endpoints/common/constants.ts index 0dc3c651c9e4d..b76246aa53a49 100644 --- a/x-pack/plugins/search_inference_endpoints/common/constants.ts +++ b/x-pack/plugins/search_inference_endpoints/common/constants.ts @@ -5,12 +5,8 @@ * 2.0. */ -import { SearchInferenceEndpointsId } from '@kbn/deeplinks-search/deep_links'; - export const PLUGIN_ID = 'searchInferenceEndpoints'; export const PLUGIN_NAME = 'Inference Endpoints'; export const INFERENCE_ENDPOINTS_QUERY_KEY = 'inferenceEndpointsQueryKey'; export const TRAINED_MODEL_STATS_QUERY_KEY = 'trainedModelStats'; - -export const SEARCH_INFERENCE_ENDPOINTS: SearchInferenceEndpointsId = 'searchInferenceEndpoints'; diff --git a/x-pack/plugins/search_inference_endpoints/public/plugin.ts b/x-pack/plugins/search_inference_endpoints/public/plugin.ts index 9afd22c3dc5cb..cb60f611b3bb3 100644 --- a/x-pack/plugins/search_inference_endpoints/public/plugin.ts +++ b/x-pack/plugins/search_inference_endpoints/public/plugin.ts @@ -52,12 +52,9 @@ export class SearchInferenceEndpointsPlugin { id: 'inferenceEndpoints', path: `/${INFERENCE_ENDPOINTS_PATH}`, - title: i18n.translate( - 'xpack.enterpriseSearch.navigation.relevanceInferenceEndpointsLinkLabel', - { - defaultMessage: 'Inference Endpoints', - } - ), + title: i18n.translate('xpack.searchInferenceEndpoints.InferenceEndpointsLinkLabel', { + defaultMessage: 'Inference Endpoints', + }), }, ], title: PLUGIN_NAME, From 41d3620ced466bcc13cca89c321f64f88f6188dd Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Wed, 20 Nov 2024 18:35:27 -0500 Subject: [PATCH 16/19] fixing formatting issue in tsconfig file --- .../search_inference_endpoints/tsconfig.json | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/search_inference_endpoints/tsconfig.json b/x-pack/plugins/search_inference_endpoints/tsconfig.json index 8e5f55db3e0db..9a5b160779e7a 100644 --- a/x-pack/plugins/search_inference_endpoints/tsconfig.json +++ b/x-pack/plugins/search_inference_endpoints/tsconfig.json @@ -1,9 +1,14 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "outDir": "target/types" + "outDir": "target/types", }, - "include": ["__mocks__/**/*", "common/**/*", "public/**/*", "server/**/*"], + "include": [ + "__mocks__/**/*", + "common/**/*", + "public/**/*", + "server/**/*" + ], "kbn_references": [ "@kbn/config-schema", "@kbn/core", @@ -32,5 +37,7 @@ "@kbn/serverless", "@kbn/utility-types" ], - "exclude": ["target/**/*"] + "exclude": [ + "target/**/*", + ] } From 4b757e19a7aa6cfc049603ca31d1518777fc15d4 Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Thu, 21 Nov 2024 12:35:03 -0500 Subject: [PATCH 17/19] Fixing semantic_text field tests --- .../index_details_page.test.tsx | 23 ++++++++++++++++++- .../select_inference_id.test.tsx | 23 +++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx index 5a97dadc870cb..4badcc04540b1 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx @@ -727,6 +727,11 @@ describe('', () => { isActive: true, hasAtLeast: jest.fn((type) => true), }; + const INFERENCE_LOCATOR = 'SEARCH_INFERENCE_ENDPOINTS'; + const createMockLocator = (id: string) => ({ + useUrl: jest.fn().mockReturnValue('https://redirect.me/to/inference_endpoints'), + }); + const mockInferenceManagementLocator = createMockLocator(INFERENCE_LOCATOR); beforeEach(async () => { httpRequestsMockHelpers.setInferenceModels({ data: [ @@ -750,7 +755,9 @@ describe('', () => { docLinks: { links: { ml: '', - enterpriseSearch: '', + inferenceManagement: { + inferenceAPIDocumentation: 'https://abc.com/inference-api-create', + }, }, }, core: { @@ -819,6 +826,20 @@ describe('', () => { }, }, }, + share: { + url: { + locators: { + get: jest.fn((id) => { + switch (id) { + case INFERENCE_LOCATOR: + return mockInferenceManagementLocator; + default: + throw new Error(`Unknown locator id: ${id}`); + } + }), + }, + }, + }, }, }, }); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx index 2fb9165e8fd10..1c9633f829bc3 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx @@ -20,6 +20,11 @@ import { InferenceAPIConfigResponse } from '@kbn/ml-trained-models-utils'; const createInferenceEndpointMock = jest.fn(); const mockDispatch = jest.fn(); +const INFERENCE_LOCATOR = 'SEARCH_INFERENCE_ENDPOINTS'; +const createMockLocator = (id: string) => ({ + useUrl: jest.fn().mockReturnValue('https://redirect.me/to/inference_endpoints'), +}); +const mockInferenceManagementLocator = createMockLocator(INFERENCE_LOCATOR); jest.mock('../../../public/application/app_context', () => ({ useAppContext: jest.fn().mockReturnValue({ @@ -33,8 +38,8 @@ jest.mock('../../../public/application/app_context', () => ({ }, docLinks: { links: { - enterpriseSearch: { - inferenceApiCreate: 'https://abc.com/inference-api-create', + inferenceManagement: { + inferenceAPIDocumentation: 'https://abc.com/inference-api-create', }, }, }, @@ -47,6 +52,20 @@ jest.mock('../../../public/application/app_context', () => ({ }, }, }, + share: { + url: { + locators: { + get: jest.fn((id) => { + switch (id) { + case INFERENCE_LOCATOR: + return mockInferenceManagementLocator; + default: + throw new Error(`Unknown locator id: ${id}`); + } + }), + }, + }, + }, }, }), })); From 7cd2d916ce58700b71d99ed880da18332e5734a6 Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Thu, 21 Nov 2024 18:13:08 -0500 Subject: [PATCH 18/19] Fix navigation issue with FTR tests --- x-pack/test_serverless/functional/test_suites/search/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test_serverless/functional/test_suites/search/config.ts b/x-pack/test_serverless/functional/test_suites/search/config.ts index a58efad9a8043..47763068455b5 100644 --- a/x-pack/test_serverless/functional/test_suites/search/config.ts +++ b/x-pack/test_serverless/functional/test_suites/search/config.ts @@ -46,7 +46,7 @@ export default createTestConfig({ pathname: '/app/elasticsearch/indices', }, searchInferenceEndpoints: { - pathname: '/app/search_inference_endpoints', + pathname: '/app/elasticsearch/relevance/inference_endpoints', }, }, }); From 505d488d14fbb1b7838ad4d27a41e9752800c5de Mon Sep 17 00:00:00 2001 From: Samiul Monir Date: Fri, 22 Nov 2024 11:56:34 -0500 Subject: [PATCH 19/19] Removing empty state from search inference plugin --- .../common/translations.ts | 62 ----------- .../empty_prompt/add_empty_prompt.scss | 3 - .../empty_prompt/add_empty_prompt.test.tsx | 47 -------- .../empty_prompt/add_empty_prompt.tsx | 103 ------------------ .../empty_prompt/endpoint_prompt.tsx | 27 ----- .../public/components/empty_prompt/index.ts | 8 -- .../public/components/inference_endpoints.tsx | 9 +- .../translations/translations/fr-FR.json | 9 -- .../translations/translations/ja-JP.json | 9 -- .../translations/translations/zh-CN.json | 9 -- 10 files changed, 2 insertions(+), 284 deletions(-) delete mode 100644 x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.scss delete mode 100644 x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx delete mode 100644 x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx delete mode 100644 x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx delete mode 100644 x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/index.ts diff --git a/x-pack/plugins/search_inference_endpoints/common/translations.ts b/x-pack/plugins/search_inference_endpoints/common/translations.ts index 0f1aa4a8abcfc..8b63725c59f96 100644 --- a/x-pack/plugins/search_inference_endpoints/common/translations.ts +++ b/x-pack/plugins/search_inference_endpoints/common/translations.ts @@ -26,49 +26,6 @@ export const MANAGE_INFERENCE_ENDPOINTS_LABEL = i18n.translate( } ); -export const CREATE_FIRST_INFERENCE_ENDPOINT_DESCRIPTION = i18n.translate( - 'xpack.searchInferenceEndpoints.addEmptyPrompt.createFirstInferenceEndpointDescription', - { - defaultMessage: - "Inference endpoints enable you to perform inference tasks using NLP models provided by third-party services or Elastic's built-in models like ELSER and E5. Set up tasks such as text embedding, completions, reranking, and more by using the Create Inference API.", - } -); - -export const START_WITH_PREPARED_ENDPOINTS_LABEL = i18n.translate( - 'xpack.searchInferenceEndpoints.addEmptyPrompt.startWithPreparedEndpointsLabel', - { - defaultMessage: 'Learn more about built-in NLP models:', - } -); - -export const ELSER_TITLE = i18n.translate( - 'xpack.searchInferenceEndpoints.addEmptyPrompt.elserTitle', - { - defaultMessage: 'ELSER', - } -); - -export const LEARN_HOW_TO_CREATE_INFERENCE_ENDPOINTS_LINK = i18n.translate( - 'xpack.searchInferenceEndpoints.addEmptyPrompt.learnHowToCreateInferenceEndpoints', - { - defaultMessage: 'Learn how to create inference endpoints', - } -); - -export const SEMANTIC_SEARCH_WITH_ELSER_LINK = i18n.translate( - 'xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithElser', - { - defaultMessage: 'Semantic search with ELSER', - } -); - -export const SEMANTIC_SEARCH_WITH_E5_LINK = i18n.translate( - 'xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithE5', - { - defaultMessage: 'Semantic search with E5 Multilingual', - } -); - export const VIEW_YOUR_MODELS_LINK = i18n.translate( 'xpack.searchInferenceEndpoints.viewYourModels', { @@ -83,25 +40,6 @@ export const API_DOCUMENTATION_LINK = i18n.translate( } ); -export const ELSER_DESCRIPTION = i18n.translate( - 'xpack.searchInferenceEndpoints.addEmptyPrompt.elserDescription', - { - defaultMessage: "ELSER is Elastic's sparse vector NLP model for semantic search in English.", - } -); - -export const E5_TITLE = i18n.translate('xpack.searchInferenceEndpoints.addEmptyPrompt.e5Title', { - defaultMessage: 'E5 Multilingual', -}); - -export const E5_DESCRIPTION = i18n.translate( - 'xpack.searchInferenceEndpoints.addEmptyPrompt.e5Description', - { - defaultMessage: - 'E5 is a third-party NLP model that enables you to perform multilingual semantic search by using dense vector representations.', - } -); - export const ERROR_TITLE = i18n.translate('xpack.searchInferenceEndpoints.inferenceId.errorTitle', { defaultMessage: 'Error adding inference endpoint', }); diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.scss b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.scss deleted file mode 100644 index b85859948b0be..0000000000000 --- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.scss +++ /dev/null @@ -1,3 +0,0 @@ -.addEmptyPrompt { - max-width: 860px; -} \ No newline at end of file diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx deleted file mode 100644 index 755c1f0a1de54..0000000000000 --- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { screen } from '@testing-library/react'; -import { AddEmptyPrompt } from './add_empty_prompt'; - -import { renderReactTestingLibraryWithI18n as render } from '@kbn/test-jest-helpers'; -import '@testing-library/jest-dom'; - -describe('When empty prompt is loaded', () => { - beforeEach(() => { - render(); - }); - - it('should display the description for creation of the first inference endpoint', () => { - expect( - screen.getByText( - /Inference endpoints enable you to perform inference tasks using NLP models provided by third-party services/ - ) - ).toBeInTheDocument(); - }); - - it('should have a learn-more link', () => { - const learnMoreLink = screen.getByTestId('learn-how-to-create-inference-endpoints'); - expect(learnMoreLink).toBeInTheDocument(); - }); - - it('should have a view-your-models link', () => { - const learnMoreLink = screen.getByTestId('view-your-models'); - expect(learnMoreLink).toBeInTheDocument(); - }); - - it('should have a semantic-search-with-elser link', () => { - const learnMoreLink = screen.getByTestId('semantic-search-with-elser'); - expect(learnMoreLink).toBeInTheDocument(); - }); - - it('should have a semantic-search-with-e5 link', () => { - const learnMoreLink = screen.getByTestId('semantic-search-with-e5'); - expect(learnMoreLink).toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx deleted file mode 100644 index 782994975ada4..0000000000000 --- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { - EuiPageTemplate, - EuiFlexGroup, - EuiFlexItem, - EuiImage, - EuiSpacer, - EuiLink, -} from '@elastic/eui'; -import { docLinks } from '../../../common/doc_links'; - -import * as i18n from '../../../common/translations'; - -import inferenceEndpoint from '../../assets/images/inference_endpoint.svg'; - -import { EndpointPrompt } from './endpoint_prompt'; -import { useTrainedModelPageUrl } from '../../hooks/use_trained_model_page_url'; - -import './add_empty_prompt.scss'; - -export const AddEmptyPrompt: React.FC = () => { - const trainedModelPageUrl = useTrainedModelPageUrl(); - - return ( - } - title={

{i18n.INFERENCE_ENDPOINT_LABEL}

} - body={ - - - {i18n.CREATE_FIRST_INFERENCE_ENDPOINT_DESCRIPTION} - - - - {i18n.LEARN_HOW_TO_CREATE_INFERENCE_ENDPOINTS_LINK} - - - - - {i18n.VIEW_YOUR_MODELS_LINK} - - - - } - footer={ - - - {i18n.START_WITH_PREPARED_ENDPOINTS_LABEL} - - - - - - {i18n.SEMANTIC_SEARCH_WITH_ELSER_LINK} -
- } - /> - - - - {i18n.SEMANTIC_SEARCH_WITH_E5_LINK} - - } - /> - -
- - } - /> - ); -}; diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx deleted file mode 100644 index aa6ff9d582e10..0000000000000 --- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiCard } from '@elastic/eui'; - -interface EndpointPromptProps { - title: string; - description: string; - footer: React.ReactElement; -} - -export const EndpointPrompt: React.FC = ({ title, description, footer }) => ( - -); diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/index.ts b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/index.ts deleted file mode 100644 index dcb2d12f6c986..0000000000000 --- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export { AddEmptyPrompt } from './add_empty_prompt'; diff --git a/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx b/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx index 1aea8df69e0ee..c39bc69fc300b 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx @@ -11,7 +11,6 @@ import { EuiPageTemplate } from '@elastic/eui'; import { useQueryInferenceEndpoints } from '../hooks/use_inference_endpoints'; import { TabularPage } from './all_inference_endpoints/tabular_page'; -import { AddEmptyPrompt } from './empty_prompt/add_empty_prompt'; import { InferenceEndpointsHeader } from './inference_endpoints_header'; export const InferenceEndpoints: React.FC = () => { @@ -21,13 +20,9 @@ export const InferenceEndpoints: React.FC = () => { return ( <> - {inferenceEndpoints.length > 0 && } + - {inferenceEndpoints.length === 0 ? ( - - ) : ( - - )} + ); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 45533bf57574a..9e91d5ec13af5 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -36031,15 +36031,6 @@ "xpack.searchInferenceEndpoints.actions.endpointAddedSuccess": "Point de terminaison ajouté", "xpack.searchInferenceEndpoints.actions.endpointAddedSuccessDescription": "Le point de terminaison d'inférence \"{endpointId}\" a été ajouté.", "xpack.searchInferenceEndpoints.actions.trainedModelsStatGatherFailed": "Échec de la récupération des statistiques du modèle entraîné", - "xpack.searchInferenceEndpoints.addEmptyPrompt.createFirstInferenceEndpointDescription": "Les points de terminaison d'inférence vous permettent d'effectuer des tâches d'inférence à l'aide de modèles NLP fournis par des services tiers ou de modèles intégrés d'Elastic comme ELSER et E5. Configurez des tâches telles que l'incorporation de texte, les complétions, le reclassement et bien plus encore à l'aide de la fonction Créer une API d'inférence.", - "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Description": "E5 est un modèle NLP tiers qui vous permet de réaliser des recherches sémantiques multilingues en utilisant des représentations vectorielles denses.", - "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Title": "E5 multilingue", - "xpack.searchInferenceEndpoints.addEmptyPrompt.elserDescription": "ELSER est le modèle NLP vectoriel creux d'Elastic pour la recherche sémantique en anglais.", - "xpack.searchInferenceEndpoints.addEmptyPrompt.elserTitle": "ELSER", - "xpack.searchInferenceEndpoints.addEmptyPrompt.learnHowToCreateInferenceEndpoints": "Découvrez comment créer des points de terminaison d'inférence", - "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithE5": "Recherche sémantique avec E5 multilingue", - "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithElser": "Recherche sémantique avec ELSER", - "xpack.searchInferenceEndpoints.addEmptyPrompt.startWithPreparedEndpointsLabel": "En savoir plus sur les modèles NLP intégrés :", "xpack.searchInferenceEndpoints.allInferenceEndpoints.description": "Les points de terminaison d'inférence rationalisent le déploiement et la gestion des modèles d'apprentissage automatique dans Elasticsearch. Configurez et gérez des tâches NLP à l'aide de points de terminaison uniques afin de créer une recherche basée sur l'IA.", "xpack.searchInferenceEndpoints.apiDocumentationLink": "Documentation sur les API", "xpack.searchInferenceEndpoints.cancel": "Annuler", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 9d947185a869d..699fa6c37596b 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -36000,15 +36000,6 @@ "xpack.searchInferenceEndpoints.actions.endpointAddedSuccess": "エンドポイントが追加されました", "xpack.searchInferenceEndpoints.actions.endpointAddedSuccessDescription": "インターフェースエンドポイント\"{endpointId}\"が追加されました。", "xpack.searchInferenceEndpoints.actions.trainedModelsStatGatherFailed": "学習済みモデル統計情報を取得できませんでした", - "xpack.searchInferenceEndpoints.addEmptyPrompt.createFirstInferenceEndpointDescription": "推論エンドポイントを使用すると、サードパーティサービスが提供するNLPモデルや、ELSERやE5などのElasticの組み込みモデルを使用して推論タスクを実行できます。Create Inference APIを使用して、テキスト埋め込み、入力、再ランク付けなどのタスクを設定します。", - "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Description": "E5は、密ベクトル表現を使用して、多言語のセマンティック検索を可能にするサードパーティNLPモデルです。", - "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Title": "E5 Multilingual", - "xpack.searchInferenceEndpoints.addEmptyPrompt.elserDescription": "ELSERは、英語でのセマンティック検索向けにElasticの疎ベクトルNLPモデルです。", - "xpack.searchInferenceEndpoints.addEmptyPrompt.elserTitle": "ELSER", - "xpack.searchInferenceEndpoints.addEmptyPrompt.learnHowToCreateInferenceEndpoints": "推論エンドポイントを作成する方法", - "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithE5": "E5 Multilingualを使用したセマンティック検索", - "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithElser": "ELSERを使用したセマンティック検索", - "xpack.searchInferenceEndpoints.addEmptyPrompt.startWithPreparedEndpointsLabel": "組み込まれたNLPモデルの詳細:", "xpack.searchInferenceEndpoints.allInferenceEndpoints.description": "推論エンドポイントは、Elasticsearchにおける機械学習モデルのデプロイと管理を合理化します。独自のエンドポイントを使用してNLPタスクを設定および管理し、AIを活用した検索を構築します。", "xpack.searchInferenceEndpoints.apiDocumentationLink": "APIドキュメント", "xpack.searchInferenceEndpoints.cancel": "キャンセル", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 661a43585defa..c3b43206335aa 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -35438,15 +35438,6 @@ "xpack.searchInferenceEndpoints.actions.endpointAddedFailure": "终端创建失败", "xpack.searchInferenceEndpoints.actions.endpointAddedSuccess": "已添加终端", "xpack.searchInferenceEndpoints.actions.trainedModelsStatGatherFailed": "无法检索已训练模型统计信息", - "xpack.searchInferenceEndpoints.addEmptyPrompt.createFirstInferenceEndpointDescription": "利用推理终端,您可以使用由第三方服务提供的 NLP 模型或 ELSER 和 E5 等 Elastic 内置模型来执行推理任务。通过使用创建推理 API 来设置任务,如文本嵌入、完成、重新排名等。", - "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Description": "E5 是一个第三方 NLP 模型,它允许您通过使用密集向量表示方法来执行多语言语义搜索。", - "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Title": "E5 多语言", - "xpack.searchInferenceEndpoints.addEmptyPrompt.elserDescription": "ELSER 是 Elastic 的英文版稀疏向量语义搜索 NLP 模型。", - "xpack.searchInferenceEndpoints.addEmptyPrompt.elserTitle": "ELSER", - "xpack.searchInferenceEndpoints.addEmptyPrompt.learnHowToCreateInferenceEndpoints": "了解如何创建推理终端", - "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithE5": "利用 E5 多语言版进行语义搜索", - "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithElser": "利用 ELSER 进行语义搜索", - "xpack.searchInferenceEndpoints.addEmptyPrompt.startWithPreparedEndpointsLabel": "详细了解内置 NLP 模型:", "xpack.searchInferenceEndpoints.allInferenceEndpoints.description": "推理终端简化了 Elasticsearch 中的 Machine Learning 模型部署和管理。使用唯一的终端来设置和管理 NLP 任务,以构建 AI 驱动式搜索。", "xpack.searchInferenceEndpoints.apiDocumentationLink": "API 文档", "xpack.searchInferenceEndpoints.cancel": "取消",