From 8f12714219ca4b4c8e58678d42e9978c3defa40b Mon Sep 17 00:00:00 2001 From: Sid Date: Thu, 21 Nov 2024 15:14:54 +0100 Subject: [PATCH 01/18] [Session management] update cleanup to allow partial search results for PIT query (#200912) Closes https://github.com/elastic/kibana/issues/200008 ## Summary This PR updates the session cleanup task to allow partial results in the point in time query used to delete any invalid sessions. ### Notes Using a [recently introduced option by ES](https://github.com/elastic/elasticsearch/pull/111516), the session cleanup now allows the PIT to run over partial results. This should reduce the noise we see around session_cleanup errors in our logs. ### Release notes Fixes error with opening point in time query for session deletion by now accounting for partial results. ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] The PR description includes the appropriate Release Notes section, and the correct `release_node:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../security/server/session_management/session_index.test.ts | 5 +++++ .../security/server/session_management/session_index.ts | 1 + 2 files changed, 6 insertions(+) diff --git a/x-pack/plugins/security/server/session_management/session_index.test.ts b/x-pack/plugins/security/server/session_management/session_index.test.ts index e1890273469ed..04991f4aeefd6 100644 --- a/x-pack/plugins/security/server/session_management/session_index.test.ts +++ b/x-pack/plugins/security/server/session_management/session_index.test.ts @@ -473,6 +473,7 @@ describe('Session index', () => { expect(mockElasticsearchClient.search).toHaveBeenCalledTimes(1); expect(mockElasticsearchClient.search).toHaveBeenCalledWith({ _source_includes: 'usernameHash,provider', + allow_partial_search_results: true, sort: '_shard_doc', track_total_hits: false, search_after: undefined, @@ -555,6 +556,7 @@ describe('Session index', () => { expect(mockElasticsearchClient.search).toHaveBeenCalledTimes(1); expect(mockElasticsearchClient.search).toHaveBeenCalledWith({ _source_includes: 'usernameHash,provider', + allow_partial_search_results: true, sort: '_shard_doc', track_total_hits: false, search_after: undefined, @@ -649,6 +651,7 @@ describe('Session index', () => { expect(mockElasticsearchClient.search).toHaveBeenCalledTimes(1); expect(mockElasticsearchClient.search).toHaveBeenCalledWith({ _source_includes: 'usernameHash,provider', + allow_partial_search_results: true, sort: '_shard_doc', track_total_hits: false, search_after: undefined, @@ -737,6 +740,7 @@ describe('Session index', () => { expect(mockElasticsearchClient.search).toHaveBeenCalledTimes(1); expect(mockElasticsearchClient.search).toHaveBeenCalledWith({ _source_includes: 'usernameHash,provider', + allow_partial_search_results: true, sort: '_shard_doc', track_total_hits: false, search_after: undefined, @@ -850,6 +854,7 @@ describe('Session index', () => { expect(mockElasticsearchClient.search).toHaveBeenCalledTimes(1); expect(mockElasticsearchClient.search).toHaveBeenCalledWith({ _source_includes: 'usernameHash,provider', + allow_partial_search_results: true, sort: '_shard_doc', track_total_hits: false, search_after: undefined, diff --git a/x-pack/plugins/security/server/session_management/session_index.ts b/x-pack/plugins/security/server/session_management/session_index.ts index 9f11e9224243c..9166ec9deb91f 100644 --- a/x-pack/plugins/security/server/session_management/session_index.ts +++ b/x-pack/plugins/security/server/session_management/session_index.ts @@ -857,6 +857,7 @@ export class SessionIndex { size: SESSION_INDEX_CLEANUP_BATCH_SIZE, sort: '_shard_doc', track_total_hits: false, // for performance + allow_partial_search_results: true, }); const { hits } = searchResponse.hits; if (hits.length > 0) { From 889ce000eb18bf60d3dc65ec0b39dbf705c7184b Mon Sep 17 00:00:00 2001 From: Sid Date: Thu, 21 Nov 2024 15:15:13 +0100 Subject: [PATCH 02/18] [API keys] Improve functional tests for API keys management page (#200110) Closes https://github.com/elastic/kibana/issues/200756 ## Summary Enhance existing functional tests for API Keys querying to test filters and toggles while querying API keys. ### Notes The following tests were added: - Toggling the following filters displays the correct keys - Personal, Managed, Cross cluster types - Active or expired keys - Filtering by username by clicking the dropdown list - Added test for querying using the search bar **but it is skipped** for now as we'd like to fix the behavior. Tracked by https://github.com/elastic/kibana/issues/195795 ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios= - [ ] The PR description includes the appropriate Release Notes section, and the correct `release_node:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: Elastic Machine --- .../api_keys/api_keys_grid/api_keys_table.tsx | 7 + .../functional/apps/api_keys/home_page.ts | 129 ++++++++++++++++++ .../functional/page_objects/api_keys_page.ts | 29 ++++ 3 files changed, 165 insertions(+) diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_table.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_table.tsx index f536b5838bab7..8ceff7f1460f6 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_table.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_table.tsx @@ -274,6 +274,7 @@ export const ApiKeysTable: FunctionComponent = ({ = ({ que onFilterChange({ ...filters, type: filters.type === 'rest' ? undefined : 'rest' }); }} withNext={types.includes('cross_cluster') || types.includes('managed')} + data-test-subj="personalFilterButton" > = ({ que }); }} withNext={types.includes('managed')} + data-test-subj="crossClusterFilterButton" > = ({ que type: filters.type === 'managed' ? undefined : 'managed', }); }} + data-test-subj="managedFilterButton" > = ({ } }} withNext={true} + data-test-subj="activeFilterButton" > = ({ onFilterChange({ ...filters, expired: true }); } }} + data-test-subj="expiredFilterButton" > = ({ que numFilters={usernames.length} hasActiveFilters={numActiveFilters ? true : false} numActiveFilters={numActiveFilters} + data-test-subj="ownerFilterButton" > { ); }); }); + + describe('querying API keys', function () { + before(async () => { + await clearAllApiKeys(es, log); + await security.testUser.setRoles(['kibana_admin', 'test_api_keys']); + + await es.transport.request({ + method: 'POST', + path: '/_security/cross_cluster/api_key', + body: { + name: 'test_cross_cluster', + expiration: '1d', + access: { + search: [ + { + names: ['*'], + }, + ], + replication: [ + { + names: ['*'], + }, + ], + }, + }, + }); + + await es.security.createApiKey({ + name: 'my api key', + expiration: '1d', + role_descriptors: { + role_1: {}, + }, + metadata: { + managed: true, + }, + }); + + await es.security.createApiKey({ + name: 'Alerting: Managed', + expiration: '1d', + role_descriptors: { + role_1: {}, + }, + }); + + await es.security.createApiKey({ + name: 'test_api_key', + expiration: '1s', + role_descriptors: { + role_1: {}, + }, + }); + + await es.security.grantApiKey({ + api_key: { + name: 'test_user_api_key', + expiration: '1d', + }, + grant_type: 'password', + run_as: 'test_user', + username: 'elastic', + password: 'changeme', + }); + + await pageObjects.common.navigateToApp('apiKeys'); + }); + + after(async () => { + await security.testUser.restoreDefaults(); + await clearAllApiKeys(es, log); + }); + + it('active/expired filter buttons work as expected', async () => { + await pageObjects.apiKeys.clickExpiryFilters('active'); + await ensureApiKeysExist(['my api key', 'Alerting: Managed', 'test_cross_cluster']); + expect(await pageObjects.apiKeys.doesApiKeyExist('test_api_key')).to.be(false); + + await pageObjects.apiKeys.clickExpiryFilters('expired'); + await ensureApiKeysExist(['test_api_key']); + expect(await pageObjects.apiKeys.doesApiKeyExist('my api key')).to.be(false); + + // reset filter buttons + await pageObjects.apiKeys.clickExpiryFilters('expired'); + }); + + it('api key type filter buttons work as expected', async () => { + await pageObjects.apiKeys.clickTypeFilters('personal'); + + await ensureApiKeysExist(['test_api_key']); + + await pageObjects.apiKeys.clickTypeFilters('cross_cluster'); + + await ensureApiKeysExist(['test_cross_cluster']); + + await pageObjects.apiKeys.clickTypeFilters('managed'); + + await ensureApiKeysExist(['my api key', 'Alerting: Managed']); + + // reset filters by simulate clicking the managed filter button again + await pageObjects.apiKeys.clickTypeFilters('managed'); + }); + + it('username filter buttons work as expected', async () => { + await pageObjects.apiKeys.clickUserNameDropdown(); + expect( + await testSubjects.exists('userProfileSelectableOption-system_indices_superuser') + ).to.be(true); + expect(await testSubjects.exists('userProfileSelectableOption-test_user')).to.be(true); + + await testSubjects.click('userProfileSelectableOption-test_user'); + + await ensureApiKeysExist(['test_user_api_key']); + await testSubjects.click('userProfileSelectableOption-test_user'); + + await testSubjects.click('userProfileSelectableOption-system_indices_superuser'); + + await ensureApiKeysExist(['my api key', 'Alerting: Managed', 'test_cross_cluster']); + }); + + it.skip('search bar works as expected', async () => { + await pageObjects.apiKeys.setSearchBarValue('test_user_api_key'); + + await ensureApiKeysExist(['test_user_api_key']); + + await pageObjects.apiKeys.setSearchBarValue('"my api key"'); + await ensureApiKeysExist(['my api key']); + }); + }); }); }; diff --git a/x-pack/test/functional/page_objects/api_keys_page.ts b/x-pack/test/functional/page_objects/api_keys_page.ts index 9b196f70eeef0..efff9930f10a9 100644 --- a/x-pack/test/functional/page_objects/api_keys_page.ts +++ b/x-pack/test/functional/page_objects/api_keys_page.ts @@ -157,5 +157,34 @@ export function ApiKeysPageProvider({ getService }: FtrProviderContext) { const toast = await testSubjects.find('updateApiKeySuccessToast'); return toast.getVisibleText(); }, + + async clickExpiryFilters(type: 'active' | 'expired') { + const button = await testSubjects.find( + type === 'active' ? 'activeFilterButton' : 'expiredFilterButton' + ); + return button.click(); + }, + + async clickTypeFilters(type: 'personal' | 'managed' | 'cross_cluster') { + const buttonMap = { + personal: 'personalFilterButton', + managed: 'managedFilterButton', + cross_cluster: 'crossClusterFilterButton', + }; + + const button = await testSubjects.find(buttonMap[type]); + return button.click(); + }, + + async clickUserNameDropdown() { + const button = await testSubjects.find('ownerFilterButton'); + return button.click(); + }, + + async setSearchBarValue(query: string) { + const searchBar = await testSubjects.find('apiKeysSearchBar'); + await searchBar.clearValue(); + return searchBar.type(query); + }, }; } From 30e075a1b601a9bd5564667b67b3112479d1eebc Mon Sep 17 00:00:00 2001 From: Ilya Nikokoshev Date: Thu, 21 Nov 2024 16:34:07 +0100 Subject: [PATCH 03/18] [Automatic Import] Correctly output icons in the manifest (#201139) ## Release Note Fixes a bug in Automatic Import where icons were not shown after the integration was installed. ## Summary Closes #201008. When implementing safe manifest output #192316 a bug crept in: the icons array was incorrectly output as a dictionary icons: src: /img/logoElastic.svg title: syslog_test3 Logo size: 32x32 type: image/svg+xml and the test was not smart enough to pick it up: expect(manifest.icons).toBeTruthy(); We fix the field and add better tests for it. --- .../integration_builder/build_integration.test.ts | 9 ++++++++- .../integration_builder/build_integration.ts | 14 ++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.test.ts b/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.test.ts index 419e287e23bf7..d7ce89e2e8f63 100644 --- a/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.test.ts +++ b/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.test.ts @@ -277,6 +277,13 @@ describe('renderPackageManifestYAML', () => { expect(manifest.name).toBe(integration.name); expect(manifest.type).toBe('integration'); expect(manifest.description).toBe(integration.description); - expect(manifest.icons).toBeTruthy(); + expect(Array.isArray(manifest.icons)).toBe(true); + expect((manifest.icons as object[]).length).toBe(1); + expect((manifest.icons as object[])[0]).toEqual({ + src: '/img/logo.svg', + title: 'Sample Integration Logo', + size: '32x32', + type: 'image/svg+xml', + }); }); }); diff --git a/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.ts b/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.ts index 8743ada38bdb6..bf2e9b6b9d5a7 100644 --- a/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.ts +++ b/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.ts @@ -185,12 +185,14 @@ function createPackageManifestDict( }; if (package_logo !== undefined && package_logo !== '') { - data.icons = { - src: '/img/logo.svg', - title: `${package_title} Logo`, - size: '32x32', - type: 'image/svg+xml', - }; + data.icons = [ + { + src: '/img/logo.svg', + title: `${package_title} Logo`, + size: '32x32', + type: 'image/svg+xml', + }, + ]; } return data; } From f9287a954581113e0d4cbf5f90ac4eb2a19b7c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Thu, 21 Nov 2024 16:40:52 +0100 Subject: [PATCH 04/18] [Feature Flags] Set RUM transaction.outcome (#200576) --- .../src/feature_flags_service.test.ts | 62 +++++++++++++++++-- .../src/feature_flags_service.ts | 14 ++++- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/packages/core/feature-flags/core-feature-flags-browser-internal/src/feature_flags_service.test.ts b/packages/core/feature-flags/core-feature-flags-browser-internal/src/feature_flags_service.test.ts index 3f14a2dd92269..cc11599d48d54 100644 --- a/packages/core/feature-flags/core-feature-flags-browser-internal/src/feature_flags_service.test.ts +++ b/packages/core/feature-flags/core-feature-flags-browser-internal/src/feature_flags_service.test.ts @@ -8,10 +8,10 @@ */ import { firstValueFrom } from 'rxjs'; -import { apm } from '@elastic/apm-rum'; +import { Transaction, apm } from '@elastic/apm-rum'; import { type Client, OpenFeature, type Provider } from '@openfeature/web-sdk'; import { coreContextMock } from '@kbn/core-base-browser-mocks'; -import type { FeatureFlagsStart } from '@kbn/core-feature-flags-browser'; +import type { FeatureFlagsSetup, FeatureFlagsStart } from '@kbn/core-feature-flags-browser'; import { injectedMetadataServiceMock } from '@kbn/core-injected-metadata-browser-mocks'; import type { InternalInjectedMetadataSetup } from '@kbn/core-injected-metadata-browser-internal'; import { FeatureFlagsService } from '..'; @@ -63,7 +63,7 @@ describe('FeatureFlagsService Browser', () => { test('awaits initialization in the start context', async () => { const { setProvider } = featureFlagsService.setup({ injectedMetadata }); let externalResolve: Function = () => void 0; - const spy = jest.spyOn(OpenFeature, 'setProviderAndWait').mockImplementation(async () => { + const spy = jest.spyOn(OpenFeature, 'setProviderAndWait').mockImplementationOnce(async () => { await new Promise((resolve) => { externalResolve = resolve; }); @@ -80,7 +80,7 @@ describe('FeatureFlagsService Browser', () => { test('do not hold for too long during initialization', async () => { const { setProvider } = featureFlagsService.setup({ injectedMetadata }); - const spy = jest.spyOn(OpenFeature, 'setProviderAndWait').mockImplementation(async () => { + const spy = jest.spyOn(OpenFeature, 'setProviderAndWait').mockImplementationOnce(async () => { await new Promise(() => {}); // never resolves }); const apmCaptureErrorSpy = jest.spyOn(apm, 'captureError'); @@ -95,6 +95,60 @@ describe('FeatureFlagsService Browser', () => { expect.stringContaining('The feature flags provider took too long to initialize.') ); }); + + describe('APM instrumentation', () => { + const fakeProvider = { metadata: { name: 'fake provider' } } as Provider; + + let setProvider: FeatureFlagsSetup['setProvider']; + let apmSpy: jest.SpyInstance; + let setProviderSpy: jest.SpyInstance>; + + beforeEach(() => { + const setup = featureFlagsService.setup({ injectedMetadata }); + setProvider = setup.setProvider; + setProviderSpy = jest.spyOn(OpenFeature, 'setProviderAndWait'); + apmSpy = jest.spyOn(apm, 'startTransaction'); + }); + + test('starts an APM transaction to track the time it takes to set a provider', () => { + expect.assertions(1); + setProvider(fakeProvider); + expect(apmSpy).toHaveBeenCalledWith('set-provider', 'feature-flags'); + }); + + test('APM transaction tracks success', async () => { + expect.assertions(4); + + setProviderSpy.mockResolvedValueOnce(); + setProvider(fakeProvider); + + const transaction = apmSpy.mock.results[0].value; + const endTransactionSpy = jest.spyOn(transaction, 'end'); + expect(transaction.outcome).toBeUndefined(); + expect(endTransactionSpy).toHaveBeenCalledTimes(0); + await setProviderSpy.mock.results[0].value.catch(() => {}); + expect(transaction.outcome).toBe('success'); + expect(endTransactionSpy).toHaveBeenCalledTimes(1); + }); + + test('APM transaction tracks failures', async () => { + expect.assertions(5); + + const apmCaptureErrorSpy = jest.spyOn(apm, 'captureError'); + const error = new Error('Something went terribly wrong'); + setProviderSpy.mockRejectedValueOnce(error); + setProvider(fakeProvider); + + const transaction = apmSpy.mock.results[0].value; + const endTransactionSpy = jest.spyOn(transaction, 'end'); + expect(transaction.outcome).toBeUndefined(); + expect(endTransactionSpy).toHaveBeenCalledTimes(0); + await setProviderSpy.mock.results[0].value.catch(() => {}); + expect(apmCaptureErrorSpy).toHaveBeenCalledWith(error); + expect(transaction.outcome).toBe('failure'); + expect(endTransactionSpy).toHaveBeenCalledTimes(1); + }); + }); }); describe('context handling', () => { diff --git a/packages/core/feature-flags/core-feature-flags-browser-internal/src/feature_flags_service.ts b/packages/core/feature-flags/core-feature-flags-browser-internal/src/feature_flags_service.ts index afc32d93aee3c..388a4056e4a8e 100644 --- a/packages/core/feature-flags/core-feature-flags-browser-internal/src/feature_flags_service.ts +++ b/packages/core/feature-flags/core-feature-flags-browser-internal/src/feature_flags_service.ts @@ -71,11 +71,21 @@ export class FeatureFlagsService { const transaction = apm.startTransaction('set-provider', 'feature-flags'); this.isProviderReadyPromise = OpenFeature.setProviderAndWait(provider); this.isProviderReadyPromise - .then(() => transaction?.end()) + .then(() => { + if (transaction) { + // @ts-expect-error RUM types are not correct + transaction.outcome = 'success'; + transaction.end(); + } + }) .catch((err) => { this.logger.error(err); apm.captureError(err); - transaction?.end(); + if (transaction) { + // @ts-expect-error RUM types are not correct + transaction.outcome = 'failure'; + transaction.end(); + } }); }, appendContext: (contextToAppend) => this.appendContext(contextToAppend), From 324ecc2c37e59f55643bd5685bb1db08be4a4fb9 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Thu, 21 Nov 2024 11:12:10 -0500 Subject: [PATCH 05/18] fix(slo): Add missing new context providers around burn rate editor (#201199) --- .../slo/public/rules/register_burn_rate_rule_type.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/slo/public/rules/register_burn_rate_rule_type.ts b/x-pack/plugins/observability_solution/slo/public/rules/register_burn_rate_rule_type.ts index cea53c96ab0a0..cd0b5ec478362 100644 --- a/x-pack/plugins/observability_solution/slo/public/rules/register_burn_rate_rule_type.ts +++ b/x-pack/plugins/observability_solution/slo/public/rules/register_burn_rate_rule_type.ts @@ -67,7 +67,9 @@ export const registerBurnRateRuleType = ( documentationUrl(docLinks) { return `${docLinks.links.observability.sloBurnRateRule}`; }, - ruleParamsExpression: lazy(() => import('../components/burn_rate_rule_editor')), + ruleParamsExpression: lazyWithContextProviders( + lazy(() => import('../components/burn_rate_rule_editor')) + ), validate: validateBurnRateRule, requiresAppContext: false, defaultActionMessage: sloBurnRateDefaultActionMessage, From 0b34bbf47f7478c473cc8b8ad60945fd0aa46cc8 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 21 Nov 2024 17:18:00 +0100 Subject: [PATCH 06/18] [Console] Automate console definitions (#200935) --- .../kibana-console-definitions-sync.yml | 54 +++++++++++++++ .../pipelines/console_definitions_sync.yml | 10 +++ .../scripts/steps/console_definitions_sync.sh | 68 +++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 .buildkite/pipeline-resource-definitions/kibana-console-definitions-sync.yml create mode 100644 .buildkite/pipelines/console_definitions_sync.yml create mode 100755 .buildkite/scripts/steps/console_definitions_sync.sh diff --git a/.buildkite/pipeline-resource-definitions/kibana-console-definitions-sync.yml b/.buildkite/pipeline-resource-definitions/kibana-console-definitions-sync.yml new file mode 100644 index 0000000000000..a228823202c01 --- /dev/null +++ b/.buildkite/pipeline-resource-definitions/kibana-console-definitions-sync.yml @@ -0,0 +1,54 @@ +# yaml-language-server: $schema=https://gist.githubusercontent.com/elasticmachine/988b80dae436cafea07d9a4a460a011d/raw/rre.schema.json +apiVersion: backstage.io/v1alpha1 +kind: Resource +metadata: + name: bk-kibana-console-definitions-sync + description: Opens a PR if anything changes in the console definitions in elasticsearch-definitions + links: + - url: 'https://buildkite.com/elastic/kibana-console-definitions-sync' + title: Pipeline link +spec: + type: buildkite-pipeline + owner: 'group:kibana-management' + system: buildkite + implementation: + apiVersion: buildkite.elastic.dev/v1 + kind: Pipeline + metadata: + name: kibana / Console definitions sync + description: Opens a PR if anything changes in the console definitions in elasticsearch-definitions + spec: + env: + SLACK_NOTIFICATIONS_CHANNEL: '#kibana-management' + ELASTIC_SLACK_NOTIFICATIONS_ENABLED: 'true' + allow_rebuilds: false + branch_configuration: main + default_branch: main + repository: elastic/kibana + pipeline_file: .buildkite/pipelines/console_definitions_sync.yml + provider_settings: + build_branches: false + build_pull_requests: false + publish_commit_status: false + trigger_mode: none + build_tags: false + prefix_pull_request_fork_branch_names: false + skip_pull_request_builds_for_existing_commits: true + teams: + kibana-management: + access_level: MANAGE_BUILD_AND_READ + kibana-operations: + access_level: MANAGE_BUILD_AND_READ + appex-qa: + access_level: MANAGE_BUILD_AND_READ + kibana-tech-leads: + access_level: MANAGE_BUILD_AND_READ + everyone: + access_level: BUILD_AND_READ + schedules: + Weekly build: + cronline: 0 0 * * 1 America/New_York + message: Weekly build + branch: main + tags: + - kibana diff --git a/.buildkite/pipelines/console_definitions_sync.yml b/.buildkite/pipelines/console_definitions_sync.yml new file mode 100644 index 0000000000000..22d91eacbdbdb --- /dev/null +++ b/.buildkite/pipelines/console_definitions_sync.yml @@ -0,0 +1,10 @@ +steps: + - command: .buildkite/scripts/steps/console_definitions_sync.sh + label: Console Definitions Sync + timeout_in_minutes: 10 + agents: + image: family/kibana-ubuntu-2004 + imageProject: elastic-images-prod + provider: gcp + machineType: n2-standard-2 + preemptible: true diff --git a/.buildkite/scripts/steps/console_definitions_sync.sh b/.buildkite/scripts/steps/console_definitions_sync.sh new file mode 100755 index 0000000000000..55719292959e8 --- /dev/null +++ b/.buildkite/scripts/steps/console_definitions_sync.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +set -euo pipefail + +report_main_step () { + echo "--- $1" +} + +main () { + cd "$PARENT_DIR" + + report_main_step "Cloning repositories" + + rm -rf elasticsearch-specification + if ! git clone https://github.com/elastic/elasticsearch-specification --depth 1; then + echo "Error: Failed to clone the elasticsearch-specification repository." + exit 1 + fi + + cd "$KIBANA_DIR" + + report_main_step "Generating console definitions" + node scripts/generate_console_definitions.js --source "$PARENT_DIR/elasticsearch-specification" --emptyDest + + # Check if there are any differences + set +e + git diff --exit-code --quiet "$destination_file" + if [ $? -eq 0 ]; then + echo "No differences found. Exiting.." + exit + fi + set -e + + report_main_step "Differences found. Checking for an existing pull request." + + KIBANA_MACHINE_USERNAME="kibanamachine" + git config --global user.name "$KIBANA_MACHINE_USERNAME" + git config --global user.email '42973632+kibanamachine@users.noreply.github.com' + + PR_TITLE='[Console] Update console definitions' + PR_BODY='This PR updates the console definitions to match the latest ones from the @elastic/elasticsearch-specification repo.' + + # Check if a PR already exists + pr_search_result=$(gh pr list --search "$PR_TITLE" --state open --author "$KIBANA_MACHINE_USERNAME" --limit 1 --json title -q ".[].title") + + if [ "$pr_search_result" == "$PR_TITLE" ]; then + echo "PR already exists. Exiting.." + exit + fi + + echo "No existing PR found. Proceeding.." + + # Commit diff + BRANCH_NAME="console_definitions_sync_$(date +%s)" + + git checkout -b "$BRANCH_NAME" + + git add src/plugins/console/server/lib/spec_definitions/json/generated/* + git commit -m "Update console definitions" + + report_main_step "Changes committed. Creating pull request." + + git push origin "$BRANCH_NAME" + + # Create PR + gh pr create --title "$PR_TITLE" --body "$PR_BODY" --base main --head "${BRANCH_NAME}" --label 'release_note:skip' --label 'Feature:Console' --label 'Team:Kibana Management' +} + +main From 8b1c0f70cbe3d5e18a30523b010170179f8bd4b5 Mon Sep 17 00:00:00 2001 From: "Eyo O. Eyo" <7893459+eokoneyo@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:32:49 +0100 Subject: [PATCH 07/18] [React18] Migrate test suites to account for testing library upgrades appex-sharedux (#201153) This PR migrates test suites that use `renderHook` from the library `@testing-library/react-hooks` to adopt the equivalent and replacement of `renderHook` from the export that is now available from `@testing-library/react`. This work is required for the planned migration to react18. ## Context In this PR, usages of `waitForNextUpdate` that previously could have been destructured from `renderHook` are now been replaced with `waitFor` exported from `@testing-library/react`, furthermore `waitFor` that would also have been destructured from the same renderHook result is now been replaced with `waitFor` from the export of `@testing-library/react`. ***Why is `waitFor` a sufficient enough replacement for `waitForNextUpdate`, and better for testing values subject to async computations?*** WaitFor will retry the provided callback if an error is returned, till the configured timeout elapses. By default the retry interval is `50ms` with a timeout value of `1000ms` that effectively translates to at least 20 retries for assertions placed within waitFor. See https://testing-library.com/docs/dom-testing-library/api-async/#waitfor for more information. This however means that for person's writing tests, said person has to be explicit about expectations that describe the internal state of the hook being tested. This implies checking for instance when a react query hook is being rendered, there's an assertion that said hook isn't loading anymore. In this PR you'd notice that this pattern has been adopted, with most existing assertions following an invocation of `waitForNextUpdate` being placed within a `waitFor` invocation. In some cases the replacement is simply a `waitFor(() => new Promise((resolve) => resolve(null)))` (many thanks to @kapral18, for point out exactly why this works), where this suffices the assertions that follow aren't placed within a waitFor so this PR doesn't get larger than it needs to be. It's also worth pointing out this PR might also contain changes to test and application code to improve said existing test. ### What to do next? 1. Review the changes in this PR. 2. If you think the changes are correct, approve the PR. ## Any questions? If you have any questions or need help with this PR, please leave comments in this PR. --- .../modal/tabbed/src/context/index.test.tsx | 2 +- .../src/use_table_persist.test.ts | 2 +- .../content_client_mutation_hooks.test.tsx | 20 +++++++------------ .../content_client_query_hooks.test.tsx | 12 +++++------ 4 files changed, 14 insertions(+), 22 deletions(-) diff --git a/packages/shared-ux/modal/tabbed/src/context/index.test.tsx b/packages/shared-ux/modal/tabbed/src/context/index.test.tsx index a25504421b330..8c42dea9080c2 100644 --- a/packages/shared-ux/modal/tabbed/src/context/index.test.tsx +++ b/packages/shared-ux/modal/tabbed/src/context/index.test.tsx @@ -8,7 +8,7 @@ */ import React, { type ComponentProps, type ComponentType } from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { useModalContext, ModalContextProvider } from '.'; type ModalContextProviderProps = ComponentProps; diff --git a/packages/shared-ux/table_persist/src/use_table_persist.test.ts b/packages/shared-ux/table_persist/src/use_table_persist.test.ts index 51fbd93f7a214..9c88c97b8244a 100644 --- a/packages/shared-ux/table_persist/src/use_table_persist.test.ts +++ b/packages/shared-ux/table_persist/src/use_table_persist.test.ts @@ -8,7 +8,7 @@ */ import { CriteriaWithPagination } from '@elastic/eui'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { useEuiTablePersist } from './use_table_persist'; import { createStorage } from './storage'; // Mock this if it's external diff --git a/src/plugins/content_management/public/content_client/content_client_mutation_hooks.test.tsx b/src/plugins/content_management/public/content_client/content_client_mutation_hooks.test.tsx index d2ad215f46e4c..6e77a6c9c47da 100644 --- a/src/plugins/content_management/public/content_client/content_client_mutation_hooks.test.tsx +++ b/src/plugins/content_management/public/content_client/content_client_mutation_hooks.test.tsx @@ -8,7 +8,7 @@ */ import React, { FC, PropsWithChildren } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { ContentClientProvider } from './content_client_context'; import { ContentClient } from './content_client'; import { createCrudClientMock } from '../crud_client/crud_client.mock'; @@ -46,12 +46,10 @@ describe('useCreateContentMutation', () => { const input: CreateIn = { contentTypeId: 'testType', data: { foo: 'bar' }, version: 2 }; const output = { test: 'test' }; crudClient.create.mockResolvedValueOnce(output); - const { result, waitFor } = renderHook(() => useCreateContentMutation(), { wrapper: Wrapper }); + const { result } = renderHook(() => useCreateContentMutation(), { wrapper: Wrapper }); result.current.mutate(input); - await waitFor(() => result.current.isSuccess); - - expect(result.current.data).toEqual(output); + await waitFor(() => expect(result.current.data).toEqual(output)); }); }); @@ -66,12 +64,10 @@ describe('useUpdateContentMutation', () => { }; const output = { test: 'test' }; crudClient.update.mockResolvedValueOnce(output); - const { result, waitFor } = renderHook(() => useUpdateContentMutation(), { wrapper: Wrapper }); + const { result } = renderHook(() => useUpdateContentMutation(), { wrapper: Wrapper }); result.current.mutate(input); - await waitFor(() => result.current.isSuccess); - - expect(result.current.data).toEqual(output); + await waitFor(() => expect(result.current.data).toEqual(output)); }); }); @@ -81,11 +77,9 @@ describe('useDeleteContentMutation', () => { const input: DeleteIn = { contentTypeId: 'testType', id: 'test', version: 2 }; const output = { test: 'test' }; crudClient.delete.mockResolvedValueOnce(output); - const { result, waitFor } = renderHook(() => useDeleteContentMutation(), { wrapper: Wrapper }); + const { result } = renderHook(() => useDeleteContentMutation(), { wrapper: Wrapper }); result.current.mutate(input); - await waitFor(() => result.current.isSuccess); - - expect(result.current.data).toEqual(output); + await waitFor(() => expect(result.current.data).toEqual(output)); }); }); diff --git a/src/plugins/content_management/public/content_client/content_client_query_hooks.test.tsx b/src/plugins/content_management/public/content_client/content_client_query_hooks.test.tsx index 8cffde7ebd051..266e94641936e 100644 --- a/src/plugins/content_management/public/content_client/content_client_query_hooks.test.tsx +++ b/src/plugins/content_management/public/content_client/content_client_query_hooks.test.tsx @@ -8,7 +8,7 @@ */ import React, { FC, PropsWithChildren } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { ContentClientProvider } from './content_client_context'; import { ContentClient } from './content_client'; import { createCrudClientMock } from '../crud_client/crud_client.mock'; @@ -42,9 +42,8 @@ describe('useGetContentQuery', () => { const input: GetIn = { id: 'test', contentTypeId: 'testType', version: 2 }; const output = { test: 'test' }; crudClient.get.mockResolvedValueOnce(output); - const { result, waitFor } = renderHook(() => useGetContentQuery(input), { wrapper: Wrapper }); - await waitFor(() => result.current.isSuccess); - expect(result.current.data).toEqual(output); + const { result } = renderHook(() => useGetContentQuery(input), { wrapper: Wrapper }); + await waitFor(() => expect(result.current.data).toEqual(output)); }); }); @@ -54,10 +53,9 @@ describe('useSearchContentQuery', () => { const input: SearchIn = { contentTypeId: 'testType', query: {}, version: 2 }; const output = { hits: [{ id: 'test' }] }; crudClient.search.mockResolvedValueOnce(output); - const { result, waitFor } = renderHook(() => useSearchContentQuery(input), { + const { result } = renderHook(() => useSearchContentQuery(input), { wrapper: Wrapper, }); - await waitFor(() => result.current.isSuccess); - expect(result.current.data).toEqual(output); + await waitFor(() => expect(result.current.data).toEqual(output)); }); }); From fb35ae45df41b324a53669a735779b15d30f332f Mon Sep 17 00:00:00 2001 From: Milosz Marcinkowski <38698566+miloszmarcinkowski@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:37:05 +0100 Subject: [PATCH 08/18] Document the reason for skipped APM tests (#201214) Closes #199843 ### Summary This PR documents the reason for skipped Indices diagnostics API tests to avoid confusion in the future. APM diagnostics is an experimental internal tool. Indices diagnostics determine whether ingest pipelines were installed correctly by verifying the presence of the `observer.version` field in grok processor, this approach isn't reliable anymore. We should consider implementing improvement or sunsetting the feature if there is no maintainer. --- .../apm/diagnostics/indices.spec.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/diagnostics/indices.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/diagnostics/indices.spec.ts index 92976e6bce883..af0249d2a3359 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/diagnostics/indices.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/diagnostics/indices.spec.ts @@ -21,9 +21,10 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon let apmSynthtraceEsClient: ApmSynthtraceEsClient; - describe('Diagnostics: Indices', () => { - describe.skip('When there is no data', () => { - it('returns empty response`', async () => { + // Failing tests were skipped because the current solution for verifying ingest pipelines needs improvement + describe.skip('Diagnostics: Indices', () => { + describe('When there is no data', () => { + it('returns empty response', async () => { const { status, body } = await apmApiClient.adminUser({ endpoint: 'GET /internal/apm/diagnostics', }); @@ -34,7 +35,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); }); - describe.skip('When data is ingested', () => { + describe('When data is ingested', () => { before(async () => { const instance = apm .service({ name: 'synth-go', environment: 'production', agentName: 'go' }) @@ -68,7 +69,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); }); - describe.skip('When data is ingested without the necessary index templates', () => { + describe('When data is ingested without the necessary index templates', () => { before(async () => { await es.indices.deleteDataStream({ name: 'traces-apm-*' }); await es.indices.deleteIndexTemplate({ name: ['traces-apm'] }); @@ -114,7 +115,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); }); - describe.skip('ingest pipelines', () => { + describe('ingest pipelines', () => { before(async () => { const instance = apm .service({ name: 'synth-go', environment: 'production', agentName: 'go' }) @@ -138,7 +139,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon await apmSynthtraceEsClient.clean(); }); - describe.skip('an ingest pipeline is removed', () => { + describe('an ingest pipeline is removed', () => { before(async () => { const datastreamToUpdate = await es.indices.getDataStream({ name: 'metrics-apm.internal-default', @@ -168,7 +169,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); }); - describe.skip('an ingest pipeline is changed', () => { + describe('an ingest pipeline is changed', () => { before(async () => { const datastreamToUpdate = await es.indices.getDataStream({ name: 'metrics-apm.internal-default', From 71667b0fb002098ba7ae599c43ca88d401020a04 Mon Sep 17 00:00:00 2001 From: Jedr Blaszyk Date: Thu, 21 Nov 2024 17:38:43 +0100 Subject: [PATCH 09/18] [A11y][Crawler] Define radiogroups correctly in extraction rules flyout (#201191) ## Summary The issue: keyboard nav with tab doesn't jump between radiogroups correctly, instead skips some. Fix the issue with radiogroups selection with `TAB`, following the EUI docs: https://eui.elastic.co/#/forms/selection-controls#radio-group We need to > Pass a single `name` property to define the group. Tested locally that this is the culprit of issues when rendering multiple radio groups in the same flyout. ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [x] This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The `release_note:breaking` label should be applied in these situations. - [x] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../extraction_rules/edit_field_rule_flyout.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_field_rule_flyout.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_field_rule_flyout.tsx index 253d66d63820f..6dbda38ab1137 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_field_rule_flyout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/edit_field_rule_flyout.tsx @@ -199,6 +199,7 @@ export const EditFieldRuleFlyout: React.FC = ({ > = ({ > = ({ > Date: Thu, 21 Nov 2024 18:41:47 +0200 Subject: [PATCH 10/18] fix: [Search:Search Applications:Content page]Missing error text for Select searchable indices field (#200736) Closes: #200141 Closes: #199815 ### Description Fields which are in error should have error text that for user it should be instantly clear what is the error and how to fix it. ### What was changed: 1. Error handling was added for` applications/components/indices_select_combobox.tsx` component ### Screen image --- .../search_application/add_indices_flyout.tsx | 17 +++++++---------- .../components/indices_select_combobox.tsx | 18 +++++++++++++++++- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/components/search_application/add_indices_flyout.tsx b/x-pack/plugins/enterprise_search/public/applications/applications/components/search_application/add_indices_flyout.tsx index 0a0c7af7ed028..2f483d757505f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/applications/components/search_application/add_indices_flyout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/applications/components/search_application/add_indices_flyout.tsx @@ -19,7 +19,6 @@ import { EuiFlyoutBody, EuiFlyoutFooter, EuiFlyoutHeader, - EuiFormRow, EuiSpacer, EuiTitle, } from '@elastic/eui'; @@ -90,25 +89,22 @@ export const AddIndicesFlyout: React.FC = ({ onClose }) = )} - - - + /> = ({ onClose }) = & { 'data-telemetry-id'?: string; ignoredOptions?: string[]; + label?: string; }; export const IndicesSelectComboBox = ({ ignoredOptions, ...props }: IndicesSelectComboBoxProps) => { const [searchQuery, setSearchQuery] = useState(undefined); const { makeRequest } = useActions(FetchIndicesForSearchApplicationsAPILogic); const { status, data } = useValues(FetchIndicesForSearchApplicationsAPILogic); + const isInvalid = Boolean(searchQuery && !props.selectedOptions?.length); useEffect(() => { makeRequest({ searchQuery }); @@ -85,7 +88,20 @@ export const IndicesSelectComboBox = ({ ignoredOptions, ...props }: IndicesSelec renderOption, ...props, }; - return ; + + return ( + + + + ); }; export const indexToOption = ( From 76e9359d1b428961c79d8409d15255b747c839af Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 21 Nov 2024 18:42:09 +0200 Subject: [PATCH 11/18] fix: [Search:BehavioralAnalytics:Integration page]When generating API key, button behind dialog modal is announced (#200560) Closes: #200305 ## Description Elements which are behind dialogs shouldn't be announced as not to confuse users, especially the ones using assistive technology. ## Preconditions Stateful Behavioral Analytics -> Integration page is opened. Collection is added. ## What was changed: This PR apply the similar with [#197212](https://github.com/elastic/kibana/pull/197212) changes 1. Modal dialog was slightly updated to be more accessibility (a11y) friendly: - To differentiate the two UI states, we now use two colors for the panel: primary for the initial state and success when the API key is generated. - An `EuiCallOut` with `role="alert"` was added to announce status updates for screen reader users. 2. After creating an API key, the focus now moves to the Download API key button. ## Screen https://github.com/user-attachments/assets/3e72aeb5-34a2-43a6-b477-52a2f71b750a --- .../generate_analytics_api_key_modal.test.tsx | 7 ++- .../generate_analytics_api_key_modal.tsx | 52 +++++++++++++++---- .../generate_api_key_modal/modal.tsx | 6 ++- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/api_key_modal/generate_analytics_api_key_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/api_key_modal/generate_analytics_api_key_modal.test.tsx index 2dc27c7f7bfad..fa390d39e99d8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/api_key_modal/generate_analytics_api_key_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/api_key_modal/generate_analytics_api_key_modal.test.tsx @@ -9,9 +9,10 @@ import { setMockValues, setMockActions } from '../../../../../__mocks__/kea_logi import React from 'react'; -import { shallow, mount } from 'enzyme'; +import { shallow } from 'enzyme'; import { EuiModal, EuiFieldText, EuiCodeBlock } from '@elastic/eui'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; const mockActions = { makeRequest: jest.fn(), setKeyName: jest.fn() }; @@ -47,7 +48,9 @@ describe('GenerateAnalyticsApiKeyModal', () => { }); it('pre-set the key name with collection name', () => { - mount(); + mountWithIntl( + + ); expect(mockActions.setKeyName).toHaveBeenCalledWith('puggles API key'); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/api_key_modal/generate_analytics_api_key_modal.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/api_key_modal/generate_analytics_api_key_modal.tsx index 7cf5b76490c4f..bd5b7eed2a891 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/api_key_modal/generate_analytics_api_key_modal.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/api_key_modal/generate_analytics_api_key_modal.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useEffect } from 'react'; +import React, { useRef, useEffect } from 'react'; import { useValues, useActions } from 'kea'; @@ -24,12 +24,13 @@ import { EuiFieldText, EuiFormRow, EuiText, - EuiSpacer, - EuiFormLabel, EuiCodeBlock, + EuiCallOut, + useGeneratedHtmlId, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; import { generateAnalyticsApiKeyLogic } from '../../../../api/generate_analytics_api_key/generate_analytics_api_key_logic'; @@ -47,15 +48,23 @@ export const GenerateAnalyticsApiKeyModal: React.FC(null); + const modalTitleId = useGeneratedHtmlId(); + + useEffect(() => { + if (isSuccess) { + copyApiKeyRef.current?.focus(); + } + }, [isSuccess]); useEffect(() => { setKeyName(`${collectionName} API key`); }, [collectionName]); return ( - + - + {i18n.translate( 'xpack.enterpriseSearch.content.analytics.api.generateAnalyticsApiKeyModal.title', { @@ -66,15 +75,24 @@ export const GenerateAnalyticsApiKeyModal: React.FC <> - + {!isSuccess ? ( <> - + + } + fullWidth + > ) : ( - {keyName} - + {keyName}, + }} + /> + } + color="success" + iconType="check" + role="alert" + /> {apiKey ? ( ) : ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/modal.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/modal.tsx index d19568bea9e3c..5c0ba545bb565 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/modal.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/modal.tsx @@ -28,6 +28,7 @@ import { EuiLink, EuiCodeBlock, EuiCallOut, + useGeneratedHtmlId, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -51,6 +52,7 @@ export const GenerateApiKeyModal: React.FC = ({ indexN const { setKeyName } = useActions(GenerateApiKeyModalLogic); const { makeRequest } = useActions(GenerateApiKeyLogic); const copyApiKeyRef = useRef(null); + const modalTitleId = useGeneratedHtmlId(); useEffect(() => { if (isSuccess) { @@ -59,9 +61,9 @@ export const GenerateApiKeyModal: React.FC = ({ indexN }, [isSuccess]); return ( - + - + {i18n.translate('xpack.enterpriseSearch.content.overview.generateApiKeyModal.title', { defaultMessage: 'Generate API Key', })} From b202b6ba2d0cf921e67a95f9d369b35684e45a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:52:20 +0000 Subject: [PATCH 12/18] [Infra] Error for entities API, shown when navigating to infrastructure entity details (#201136) closes https://github.com/elastic/kibana/issues/201124 Screenshot 2024-11-21 at 12 05 18 --------- Co-authored-by: Carlos Crespo --- .../entities/get_data_stream_types.test.ts | 8 ++++ .../routes/entities/get_data_stream_types.ts | 4 ++ .../routes/entities/get_latest_entity.ts | 37 +++++++++++-------- .../infra/server/routes/entities/index.ts | 8 +++- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/observability_solution/infra/server/routes/entities/get_data_stream_types.test.ts b/x-pack/plugins/observability_solution/infra/server/routes/entities/get_data_stream_types.test.ts index e6bf32332a51f..75048ac22a6a8 100644 --- a/x-pack/plugins/observability_solution/infra/server/routes/entities/get_data_stream_types.test.ts +++ b/x-pack/plugins/observability_solution/infra/server/routes/entities/get_data_stream_types.test.ts @@ -10,6 +10,7 @@ import { type InfraMetricsClient } from '../../lib/helpers/get_infra_metrics_cli import { getDataStreamTypes } from './get_data_stream_types'; import { getHasMetricsData } from './get_has_metrics_data'; import { getLatestEntity } from './get_latest_entity'; +import { loggingSystemMock } from '@kbn/core/server/mocks'; jest.mock('./get_has_metrics_data', () => ({ getHasMetricsData: jest.fn(), @@ -25,6 +26,7 @@ describe('getDataStreamTypes', () => { let infraMetricsClient: jest.Mocked; let obsEsClient: jest.Mocked; let entityManagerClient: jest.Mocked; + const logger = loggingSystemMock.createLogger(); beforeEach(() => { infraMetricsClient = {} as jest.Mocked; @@ -43,6 +45,7 @@ describe('getDataStreamTypes', () => { infraMetricsClient, obsEsClient, entityManagerClient, + logger, }; const result = await getDataStreamTypes(params); @@ -65,6 +68,7 @@ describe('getDataStreamTypes', () => { infraMetricsClient, obsEsClient, entityManagerClient, + logger, }; const result = await getDataStreamTypes(params); @@ -84,6 +88,7 @@ describe('getDataStreamTypes', () => { infraMetricsClient, obsEsClient, entityManagerClient, + logger, }; const result = await getDataStreamTypes(params); @@ -95,6 +100,7 @@ describe('getDataStreamTypes', () => { entityId: 'entity123', entityType: 'host', entityManagerClient, + logger, }); }); @@ -109,6 +115,7 @@ describe('getDataStreamTypes', () => { infraMetricsClient, obsEsClient, entityManagerClient, + logger, }; const result = await getDataStreamTypes(params); @@ -128,6 +135,7 @@ describe('getDataStreamTypes', () => { infraMetricsClient, obsEsClient, entityManagerClient, + logger, }; const result = await getDataStreamTypes(params); diff --git a/x-pack/plugins/observability_solution/infra/server/routes/entities/get_data_stream_types.ts b/x-pack/plugins/observability_solution/infra/server/routes/entities/get_data_stream_types.ts index 2d587a6e7d9a9..4a949de4d0ed7 100644 --- a/x-pack/plugins/observability_solution/infra/server/routes/entities/get_data_stream_types.ts +++ b/x-pack/plugins/observability_solution/infra/server/routes/entities/get_data_stream_types.ts @@ -10,6 +10,7 @@ import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; import { EntityDataStreamType } from '@kbn/observability-shared-plugin/common'; import type { ObservabilityElasticsearchClient } from '@kbn/observability-utils-server/es/client/create_observability_es_client'; import { castArray } from 'lodash'; +import { Logger } from '@kbn/logging'; import { type InfraMetricsClient } from '../../lib/helpers/get_infra_metrics_client'; import { getHasMetricsData } from './get_has_metrics_data'; import { getLatestEntity } from './get_latest_entity'; @@ -21,6 +22,7 @@ interface Params { infraMetricsClient: InfraMetricsClient; obsEsClient: ObservabilityElasticsearchClient; entityManagerClient: EntityClient; + logger: Logger; } export async function getDataStreamTypes({ @@ -30,6 +32,7 @@ export async function getDataStreamTypes({ entityType, infraMetricsClient, obsEsClient, + logger, }: Params) { const hasMetricsData = await getHasMetricsData({ infraMetricsClient, @@ -48,6 +51,7 @@ export async function getDataStreamTypes({ entityId, entityType, entityManagerClient, + logger, }); if (latestEntity) { diff --git a/x-pack/plugins/observability_solution/infra/server/routes/entities/get_latest_entity.ts b/x-pack/plugins/observability_solution/infra/server/routes/entities/get_latest_entity.ts index 0756bc3d52c8f..c109f53be1f11 100644 --- a/x-pack/plugins/observability_solution/infra/server/routes/entities/get_latest_entity.ts +++ b/x-pack/plugins/observability_solution/infra/server/routes/entities/get_latest_entity.ts @@ -9,6 +9,7 @@ import { ENTITY_LATEST, entitiesAliasPattern } from '@kbn/entities-schema'; import { type EntityClient } from '@kbn/entityManager-plugin/server/lib/entity_client'; import { ENTITY_TYPE, SOURCE_DATA_STREAM_TYPE } from '@kbn/observability-shared-plugin/common'; import type { ObservabilityElasticsearchClient } from '@kbn/observability-utils-server/es/client/create_observability_es_client'; +import type { Logger } from '@kbn/logging'; const ENTITIES_LATEST_ALIAS = entitiesAliasPattern({ type: '*', @@ -24,32 +25,38 @@ export async function getLatestEntity({ entityId, entityType, entityManagerClient, + logger, }: { inventoryEsClient: ObservabilityElasticsearchClient; entityType: 'host' | 'container'; entityId: string; entityManagerClient: EntityClient; + logger: Logger; }): Promise { - const { definitions } = await entityManagerClient.getEntityDefinitions({ - builtIn: true, - type: entityType, - }); + try { + const { definitions } = await entityManagerClient.getEntityDefinitions({ + builtIn: true, + type: entityType, + }); - const hostOrContainerIdentityField = definitions[0]?.identityFields?.[0]?.field; - if (hostOrContainerIdentityField === undefined) { - return undefined; - } + const hostOrContainerIdentityField = definitions[0]?.identityFields?.[0]?.field; + if (hostOrContainerIdentityField === undefined) { + return undefined; + } - const response = await inventoryEsClient.esql<{ - source_data_stream?: { type?: string | string[] }; - }>('get_latest_entities', { - query: `FROM ${ENTITIES_LATEST_ALIAS} + const response = await inventoryEsClient.esql<{ + source_data_stream?: { type?: string | string[] }; + }>('get_latest_entities', { + query: `FROM ${ENTITIES_LATEST_ALIAS} | WHERE ${ENTITY_TYPE} == ? | WHERE ${hostOrContainerIdentityField} == ? | KEEP ${SOURCE_DATA_STREAM_TYPE} `, - params: [entityType, entityId], - }); + params: [entityType, entityId], + }); - return { sourceDataStreamType: response[0].source_data_stream?.type }; + return { sourceDataStreamType: response[0].source_data_stream?.type }; + } catch (e) { + logger.error(e); + } } diff --git a/x-pack/plugins/observability_solution/infra/server/routes/entities/index.ts b/x-pack/plugins/observability_solution/infra/server/routes/entities/index.ts index 30be4fc9da498..46f2cecf45254 100644 --- a/x-pack/plugins/observability_solution/infra/server/routes/entities/index.ts +++ b/x-pack/plugins/observability_solution/infra/server/routes/entities/index.ts @@ -36,8 +36,11 @@ export const initEntitiesConfigurationRoutes = (libs: InfraBackendLibs) => { }, async (requestContext, request, response) => { const { entityId, entityType } = request.params; - const coreContext = await requestContext.core; - const infraContext = await requestContext.infra; + const [coreContext, infraContext] = await Promise.all([ + requestContext.core, + requestContext.infra, + ]); + const entityManagerClient = await infraContext.entityManager.getScopedClient({ request }); const infraMetricsClient = await getInfraMetricsClient({ request, @@ -63,6 +66,7 @@ export const initEntitiesConfigurationRoutes = (libs: InfraBackendLibs) => { entityType, infraMetricsClient, obsEsClient, + logger, }); return response.ok({ From e378c884cd476c13cba86794127cca8e68c390cb Mon Sep 17 00:00:00 2001 From: Saikat Sarkar <132922331+saikatsarkar056@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:52:36 -0700 Subject: [PATCH 13/18] Remove the callout for upgrading to get enterprise-level features (#200283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR resolves this [issue](https://github.com/elastic/search-team/issues/8523). ### Before Screenshot 2024-11-14 at 4 52 14 PM ### After Screenshot 2024-11-14 at 4 52 55 PM --- .../product_selector.test.tsx | 4 -- .../product_selector/product_selector.tsx | 6 --- .../components/setup_guide/index.ts | 1 - .../setup_guide/setup_guide_cta.scss | 10 ----- .../setup_guide/setup_guide_cta.test.tsx | 21 --------- .../setup_guide/setup_guide_cta.tsx | 45 ------------------- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - .../apps/group3/enterprise_search.ts | 9 ---- 10 files changed, 99 deletions(-) delete mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.scss delete mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.test.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.test.tsx index 70f8412eeb5b4..dd67bf33d987b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.test.tsx @@ -13,7 +13,6 @@ import { shallow } from 'enzyme'; import { ErrorStateCallout } from '../../../shared/error_state'; -import { SetupGuideCta } from '../setup_guide'; import { TrialCallout } from '../trial_callout'; import { ElasticsearchProductCard } from './elasticsearch_product_card'; @@ -26,7 +25,6 @@ describe('ProductSelector', () => { const wrapper = shallow(); expect(wrapper.find(ElasticsearchProductCard)).toHaveLength(1); - expect(wrapper.find(SetupGuideCta)).toHaveLength(1); }); it('renders the trial callout', () => { @@ -62,14 +60,12 @@ describe('ProductSelector', () => { const wrapper = shallow(); expect(wrapper.find(ElasticsearchProductCard)).toHaveLength(1); - expect(wrapper.find(SetupGuideCta)).toHaveLength(0); }); it('does not render EnterpriseSearch card without access', () => { const wrapper = shallow(); expect(wrapper.find(ElasticsearchProductCard)).toHaveLength(1); - expect(wrapper.find(SetupGuideCta)).toHaveLength(0); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx index 71139a8b36402..1f25f5f69c2e0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx @@ -30,7 +30,6 @@ import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/ import headerImage from '../../assets/search_header.png'; import { EnterpriseSearchOverviewPageTemplate } from '../layout'; -import { SetupGuideCta } from '../setup_guide'; import { TrialCallout } from '../trial_callout'; import { ElasticsearchProductCard } from './elasticsearch_product_card'; @@ -121,11 +120,6 @@ export const ProductSelector: React.FC = () => { - {!config.host && config.canDeployEntSearch && ( - - - - )} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/index.ts index ba2e47b204648..8f952f9406102 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/index.ts @@ -6,4 +6,3 @@ */ export { SetupGuide } from './setup_guide'; -export { SetupGuideCta } from './setup_guide_cta'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.scss b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.scss deleted file mode 100644 index b3e2ffd8c11e3..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.scss +++ /dev/null @@ -1,10 +0,0 @@ -.enterpriseSearchSetupCta { - &__image { - width: $euiSize * 10; - margin: 0 auto; - - @include euiBreakpoint('xs', 's') { - width: $euiSize * 15; - } - } -} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.test.tsx deleted file mode 100644 index 2516382914d6e..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.test.tsx +++ /dev/null @@ -1,21 +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 { shallow } from 'enzyme'; - -import { SetupGuideCta } from '.'; - -describe('SetupGuideCta', () => { - it('renders', () => { - const wrapper = shallow(); - - expect(wrapper.find('.enterpriseSearchSetupCta')).toHaveLength(1); - expect(wrapper.find('EuiImage')).toHaveLength(1); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.tsx deleted file mode 100644 index 346477b08dbb9..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.tsx +++ /dev/null @@ -1,45 +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 { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiText, EuiImage } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { EuiPanelTo } from '../../../shared/react_router_helpers'; -import { PRODUCT_SELECTOR_CALLOUT_HEADING } from '../../constants'; - -import CtaImage from './assets/getting_started.png'; -import './setup_guide_cta.scss'; - -export const SetupGuideCta: React.FC = () => ( - - - - -

{PRODUCT_SELECTOR_CALLOUT_HEADING}

-
- - {i18n.translate('xpack.enterpriseSearch.overview.setupCta.description', { - defaultMessage: - 'Add search to your app or internal organization with Elastic App Search and Workplace Search. Watch the video to see what you can do when search is made easy.', - })} - -
- - - -
-
-); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index f64646a2bf3d2..45533bf57574a 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -18591,7 +18591,6 @@ "xpack.enterpriseSearch.overview.gettingStarted.testConnection.description": "Envoyez une requête de test pour confirmer que votre client de langage et votre instance Elasticsearch sont opérationnels.", "xpack.enterpriseSearch.overview.gettingStarted.testConnection.title": "Tester votre connexion", "xpack.enterpriseSearch.overview.navTitle": "Aperçu", - "xpack.enterpriseSearch.overview.setupCta.description": "Ajoutez des fonctions de recherche à votre application ou à votre organisation interne avec Elastic App Search et Workplace Search. Regardez la vidéo pour savoir ce qu'il est possible de faire lorsque la recherche est facilitée.", "xpack.enterpriseSearch.pageTemplate.endpointsButtonLabel": "Points de terminaison et clés d'API", "xpack.enterpriseSearch.passwordLabel": "Mot de passe", "xpack.enterpriseSearch.pipeline.title": "Transformer et enrichir vos données", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index cb39940e6ffb6..9d947185a869d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -18563,7 +18563,6 @@ "xpack.enterpriseSearch.overview.gettingStarted.testConnection.description": "テストリクエストを送信して、言語クライアントとElasticsearchインスタンスが起動し、実行中であることを確認してください。", "xpack.enterpriseSearch.overview.gettingStarted.testConnection.title": "接続をテスト", "xpack.enterpriseSearch.overview.navTitle": "概要", - "xpack.enterpriseSearch.overview.setupCta.description": "Elastic App Search および Workplace Search を使用して、アプリまたは社内組織に検索を追加できます。検索が簡単になるとどのような利点があるのかについては、動画をご覧ください。", "xpack.enterpriseSearch.pageTemplate.endpointsButtonLabel": "エンドポイントとAPIキー", "xpack.enterpriseSearch.passwordLabel": "パスワード", "xpack.enterpriseSearch.pipeline.title": "データの変換とエンリッチ", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 150003b98dd48..661a43585defa 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -18227,7 +18227,6 @@ "xpack.enterpriseSearch.overview.gettingStarted.testConnection.description": "发送测试请求,以确认您的语言客户端和 Elasticsearch 实例已启动并正在运行。", "xpack.enterpriseSearch.overview.gettingStarted.testConnection.title": "测试您的连接", "xpack.enterpriseSearch.overview.navTitle": "概览", - "xpack.enterpriseSearch.overview.setupCta.description": "通过 Elastic App Search 和 Workplace Search,将搜索添加到您的应用或内部组织中。观看视频,了解方便易用的搜索功能可以帮您做些什么。", "xpack.enterpriseSearch.pageTemplate.endpointsButtonLabel": "终端和 API 密钥", "xpack.enterpriseSearch.passwordLabel": "密码", "xpack.enterpriseSearch.pipeline.title": "转换和扩充数据", diff --git a/x-pack/test/accessibility/apps/group3/enterprise_search.ts b/x-pack/test/accessibility/apps/group3/enterprise_search.ts index 3ef1c02c7b8a8..976f16a6c7151 100644 --- a/x-pack/test/accessibility/apps/group3/enterprise_search.ts +++ b/x-pack/test/accessibility/apps/group3/enterprise_search.ts @@ -46,15 +46,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); await a11y.testAppSnapshot(); }); - - it('loads a setup guide', async function () { - await testSubjects.click('setupGuideLink'); - await retry.waitFor( - 'setup guide visible', - async () => await testSubjects.exists('setupGuide') - ); - await a11y.testAppSnapshot(); - }); }); describe('Content', () => { From 414d2a4948890907eec0360510e75279a5044a2d Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Thu, 21 Nov 2024 18:06:07 +0100 Subject: [PATCH 14/18] [Security Solution] Fix : skip failing MKI test (#201120) ## Summary Skips Failing MKI tests --- .../alerts/alerts_cell_actions.cy.ts | 98 ++++++++++--------- 1 file changed, 54 insertions(+), 44 deletions(-) diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_cell_actions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_cell_actions.cy.ts index 107a170e9cc2d..f1fcf7f76cba7 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_cell_actions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_cell_actions.cy.ts @@ -47,57 +47,67 @@ describe('Alerts cell actions', { tags: ['@ess', '@serverless'] }, () => { waitForAlertsToPopulate(); }); - it('should filter in and out existing values', () => { - scrollAlertTableColumnIntoViewAndTest(ALERT_TABLE_SEVERITY_HEADER, () => { - cy.get(ALERT_TABLE_SEVERITY_VALUES) - .first() - .invoke('text') - .then((severityVal) => { - filterForAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); - cy.get(FILTER_BADGE).first().should('have.text', `kibana.alert.severity: ${severityVal}`); - }); - removeKqlFilter(); - }); + // Flaky in Serverless MKI only + // https://github.com/elastic/kibana/issues/201117 + it( + 'should filter in and out existing values', + { + tags: ['@skipInServerlessMKI'], + }, + () => { + scrollAlertTableColumnIntoViewAndTest(ALERT_TABLE_SEVERITY_HEADER, () => { + cy.get(ALERT_TABLE_SEVERITY_VALUES) + .first() + .invoke('text') + .then((severityVal) => { + filterForAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); + cy.get(FILTER_BADGE) + .first() + .should('have.text', `kibana.alert.severity: ${severityVal}`); + }); + removeKqlFilter(); + }); - cy.log('should work for empty properties'); - // add query condition to make sure the field is empty - fillKqlQueryBar('not file.name: *{enter}'); + cy.log('should work for empty properties'); + // add query condition to make sure the field is empty + fillKqlQueryBar('not file.name: *{enter}'); - scrollAlertTableColumnIntoViewAndTest(ALERT_TABLE_FILE_NAME_HEADER, () => { - cy.log('filter for alert property'); + scrollAlertTableColumnIntoViewAndTest(ALERT_TABLE_FILE_NAME_HEADER, () => { + cy.log('filter for alert property'); - filterForAlertProperty(ALERT_TABLE_FILE_NAME_VALUES, 0); + filterForAlertProperty(ALERT_TABLE_FILE_NAME_VALUES, 0); - cy.get(FILTER_BADGE).first().should('have.text', 'NOT file.name: exists'); - removeKqlFilter(); - }); + cy.get(FILTER_BADGE).first().should('have.text', 'NOT file.name: exists'); + removeKqlFilter(); + }); - cy.log('filter out alert property'); + cy.log('filter out alert property'); - scrollAlertTableColumnIntoViewAndTest(ALERT_TABLE_FILE_NAME_HEADER, () => { - cy.get(ALERT_TABLE_FILE_NAME_VALUES) - .first() - .then(() => { - filterOutAlertProperty(ALERT_TABLE_FILE_NAME_VALUES, 0); - cy.get(FILTER_BADGE).first().should('have.text', 'file.name: exists'); - }); - removeKqlFilter(); - }); - - cy.log('should filter out a non-empty property'); + scrollAlertTableColumnIntoViewAndTest(ALERT_TABLE_FILE_NAME_HEADER, () => { + cy.get(ALERT_TABLE_FILE_NAME_VALUES) + .first() + .then(() => { + filterOutAlertProperty(ALERT_TABLE_FILE_NAME_VALUES, 0); + cy.get(FILTER_BADGE).first().should('have.text', 'file.name: exists'); + }); + removeKqlFilter(); + }); - scrollAlertTableColumnIntoViewAndTest(ALERT_TABLE_SEVERITY_HEADER, () => { - cy.get(ALERT_TABLE_SEVERITY_VALUES) - .first() - .invoke('text') - .then((severityVal) => { - filterOutAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); - cy.get(FILTER_BADGE) - .first() - .should('have.text', `NOT kibana.alert.severity: ${severityVal}`); - }); - }); - }); + cy.log('should filter out a non-empty property'); + + scrollAlertTableColumnIntoViewAndTest(ALERT_TABLE_SEVERITY_HEADER, () => { + cy.get(ALERT_TABLE_SEVERITY_VALUES) + .first() + .invoke('text') + .then((severityVal) => { + filterOutAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); + cy.get(FILTER_BADGE) + .first() + .should('have.text', `NOT kibana.alert.severity: ${severityVal}`); + }); + }); + } + ); it('should allow copy paste', () => { scrollAlertTableColumnIntoViewAndTest(ALERT_TABLE_SEVERITY_HEADER, () => { From 74cf5d45784b9f633decae428c61ff96281dcc4b Mon Sep 17 00:00:00 2001 From: jennypavlova Date: Thu, 21 Nov 2024 18:14:43 +0100 Subject: [PATCH 15/18] [Inventory] Fix the link to discover test (#201197) Closes #201189 ## Summary After this fix was added in https://github.com/elastic/kibana/pull/200984 the test started failing as it was verifying the previous kuery value - it was missing the `" "` so after this bug was fixed the test should be updated as well (basically changing `container.id:foo` with `container.id:"foo"`) and this PR updates the test. I checked locally and the test is passing now. --- .../observability_solution/inventory/e2e/cypress/e2e/home.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/home.cy.ts b/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/home.cy.ts index ce7bdfd102a40..fdb68826e9dc8 100644 --- a/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/home.cy.ts +++ b/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/home.cy.ts @@ -225,7 +225,7 @@ describe('Home page', () => { cy.getByTestSubj('inventoryEntityActionOpenInDiscover').click(); cy.url().should( 'include', - "query:'container.id:%20foo%20AND%20entity.definition_id%20:%20builtin*" + "query:'container.id:%20%22foo%22%20AND%20entity.definition_id%20:%20builtin*" ); }); }); From 03c3d775185e3aab8d3f32f12e2a475cf3e2ce77 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 22 Nov 2024 04:17:37 +1100 Subject: [PATCH 16/18] skip failing test suite (#200758) --- .../entity_store/trial_license_complete_tier/entity_store.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/trial_license_complete_tier/entity_store.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/trial_license_complete_tier/entity_store.ts index 8bad52ae41bdb..0c5d86fa54800 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/trial_license_complete_tier/entity_store.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/entity_store/trial_license_complete_tier/entity_store.ts @@ -14,7 +14,8 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const utils = EntityStoreUtils(getService); - describe('@ess @skipInServerlessMKI Entity Store APIs', () => { + // Failing: See https://github.com/elastic/kibana/issues/200758 + describe.skip('@ess @skipInServerlessMKI Entity Store APIs', () => { const dataView = dataViewRouteHelpersFactory(supertest); before(async () => { From d8d7b7a3272eaa79774ad3850003c435035c16dc Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Thu, 21 Nov 2024 17:19:50 +0000 Subject: [PATCH 17/18] skip flaky suite (#192672) --- .../public/components/user_actions/show_more_button.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/cases/public/components/user_actions/show_more_button.test.tsx b/x-pack/plugins/cases/public/components/user_actions/show_more_button.test.tsx index 58c152f6b0b3c..34a0ad2713373 100644 --- a/x-pack/plugins/cases/public/components/user_actions/show_more_button.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/show_more_button.test.tsx @@ -14,7 +14,8 @@ import { createAppMockRenderer } from '../../common/mock'; const showMoreClickMock = jest.fn(); -describe('ShowMoreButton', () => { +// FLAKY: https://github.com/elastic/kibana/issues/192672 +describe.skip('ShowMoreButton', () => { let appMockRender: AppMockRenderer; beforeEach(() => { From cba99de545ebfe2a2864701122555b00a989d91b Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Thu, 21 Nov 2024 17:23:29 +0000 Subject: [PATCH 18/18] skip flaky suite (#191804) --- .../public/components/package_policy_actions_menu.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx index 7195eb73890f2..f016acf8783aa 100644 --- a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx +++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx @@ -109,7 +109,8 @@ function createMockPackagePolicy( ...props, }; } -describe('PackagePolicyActionsMenu', () => { +// FLAKY: https://github.com/elastic/kibana/issues/191804 +describe.skip('PackagePolicyActionsMenu', () => { beforeAll(() => { useMultipleAgentPoliciesMock.mockReturnValue({ canUseMultipleAgentPolicies: false }); });