diff --git a/.buildkite/ftr_oblt_serverless_configs.yml b/.buildkite/ftr_oblt_serverless_configs.yml index ee954577fc758..f583f1bd2adce 100644 --- a/.buildkite/ftr_oblt_serverless_configs.yml +++ b/.buildkite/ftr_oblt_serverless_configs.yml @@ -24,6 +24,8 @@ enabled: - x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group4.ts - x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group5.ts - x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group6.ts + - x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group7.ts + - x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group8.ts - x-pack/test_serverless/functional/test_suites/observability/config.screenshots.ts # serverless config files that run deployment-agnostic tests - x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts diff --git a/.buildkite/ftr_search_serverless_configs.yml b/.buildkite/ftr_search_serverless_configs.yml index e6efee5860806..20f3e8165e1e4 100644 --- a/.buildkite/ftr_search_serverless_configs.yml +++ b/.buildkite/ftr_search_serverless_configs.yml @@ -18,5 +18,7 @@ enabled: - x-pack/test_serverless/functional/test_suites/search/common_configs/config.group4.ts - x-pack/test_serverless/functional/test_suites/search/common_configs/config.group5.ts - x-pack/test_serverless/functional/test_suites/search/common_configs/config.group6.ts + - x-pack/test_serverless/functional/test_suites/search/common_configs/config.group7.ts + - x-pack/test_serverless/functional/test_suites/search/common_configs/config.group8.ts # serverless config files that run deployment-agnostic tests - x-pack/test/api_integration/deployment_agnostic/configs/serverless/search.serverless.config.ts diff --git a/.buildkite/ftr_security_serverless_configs.yml b/.buildkite/ftr_security_serverless_configs.yml index 955354e2acb50..69d4801292cf7 100644 --- a/.buildkite/ftr_security_serverless_configs.yml +++ b/.buildkite/ftr_security_serverless_configs.yml @@ -41,6 +41,8 @@ enabled: - x-pack/test_serverless/functional/test_suites/security/common_configs/config.group4.ts - x-pack/test_serverless/functional/test_suites/security/common_configs/config.group5.ts - x-pack/test_serverless/functional/test_suites/security/common_configs/config.group6.ts + - x-pack/test_serverless/functional/test_suites/security/common_configs/config.group7.ts + - x-pack/test_serverless/functional/test_suites/security/common_configs/config.group8.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/actions/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/trial_license_complete_tier/configs/serverless.config.ts diff --git a/.buildkite/pipeline-resource-definitions/trigger-version-dependent-jobs.yml b/.buildkite/pipeline-resource-definitions/trigger-version-dependent-jobs.yml index dce527f9e7f62..8dd486c3176ce 100644 --- a/.buildkite/pipeline-resource-definitions/trigger-version-dependent-jobs.yml +++ b/.buildkite/pipeline-resource-definitions/trigger-version-dependent-jobs.yml @@ -31,6 +31,7 @@ spec: default_branch: main repository: elastic/kibana pipeline_file: .buildkite/scripts/pipelines/trigger_version_dependent_jobs/pipeline.sh + skip_intermediate_builds: false provider_settings: prefix_pull_request_fork_branch_names: false skip_pull_request_builds_for_existing_commits: true diff --git a/packages/kbn-search-api-keys-components/src/components/api_key_form.tsx b/packages/kbn-search-api-keys-components/src/components/api_key_form.tsx index 0a94f3e336897..e7d4d2808433c 100644 --- a/packages/kbn-search-api-keys-components/src/components/api_key_form.tsx +++ b/packages/kbn-search-api-keys-components/src/components/api_key_form.tsx @@ -23,30 +23,31 @@ import { ApiKeyFlyoutWrapper } from './api_key_flyout_wrapper'; import { useSearchApiKey } from '../hooks/use_search_api_key'; import { Status } from '../constants'; +const API_KEY_MASK = '•'.repeat(60); + interface ApiKeyFormProps { hasTitle?: boolean; } export const ApiKeyForm: React.FC = ({ hasTitle = true }) => { const [showFlyout, setShowFlyout] = useState(false); - const { apiKey, status, updateApiKey, toggleApiKeyVisibility, displayedApiKey, apiKeyIsVisible } = - useSearchApiKey(); + const { apiKey, status, updateApiKey, toggleApiKeyVisibility } = useSearchApiKey(); const titleLocale = i18n.translate('searchApiKeysComponents.apiKeyForm.title', { defaultMessage: 'API Key', }); - if (apiKey && displayedApiKey) { + if (apiKey) { return ( { + const { http } = useKibana().services; + const { mutateAsync: createApiKey } = useMutation({ + mutationFn: async () => { + try { + if (!http?.post) { + throw new Error('HTTP service is unavailable'); + } + + return await http.post(APIRoutes.API_KEYS); + } catch (err) { + onError(err); + } + }, + onSuccess: (receivedApiKey) => { + if (receivedApiKey) { + onSuccess(receivedApiKey); + } + }, + }); + + return createApiKey; +}; diff --git a/packages/kbn-search-api-keys-components/src/hooks/use_validate_api_key.ts b/packages/kbn-search-api-keys-components/src/hooks/use_validate_api_key.ts new file mode 100644 index 0000000000000..43b75990f032e --- /dev/null +++ b/packages/kbn-search-api-keys-components/src/hooks/use_validate_api_key.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { useMutation } from '@tanstack/react-query'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { APIRoutes } from '../types'; + +export const useValidateApiKey = (): ((id: string) => Promise) => { + const { http } = useKibana().services; + const { mutateAsync: validateApiKey } = useMutation(async (id: string) => { + try { + if (!http?.post) { + throw new Error('HTTP service is unavailable'); + } + + const response = await http.post<{ isValid: boolean }>(APIRoutes.API_KEY_VALIDITY, { + body: JSON.stringify({ id }), + }); + + return response.isValid; + } catch (err) { + return false; + } + }); + + return validateApiKey; +}; diff --git a/packages/kbn-search-api-keys-components/src/providers/search_api_key_provider.tsx b/packages/kbn-search-api-keys-components/src/providers/search_api_key_provider.tsx index a3d3ce2aea830..04cf9655b26ea 100644 --- a/packages/kbn-search-api-keys-components/src/providers/search_api_key_provider.tsx +++ b/packages/kbn-search-api-keys-components/src/providers/search_api_key_provider.tsx @@ -7,176 +7,109 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { useCallback, useReducer, createContext, useEffect } from 'react'; -import { useMutation } from '@tanstack/react-query'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import type { APIKeyCreationResponse } from '@kbn/search-api-keys-server/types'; -import { APIRoutes } from '../types'; +import React, { useCallback, createContext, useState, useMemo, useRef } from 'react'; +import { useCreateApiKey } from '../hooks/use_create_api_key'; import { Status } from '../constants'; +import { useValidateApiKey } from '../hooks/use_validate_api_key'; const API_KEY_STORAGE_KEY = 'searchApiKey'; -const API_KEY_MASK = '•'.repeat(60); - -interface ApiKeyState { - status: Status; - apiKey: string | null; -} interface APIKeyContext { - displayedApiKey: string | null; apiKey: string | null; toggleApiKeyVisibility: () => void; updateApiKey: ({ id, encoded }: { id: string; encoded: string }) => void; status: Status; - apiKeyIsVisible: boolean; initialiseKey: () => void; } -type Action = - | { type: 'SET_API_KEY'; apiKey: string; status: Status } - | { type: 'SET_STATUS'; status: Status } - | { type: 'CLEAR_API_KEY' } - | { type: 'TOGGLE_API_KEY_VISIBILITY' }; - -const initialState: ApiKeyState = { - apiKey: null, - status: Status.uninitialized, -}; - -const reducer = (state: ApiKeyState, action: Action): ApiKeyState => { - switch (action.type) { - case 'SET_API_KEY': - return { ...state, apiKey: action.apiKey, status: action.status }; - case 'SET_STATUS': - return { ...state, status: action.status }; - case 'TOGGLE_API_KEY_VISIBILITY': - return { - ...state, - status: - state.status === Status.showHiddenKey ? Status.showPreviewKey : Status.showHiddenKey, - }; - case 'CLEAR_API_KEY': - return { ...state, apiKey: null, status: Status.showCreateButton }; - default: - return state; - } -}; - export const ApiKeyContext = createContext({ - displayedApiKey: null, apiKey: null, toggleApiKeyVisibility: () => {}, updateApiKey: () => {}, status: Status.uninitialized, - apiKeyIsVisible: false, initialiseKey: () => {}, }); export const SearchApiKeyProvider: React.FC = ({ children }) => { - const { http } = useKibana().services; - const [state, dispatch] = useReducer(reducer, initialState); - + const isInitialising = useRef(false); + const [apiKey, setApiKey] = useState(null); + const [status, setStatus] = useState(Status.uninitialized); const updateApiKey = useCallback(({ id, encoded }: { id: string; encoded: string }) => { sessionStorage.setItem(API_KEY_STORAGE_KEY, JSON.stringify({ id, encoded })); - dispatch({ type: 'SET_API_KEY', apiKey: encoded, status: Status.showHiddenKey }); - }, []); - const handleShowKeyVisibility = useCallback(() => { - dispatch({ type: 'TOGGLE_API_KEY_VISIBILITY' }); + setApiKey(encoded); + setStatus(Status.showHiddenKey); }, []); - const initialiseKey = useCallback(() => { - dispatch({ type: 'SET_STATUS', status: Status.loading }); + const toggleApiKeyVisibility = useCallback(() => { + setStatus((prevStatus) => + prevStatus === Status.showHiddenKey ? Status.showPreviewKey : Status.showHiddenKey + ); }, []); - const { mutateAsync: validateApiKey } = useMutation(async (id: string) => { - try { - if (!http?.post) { - throw new Error('HTTP service is unavailable'); - } - - const response = await http.post<{ isValid: boolean }>(APIRoutes.API_KEY_VALIDITY, { - body: JSON.stringify({ id }), - }); - - return response.isValid; - } catch (err) { - return false; - } - }); - const { mutateAsync: createApiKey } = useMutation({ - mutationFn: async () => { - try { - if (!http?.post) { - throw new Error('HTTP service is unavailable'); - } - - return await http.post(APIRoutes.API_KEYS); - } catch (err) { - if (err.response?.status === 400) { - dispatch({ type: 'SET_STATUS', status: Status.showCreateButton }); - } else if (err.response?.status === 403) { - dispatch({ type: 'SET_STATUS', status: Status.showUserPrivilegesError }); - } else { - throw err; - } - } - }, + const validateApiKey = useValidateApiKey(); + const createApiKey = useCreateApiKey({ onSuccess: (receivedApiKey) => { if (receivedApiKey) { sessionStorage.setItem( API_KEY_STORAGE_KEY, JSON.stringify({ id: receivedApiKey.id, encoded: receivedApiKey.encoded }) ); - dispatch({ - type: 'SET_API_KEY', - apiKey: receivedApiKey.encoded, - status: Status.showHiddenKey, - }); + setApiKey(receivedApiKey.encoded); + setStatus(Status.showHiddenKey); + } + }, + onError: (err) => { + if (err.response?.status === 400) { + setStatus(Status.showCreateButton); + } else if (err.response?.status === 403) { + setStatus(Status.showUserPrivilegesError); + } else { + throw err; } }, }); + const initialiseKey = useCallback(async () => { + if (status !== Status.uninitialized || isInitialising.current) { + return; + } - useEffect(() => { - const initialiseApiKey = async () => { - try { - if (state.status === Status.loading) { - const storedKey = sessionStorage.getItem(API_KEY_STORAGE_KEY); + isInitialising.current = true; + + try { + setStatus(Status.loading); + const storedKey = sessionStorage.getItem(API_KEY_STORAGE_KEY); - if (storedKey) { - const { id, encoded } = JSON.parse(storedKey); + if (storedKey) { + const { id, encoded } = JSON.parse(storedKey); - if (await validateApiKey(id)) { - dispatch({ - type: 'SET_API_KEY', - apiKey: encoded, - status: Status.showHiddenKey, - }); - } else { - sessionStorage.removeItem(API_KEY_STORAGE_KEY); - dispatch({ - type: 'CLEAR_API_KEY', - }); - await createApiKey(); - } - } else { - await createApiKey(); - } + if (await validateApiKey(id)) { + setApiKey(encoded); + setStatus(Status.showHiddenKey); + } else { + sessionStorage.removeItem(API_KEY_STORAGE_KEY); + setApiKey(null); + setStatus(Status.showCreateButton); + await createApiKey(); } - } catch (e) { - dispatch({ type: 'CLEAR_API_KEY' }); + } else { + await createApiKey(); } - }; - - initialiseApiKey(); - }, [state.status, createApiKey, validateApiKey]); - - const value: APIKeyContext = { - displayedApiKey: state.status === Status.showPreviewKey ? state.apiKey : API_KEY_MASK, - apiKey: state.apiKey, - toggleApiKeyVisibility: handleShowKeyVisibility, - updateApiKey, - status: state.status, - apiKeyIsVisible: state.status === Status.showPreviewKey, - initialiseKey, - }; + } catch (e) { + setApiKey(null); + setStatus(Status.showCreateButton); + } finally { + isInitialising.current = false; + } + }, [status, createApiKey, validateApiKey]); + + const value: APIKeyContext = useMemo( + () => ({ + apiKey, + toggleApiKeyVisibility, + updateApiKey, + status, + initialiseKey, + }), + [apiKey, status, toggleApiKeyVisibility, updateApiKey, initialiseKey] + ); return {children}; }; diff --git a/packages/kbn-search-api-keys-server/src/lib/privileges.ts b/packages/kbn-search-api-keys-server/src/lib/privileges.ts index fc5ad1f896746..9507e92b02eea 100644 --- a/packages/kbn-search-api-keys-server/src/lib/privileges.ts +++ b/packages/kbn-search-api-keys-server/src/lib/privileges.ts @@ -19,9 +19,15 @@ export async function fetchUserStartPrivileges( // and can also have permissions for index monitoring const securityCheck = await client.security.hasPrivileges({ cluster: ['manage'], + index: [ + { + names: ['*'], + privileges: ['read', 'write'], + }, + ], }); - return securityCheck?.cluster?.manage ?? false; + return securityCheck.has_all_requested ?? false; } catch (e) { logger.error(`Error checking user privileges for search API Keys`); logger.error(e); diff --git a/packages/kbn-search-api-keys-server/src/routes/routes.ts b/packages/kbn-search-api-keys-server/src/routes/routes.ts index 77a08644f34a5..0e4eb81309c87 100644 --- a/packages/kbn-search-api-keys-server/src/routes/routes.ts +++ b/packages/kbn-search-api-keys-server/src/routes/routes.ts @@ -71,14 +71,6 @@ export function registerSearchApiKeysRoutes(router: IRouter, logger: Logger) { try { const core = await context.core; const client = core.elasticsearch.client.asCurrentUser; - const clusterHasApiKeys = await fetchClusterHasApiKeys(client, logger); - - if (clusterHasApiKeys) { - return response.customError({ - body: { message: 'Project already has API keys' }, - statusCode: 400, - }); - } const canCreateApiKeys = await fetchUserStartPrivileges(client, logger); @@ -89,6 +81,15 @@ export function registerSearchApiKeysRoutes(router: IRouter, logger: Logger) { }); } + const clusterHasApiKeys = await fetchClusterHasApiKeys(client, logger); + + if (clusterHasApiKeys) { + return response.customError({ + body: { message: 'Project already has API keys' }, + statusCode: 400, + }); + } + const apiKey = await createAPIKey(API_KEY_NAME, client, logger); return response.ok({ diff --git a/test/functional/apps/management/data_views/_handle_alias.ts b/test/functional/apps/management/data_views/_handle_alias.ts index ca9f2b1f8cfea..a3b8a0266dae4 100644 --- a/test/functional/apps/management/data_views/_handle_alias.ts +++ b/test/functional/apps/management/data_views/_handle_alias.ts @@ -18,7 +18,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'home', 'settings', 'discover', 'timePicker']); const kibanaServer = getService('kibanaServer'); - describe('Index patterns on aliases', function () { + // Failing: See https://github.com/elastic/kibana/issues/201744 + describe.skip('Index patterns on aliases', function () { before(async function () { await kibanaServer.savedObjects.cleanStandardList(); await security.testUser.setRoles(['kibana_admin', 'test_alias_reader']); diff --git a/x-pack/plugins/cases/public/components/filter_popover/index.test.tsx b/x-pack/plugins/cases/public/components/filter_popover/index.test.tsx index c45599860a560..351cc6e77a986 100644 --- a/x-pack/plugins/cases/public/components/filter_popover/index.test.tsx +++ b/x-pack/plugins/cases/public/components/filter_popover/index.test.tsx @@ -11,7 +11,8 @@ import { render, waitFor, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { FilterPopover } from '.'; -describe('FilterPopover ', () => { +// Failing: See https://github.com/elastic/kibana/issues/176679 +describe.skip('FilterPopover ', () => { const onSelectedOptionsChanged = jest.fn(); const tags: string[] = ['coke', 'pepsi']; diff --git a/x-pack/plugins/search_indices/public/components/index_documents/add_documents_code_example.tsx b/x-pack/plugins/search_indices/public/components/index_documents/add_documents_code_example.tsx index cdd773f4e6a81..e84ca5bd47be0 100644 --- a/x-pack/plugins/search_indices/public/components/index_documents/add_documents_code_example.tsx +++ b/x-pack/plugins/search_indices/public/components/index_documents/add_documents_code_example.tsx @@ -60,7 +60,7 @@ export const AddDocumentsCodeExample = ({ generateSampleDocument(codeSampleMappings, `Example text ${num}`) ); }, [codeSampleMappings]); - const { apiKey, apiKeyIsVisible } = useSearchApiKey(); + const { apiKey } = useSearchApiKey(); const codeParams: IngestCodeSnippetParameters = useMemo(() => { return { indexName, @@ -68,17 +68,9 @@ export const AddDocumentsCodeExample = ({ sampleDocuments, indexHasMappings, mappingProperties: codeSampleMappings, - apiKey: apiKeyIsVisible && apiKey ? apiKey : undefined, + apiKey: apiKey || undefined, }; - }, [ - indexName, - elasticsearchUrl, - sampleDocuments, - codeSampleMappings, - indexHasMappings, - apiKeyIsVisible, - apiKey, - ]); + }, [indexName, elasticsearchUrl, sampleDocuments, codeSampleMappings, indexHasMappings, apiKey]); return ( { return { indexName: indexName || undefined, elasticsearchURL: elasticsearchUrl, - apiKey: apiKeyIsVisible && apiKey ? apiKey : undefined, + apiKey: apiKey || undefined, }; - }, [indexName, elasticsearchUrl, apiKeyIsVisible, apiKey]); + }, [indexName, elasticsearchUrl, apiKey]); const selectedCodeExample = useMemo(() => { return selectedCodeExamples[selectedLanguage]; }, [selectedLanguage, selectedCodeExamples]); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 970d4897b9e6a..765be17d98b5d 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -48859,7 +48859,6 @@ "xpack.upgradeAssistant.overview.apiCompatibilityNoteTitle": "Appliquer les en-têtes de compatibilité d'API (facultatif)", "xpack.upgradeAssistant.overview.backupStepDescription": "Assurez-vous de disposer d'un snapshot actuel avant d'effectuer des modifications.", "xpack.upgradeAssistant.overview.backupStepTitle": "Sauvegarder vos données", - "xpack.upgradeAssistant.overview.checkUpcomingVersion": "Si vous ne travaillez pas sur la dernière version de la Suite Elastic, utilisez l'assistant de mise à niveau pour effectuer la préparation de la prochaine mise à niveau.", "xpack.upgradeAssistant.overview.cloudBackup.hasSnapshotMessage": "Dernier snapshot créé le {lastBackupTime}.", "xpack.upgradeAssistant.overview.cloudBackup.loadingError": "Une erreur s'est produite lors de la récupération du dernier statut de snapshot", "xpack.upgradeAssistant.overview.cloudBackup.noSnapshotMessage": "Vos données n'ont pas été sauvegardées.", @@ -48934,7 +48933,6 @@ "xpack.upgradeAssistant.overview.verifyChanges.retryButton": "Réessayer", "xpack.upgradeAssistant.overview.viewDiscoverResultsAction": "Analyser les logs dans Discover", "xpack.upgradeAssistant.overview.viewObservabilityResultsAction": "Afficher les logs d'obsolescence dans Logs Explorer", - "xpack.upgradeAssistant.overview.whatsNewLink": "Consulter les points forts de la toute dernière version", "xpack.upgradeAssistant.reindex.reindexPrivilegesErrorBatch": "Vous ne disposez pas des privilèges appropriés pour réindexer \"{indexName}\".", "xpack.upgradeAssistant.status.allDeprecationsResolvedMessage": "Tous les avertissements de déclassement ont été résolus.", "xpack.upgradeAssistant.status.deprecationsUnresolvedMessage": "Les problèmes suivants doivent être résolus avant la mise à niveau : {upgradeIssues}.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 1ae2f8380600d..3f1b10bdce8ae 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -48820,7 +48820,6 @@ "xpack.upgradeAssistant.overview.apiCompatibilityNoteTitle": "API互換性ヘッダーを適用(オプション)", "xpack.upgradeAssistant.overview.backupStepDescription": "変更を行う前に、現在のスナップショットがあることを確認してください。", "xpack.upgradeAssistant.overview.backupStepTitle": "データをバックアップ", - "xpack.upgradeAssistant.overview.checkUpcomingVersion": "最新バージョンのElastic Stackを使用していない場合は、アップグレードアシスタンスを使用して、次回のアップグレードを準備してください。", "xpack.upgradeAssistant.overview.cloudBackup.hasSnapshotMessage": "前回のスナップショットは{lastBackupTime}に作成されました。", "xpack.upgradeAssistant.overview.cloudBackup.loadingError": "最新のスナップショットステータスの取得中にエラーが発生しました", "xpack.upgradeAssistant.overview.cloudBackup.noSnapshotMessage": "データはバックアップされていません。", @@ -48895,7 +48894,6 @@ "xpack.upgradeAssistant.overview.verifyChanges.retryButton": "再試行", "xpack.upgradeAssistant.overview.viewDiscoverResultsAction": "Discoverでログを分析", "xpack.upgradeAssistant.overview.viewObservabilityResultsAction": "Logs Explorerで廃止予定ログを表示", - "xpack.upgradeAssistant.overview.whatsNewLink": "最新リリースのハイライトを確認", "xpack.upgradeAssistant.reindex.reindexPrivilegesErrorBatch": "「{indexName}」に再インデックスするための権限が不十分です。", "xpack.upgradeAssistant.status.allDeprecationsResolvedMessage": "すべての廃止予定の警告が解決されました。", "xpack.upgradeAssistant.status.deprecationsUnresolvedMessage": "アップグレード前に次の問題を解決する必要があります:{upgradeIssues}。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 27eb8d93e9919..463906b3e6cff 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -48072,7 +48072,6 @@ "xpack.upgradeAssistant.overview.apiCompatibilityNoteTitle": "应用 API 兼容性标头(可选)", "xpack.upgradeAssistant.overview.backupStepDescription": "做出更改之前,请确保具有当前快照。", "xpack.upgradeAssistant.overview.backupStepTitle": "备份您的数据", - "xpack.upgradeAssistant.overview.checkUpcomingVersion": "如果您未使用最新版本的 Elastic Stack,请使用升级助手准备下次升级。", "xpack.upgradeAssistant.overview.cloudBackup.hasSnapshotMessage": "上次创建快照的时间为 {lastBackupTime}。", "xpack.upgradeAssistant.overview.cloudBackup.loadingError": "检索最新快照状态时出错", "xpack.upgradeAssistant.overview.cloudBackup.noSnapshotMessage": "您的数据未备份。", @@ -48147,7 +48146,6 @@ "xpack.upgradeAssistant.overview.verifyChanges.retryButton": "重试", "xpack.upgradeAssistant.overview.viewDiscoverResultsAction": "在 Discover 中分析日志", "xpack.upgradeAssistant.overview.viewObservabilityResultsAction": "在日志浏览器中查看弃用日志", - "xpack.upgradeAssistant.overview.whatsNewLink": "查看最新发布亮点", "xpack.upgradeAssistant.status.allDeprecationsResolvedMessage": "所有弃用警告均已解决。", "xpack.upgradeAssistant.status.deprecationsUnresolvedMessage": "在升级之前必须解决以下问题:{upgradeIssues}。", "xpack.upgradeAssistant.status.esTotalCriticalDepsMessage": "{esTotalCriticalDeps} 个 Elasticsearch 弃用{esTotalCriticalDeps, plural, other {问题}}", diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx index cc28b2e152e23..b9579005ffe3a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx @@ -9,13 +9,13 @@ import React, { useEffect, useState } from 'react'; import { EuiSteps, - EuiText, EuiPageHeader, EuiButtonEmpty, EuiSpacer, EuiLink, EuiPageBody, EuiPageSection, + EuiText, } from '@elastic/eui'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; @@ -94,18 +94,24 @@ export const Overview = withRouter(({ history }: RouteComponentProps) => { > + + + ), + }} /> - - - - - { + const browser = getService('browser'); + const log = getService('log'); + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['timePicker', 'svlCommonPage']); + const config = getService('config'); + let remoteEsArchiver; + + describe('lens serverless - group 1 - subgroup 5', function () { + this.tags(['esGate']); + + const esArchive = 'x-pack/test/functional/es_archives/logstash_functional'; + const localIndexPatternString = 'logstash-*'; + const remoteIndexPatternString = 'ftr-remote:logstash-*'; + const localFixtures = { + lensBasic: 'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json', + lensDefault: 'x-pack/test/functional/fixtures/kbn_archiver/lens/default', + }; + + const remoteFixtures = { + lensBasic: 'x-pack/test/functional/fixtures/kbn_archiver/lens/ccs/lens_basic.json', + lensDefault: 'x-pack/test/functional/fixtures/kbn_archiver/lens/ccs/default', + }; + let esNode: EsArchiver; + let fixtureDirs: { + lensBasic: string; + lensDefault: string; + }; + let indexPatternString: string; + before(async () => { + log.debug('Starting lens before method'); + await browser.setWindowSize(1280, 1200); + await kibanaServer.savedObjects.cleanStandardList(); + try { + config.get('esTestCluster.ccs'); + remoteEsArchiver = getService('remoteEsArchiver' as 'esArchiver'); + esNode = remoteEsArchiver; + fixtureDirs = remoteFixtures; + indexPatternString = remoteIndexPatternString; + } catch (error) { + esNode = esArchiver; + fixtureDirs = localFixtures; + indexPatternString = localIndexPatternString; + } + + await esNode.load(esArchive); + await kibanaServer.uiSettings.update({ + defaultIndex: indexPatternString, + 'dateFormat:tz': 'UTC', + }); + await kibanaServer.importExport.load(fixtureDirs.lensBasic); + await kibanaServer.importExport.load(fixtureDirs.lensDefault); + // changing the timepicker default here saves us from having to set it in Discover (~8s) + await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + }); + + after(async () => { + await esArchiver.unload(esArchive); + await PageObjects.timePicker.resetDefaultAbsoluteRangeViaUiSettings(); + await kibanaServer.importExport.unload(fixtureDirs.lensBasic); + await kibanaServer.importExport.unload(fixtureDirs.lensDefault); + await kibanaServer.savedObjects.cleanStandardList(); + }); + + loadTestFile(require.resolve('./tsdb.ts')); // 14m 25s + }); +}; diff --git a/x-pack/test_serverless/functional/test_suites/common/visualizations/group1/tsdb.ts b/x-pack/test_serverless/functional/test_suites/common/visualizations/group5/tsdb.ts similarity index 99% rename from x-pack/test_serverless/functional/test_suites/common/visualizations/group1/tsdb.ts rename to x-pack/test_serverless/functional/test_suites/common/visualizations/group5/tsdb.ts index 111cf30e919c5..37c74a0919750 100644 --- a/x-pack/test_serverless/functional/test_suites/common/visualizations/group1/tsdb.ts +++ b/x-pack/test_serverless/functional/test_suites/common/visualizations/group5/tsdb.ts @@ -17,7 +17,7 @@ import { getDocsGenerator, setupScenarioRunner, sumFirstNValues, -} from './tsdb_logsdb_helpers'; +} from '../tsdb_logsdb_helpers'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const { common, lens, dashboard, svlCommonPage } = getPageObjects([ diff --git a/x-pack/test_serverless/functional/test_suites/common/visualizations/group6/index.ts b/x-pack/test_serverless/functional/test_suites/common/visualizations/group6/index.ts new file mode 100644 index 0000000000000..d320116aa24ce --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/common/visualizations/group6/index.ts @@ -0,0 +1,78 @@ +/* + * 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 { EsArchiver } from '@kbn/es-archiver'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default ({ getService, loadTestFile, getPageObjects }: FtrProviderContext) => { + const browser = getService('browser'); + const log = getService('log'); + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['timePicker', 'svlCommonPage']); + const config = getService('config'); + let remoteEsArchiver; + + describe('lens serverless - group 1 - subgroup 6', function () { + this.tags(['esGate']); + + const esArchive = 'x-pack/test/functional/es_archives/logstash_functional'; + const localIndexPatternString = 'logstash-*'; + const remoteIndexPatternString = 'ftr-remote:logstash-*'; + const localFixtures = { + lensBasic: 'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json', + lensDefault: 'x-pack/test/functional/fixtures/kbn_archiver/lens/default', + }; + + const remoteFixtures = { + lensBasic: 'x-pack/test/functional/fixtures/kbn_archiver/lens/ccs/lens_basic.json', + lensDefault: 'x-pack/test/functional/fixtures/kbn_archiver/lens/ccs/default', + }; + let esNode: EsArchiver; + let fixtureDirs: { + lensBasic: string; + lensDefault: string; + }; + let indexPatternString: string; + before(async () => { + log.debug('Starting lens before method'); + await browser.setWindowSize(1280, 1200); + await kibanaServer.savedObjects.cleanStandardList(); + try { + config.get('esTestCluster.ccs'); + remoteEsArchiver = getService('remoteEsArchiver' as 'esArchiver'); + esNode = remoteEsArchiver; + fixtureDirs = remoteFixtures; + indexPatternString = remoteIndexPatternString; + } catch (error) { + esNode = esArchiver; + fixtureDirs = localFixtures; + indexPatternString = localIndexPatternString; + } + + await esNode.load(esArchive); + await kibanaServer.uiSettings.update({ + defaultIndex: indexPatternString, + 'dateFormat:tz': 'UTC', + }); + await kibanaServer.importExport.load(fixtureDirs.lensBasic); + await kibanaServer.importExport.load(fixtureDirs.lensDefault); + // changing the timepicker default here saves us from having to set it in Discover (~8s) + await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + }); + + after(async () => { + await esArchiver.unload(esArchive); + await PageObjects.timePicker.resetDefaultAbsoluteRangeViaUiSettings(); + await kibanaServer.importExport.unload(fixtureDirs.lensBasic); + await kibanaServer.importExport.unload(fixtureDirs.lensDefault); + await kibanaServer.savedObjects.cleanStandardList(); + }); + + loadTestFile(require.resolve('./logsdb.ts')); // 28m + }); +}; diff --git a/x-pack/test_serverless/functional/test_suites/common/visualizations/group1/logsdb.ts b/x-pack/test_serverless/functional/test_suites/common/visualizations/group6/logsdb.ts similarity index 99% rename from x-pack/test_serverless/functional/test_suites/common/visualizations/group1/logsdb.ts rename to x-pack/test_serverless/functional/test_suites/common/visualizations/group6/logsdb.ts index 040490310d95d..868c7ac0609e6 100644 --- a/x-pack/test_serverless/functional/test_suites/common/visualizations/group1/logsdb.ts +++ b/x-pack/test_serverless/functional/test_suites/common/visualizations/group6/logsdb.ts @@ -14,14 +14,15 @@ import { getDocsGenerator, setupScenarioRunner, TIME_PICKER_FORMAT, -} from './tsdb_logsdb_helpers'; +} from '../tsdb_logsdb_helpers'; export default function ({ getService, getPageObjects }: FtrProviderContext) { - const { common, lens, discover, header } = getPageObjects([ + const { common, lens, discover, header, svlCommonPage } = getPageObjects([ 'common', 'lens', 'discover', 'header', + 'svlCommonPage', ]); const testSubjects = getService('testSubjects'); const find = getService('find'); @@ -46,6 +47,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const toTime = 'Jun 16, 2023 @ 00:00:00.000'; before(async () => { + await svlCommonPage.loginAsAdmin(); log.info(`loading ${logsdbIndex} index...`); await esArchiver.loadIfNeeded(logsdbEsArchive); log.info(`creating a data view for "${logsdbDataView}"...`); diff --git a/x-pack/test_serverless/functional/test_suites/common/visualizations/group1/tsdb_logsdb_helpers.ts b/x-pack/test_serverless/functional/test_suites/common/visualizations/tsdb_logsdb_helpers.ts similarity index 99% rename from x-pack/test_serverless/functional/test_suites/common/visualizations/group1/tsdb_logsdb_helpers.ts rename to x-pack/test_serverless/functional/test_suites/common/visualizations/tsdb_logsdb_helpers.ts index 23822aa1395a9..cf7272e6d85b0 100644 --- a/x-pack/test_serverless/functional/test_suites/common/visualizations/group1/tsdb_logsdb_helpers.ts +++ b/x-pack/test_serverless/functional/test_suites/common/visualizations/tsdb_logsdb_helpers.ts @@ -9,7 +9,7 @@ import { Client } from '@elastic/elasticsearch'; import { MappingProperty } from '@elastic/elasticsearch/lib/api/types'; import { ToolingLog } from '@kbn/tooling-log'; import moment from 'moment'; -import { FtrProviderContext } from '../../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export const TEST_DOC_COUNT = 100; export const TIME_PICKER_FORMAT = 'MMM D, YYYY [@] HH:mm:ss.SSS'; diff --git a/x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group7.ts b/x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group7.ts new file mode 100644 index 0000000000000..62e1e388b95b5 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group7.ts @@ -0,0 +1,20 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseTestConfig = await readConfigFile(require.resolve('../config.ts')); + + return { + ...baseTestConfig.getAll(), + testFiles: [require.resolve('../../common/visualizations/group5')], + junit: { + reportName: 'Serverless Observability Functional Tests - Common Group 7', + }, + }; +} diff --git a/x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group8.ts b/x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group8.ts new file mode 100644 index 0000000000000..c12a600b1d46b --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group8.ts @@ -0,0 +1,20 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseTestConfig = await readConfigFile(require.resolve('../config.ts')); + + return { + ...baseTestConfig.getAll(), + testFiles: [require.resolve('../../common/visualizations/group6')], + junit: { + reportName: 'Serverless Observability Functional Tests - Common Group 8', + }, + }; +} diff --git a/x-pack/test_serverless/functional/test_suites/search/common_configs/config.group7.ts b/x-pack/test_serverless/functional/test_suites/search/common_configs/config.group7.ts new file mode 100644 index 0000000000000..723c9ac2c45ad --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/search/common_configs/config.group7.ts @@ -0,0 +1,20 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseTestConfig = await readConfigFile(require.resolve('../config.ts')); + + return { + ...baseTestConfig.getAll(), + testFiles: [require.resolve('../../common/visualizations/group5')], + junit: { + reportName: 'Serverless Search Functional Tests - Common Group 7', + }, + }; +} diff --git a/x-pack/test_serverless/functional/test_suites/search/common_configs/config.group8.ts b/x-pack/test_serverless/functional/test_suites/search/common_configs/config.group8.ts new file mode 100644 index 0000000000000..521691ffabd83 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/search/common_configs/config.group8.ts @@ -0,0 +1,20 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseTestConfig = await readConfigFile(require.resolve('../config.ts')); + + return { + ...baseTestConfig.getAll(), + testFiles: [require.resolve('../../common/visualizations/group6')], + junit: { + reportName: 'Serverless Search Functional Tests - Common Group 8', + }, + }; +} diff --git a/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts b/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts index 5aa2627a3cdf4..097da2201e1e7 100644 --- a/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts +++ b/x-pack/test_serverless/functional/test_suites/search/search_index_detail.ts @@ -54,12 +54,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await pageObjects.svlSearchIndexDetailPage.expectConnectionDetails(); }); - it.skip('should show api key', async () => { - await pageObjects.svlApiKeys.deleteAPIKeys(); - await svlSearchNavigation.navigateToIndexDetailPage(indexName); - await pageObjects.svlApiKeys.expectAPIKeyAvailable(); - const apiKey = await pageObjects.svlApiKeys.getAPIKeyFromUI(); - await pageObjects.svlSearchIndexDetailPage.expectAPIKeyToBeVisibleInCodeBlock(apiKey); + describe.skip('API key details', () => { + // Flaky test related with deleting API keys + it('should show api key', async () => { + await pageObjects.svlApiKeys.deleteAPIKeys(); + await svlSearchNavigation.navigateToIndexDetailPage(indexName); + await pageObjects.svlApiKeys.expectAPIKeyAvailable(); + const apiKey = await pageObjects.svlApiKeys.getAPIKeyFromUI(); + await pageObjects.svlSearchIndexDetailPage.expectAPIKeyToBeVisibleInCodeBlock(apiKey); + }); }); it('should have quick stats', async () => { @@ -107,11 +110,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await pageObjects.embeddedConsole.clickEmbeddedConsoleControlBar(); }); - // FLAKY: https://github.com/elastic/kibana/issues/197144 - describe.skip('With data', () => { + describe('With data', () => { before(async () => { await es.index({ index: indexName, + refresh: true, body: { my_field: [1, 0, 1], }, @@ -305,6 +308,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await pageObjects.svlSearchIndexDetailPage.expectDeleteIndexButtonExistsInMoreOptions(); await pageObjects.svlSearchIndexDetailPage.expectDeleteIndexButtonToBeDisabled(); }); + it('show no privileges to create api key', async () => { + await pageObjects.svlApiKeys.expectAPIKeyNoPrivileges(); + }); }); }); }); diff --git a/x-pack/test_serverless/functional/test_suites/security/common_configs/config.group7.ts b/x-pack/test_serverless/functional/test_suites/security/common_configs/config.group7.ts new file mode 100644 index 0000000000000..2239eb67441d8 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/security/common_configs/config.group7.ts @@ -0,0 +1,20 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseTestConfig = await readConfigFile(require.resolve('../config.ts')); + + return { + ...baseTestConfig.getAll(), + testFiles: [require.resolve('../../common/visualizations/group5')], + junit: { + reportName: 'Serverless Security Functional Tests - Common Group 7', + }, + }; +} diff --git a/x-pack/test_serverless/functional/test_suites/security/common_configs/config.group8.ts b/x-pack/test_serverless/functional/test_suites/security/common_configs/config.group8.ts new file mode 100644 index 0000000000000..0089206ce72f0 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/security/common_configs/config.group8.ts @@ -0,0 +1,20 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseTestConfig = await readConfigFile(require.resolve('../config.ts')); + + return { + ...baseTestConfig.getAll(), + testFiles: [require.resolve('../../common/visualizations/group6')], + junit: { + reportName: 'Serverless Security Functional Tests - Common Group 8', + }, + }; +}