From 92ff716b750c2a47bf55ff280e0621e553f1f019 Mon Sep 17 00:00:00 2001 From: Maxim Palenov <maxim.palenov@elastic.co> Date: Mon, 28 Aug 2023 11:20:31 +0200 Subject: [PATCH 01/49] [Security Solution] Fix rules table filtering by tags with special characters (#163767) **Fixes: https://github.com/elastic/kibana/issues/163692** ## Summary This PR fixes rules table filtering for tags with special characters like colon `category:tag`. We didn't have this bug in `8.9` it was introduced by https://github.com/elastic/kibana/pull/160480 in `8.10` scope. ## Details Coverage Overview Dashboard required very similar rule filtering functionality as rule table has so https://github.com/elastic/kibana/pull/160480 moved the common logic to `common` folder and started using `escapeKuery` from `@kbn/es-query` instead of custom `escapeKuery` defined in Security Solution in `x-pack/plugins/security_solution/public/common/lib/kuery/index.ts`. The difference is the first function escapes all the special characters `\():<>"*` but the second escapes only quotes but the value must be enclosed in quotes to be passed on. Both ways are correct according to [docs](https://www.elastic.co/guide/en/kibana/current/kuery-query.html). So escaping all the special characters and enclosing the value in quotes breaks rules search. ### How was it fixed? Escaping related code in `x-pack/plugins/security_solution/common/utils/kql.ts` (`convertRulesFilterToKQL` in particular) was moved to `x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts` as Coverage Overview Dashboard API endpoint and rules table UI share the same KQL helpers and refactored along the way to be much more transparent. ### Checklist - [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 --- .../rule_management}/rule_fields.ts | 0 .../rule_management/rule_filtering.test.ts | 89 ++++++++++++ .../rule_management/rule_filtering.ts | 113 +++++++++++++++ .../common/utils/kql.test.ts | 128 ++++++++--------- .../security_solution/common/utils/kql.ts | 132 +++++------------- .../public/common/lib/kuery/index.test.ts | 58 +------- .../public/common/lib/kuery/index.ts | 34 +---- .../rule_management/api/api.test.ts | 2 +- .../rule_management/api/api.ts | 2 +- .../bulk_actions/use_bulk_actions.tsx | 2 +- .../utils/prepare_search_params.test.ts | 4 +- .../utils/prepare_search_params.ts | 2 +- .../hosts/pages/details/helpers.test.ts | 31 +--- .../explore/hosts/pages/details/helpers.ts | 18 --- .../timelines/components/timeline/helpers.tsx | 9 +- .../handle_coverage_overview_request.ts | 2 +- .../search/get_existing_prepackaged_rules.ts | 3 +- .../rules_table/rules_table_filtering.cy.ts | 47 +++++++ .../cypress/tasks/alerts_detection_rules.ts | 14 ++ 19 files changed, 376 insertions(+), 314 deletions(-) rename x-pack/plugins/security_solution/common/{ => detection_engine/rule_management}/rule_fields.ts (100%) create mode 100644 x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.test.ts create mode 100644 x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts diff --git a/x-pack/plugins/security_solution/common/rule_fields.ts b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts similarity index 100% rename from x-pack/plugins/security_solution/common/rule_fields.ts rename to x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts diff --git a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.test.ts b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.test.ts new file mode 100644 index 0000000000000..d40aadadb184f --- /dev/null +++ b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.test.ts @@ -0,0 +1,89 @@ +/* + * 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 { convertRulesFilterToKQL } from './rule_filtering'; + +describe('convertRulesFilterToKQL', () => { + const filterOptions = { + filter: '', + showCustomRules: false, + showElasticRules: false, + tags: [], + }; + + it('returns empty string if filter options are empty', () => { + const kql = convertRulesFilterToKQL(filterOptions); + + expect(kql).toBe(''); + }); + + it('handles presence of "filter" properly', () => { + const kql = convertRulesFilterToKQL({ ...filterOptions, filter: 'foo' }); + + expect(kql).toBe( + '(alert.attributes.name: "foo" OR alert.attributes.params.index: "foo" OR alert.attributes.params.threat.tactic.id: "foo" OR alert.attributes.params.threat.tactic.name: "foo" OR alert.attributes.params.threat.technique.id: "foo" OR alert.attributes.params.threat.technique.name: "foo" OR alert.attributes.params.threat.technique.subtechnique.id: "foo" OR alert.attributes.params.threat.technique.subtechnique.name: "foo")' + ); + }); + + it('escapes "filter" value properly', () => { + const kql = convertRulesFilterToKQL({ ...filterOptions, filter: '" OR (foo: bar)' }); + + expect(kql).toBe( + '(alert.attributes.name: "\\" OR (foo: bar)" OR alert.attributes.params.index: "\\" OR (foo: bar)" OR alert.attributes.params.threat.tactic.id: "\\" OR (foo: bar)" OR alert.attributes.params.threat.tactic.name: "\\" OR (foo: bar)" OR alert.attributes.params.threat.technique.id: "\\" OR (foo: bar)" OR alert.attributes.params.threat.technique.name: "\\" OR (foo: bar)" OR alert.attributes.params.threat.technique.subtechnique.id: "\\" OR (foo: bar)" OR alert.attributes.params.threat.technique.subtechnique.name: "\\" OR (foo: bar)")' + ); + }); + + it('handles presence of "showCustomRules" properly', () => { + const kql = convertRulesFilterToKQL({ ...filterOptions, showCustomRules: true }); + + expect(kql).toBe(`alert.attributes.params.immutable: false`); + }); + + it('handles presence of "showElasticRules" properly', () => { + const kql = convertRulesFilterToKQL({ ...filterOptions, showElasticRules: true }); + + expect(kql).toBe(`alert.attributes.params.immutable: true`); + }); + + it('handles presence of "showElasticRules" and "showCustomRules" at the same time properly', () => { + const kql = convertRulesFilterToKQL({ + ...filterOptions, + showElasticRules: true, + showCustomRules: true, + }); + + expect(kql).toBe(''); + }); + + it('handles presence of "tags" properly', () => { + const kql = convertRulesFilterToKQL({ ...filterOptions, tags: ['tag1', 'tag2'] }); + + expect(kql).toBe('alert.attributes.tags:("tag1" AND "tag2")'); + }); + + it('handles combination of different properties properly', () => { + const kql = convertRulesFilterToKQL({ + ...filterOptions, + filter: 'foo', + showElasticRules: true, + tags: ['tag1', 'tag2'], + }); + + expect(kql).toBe( + `(alert.attributes.name: "foo" OR alert.attributes.params.index: "foo" OR alert.attributes.params.threat.tactic.id: "foo" OR alert.attributes.params.threat.tactic.name: "foo" OR alert.attributes.params.threat.technique.id: "foo" OR alert.attributes.params.threat.technique.name: "foo" OR alert.attributes.params.threat.technique.subtechnique.id: "foo" OR alert.attributes.params.threat.technique.subtechnique.name: "foo") AND alert.attributes.params.immutable: true AND alert.attributes.tags:(\"tag1\" AND \"tag2\")` + ); + }); + + it('handles presence of "excludeRuleTypes" properly', () => { + const kql = convertRulesFilterToKQL({ + ...filterOptions, + excludeRuleTypes: ['machine_learning', 'saved_query'], + }); + + expect(kql).toBe('NOT alert.attributes.params.type: ("machine_learning" OR "saved_query")'); + }); +}); diff --git a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts new file mode 100644 index 0000000000000..b8fe93efc722a --- /dev/null +++ b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts @@ -0,0 +1,113 @@ +/* + * 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 { Type } from '@kbn/securitysolution-io-ts-alerting-types'; +import { RuleExecutionStatus } from '../../api/detection_engine'; +import { prepareKQLStringParam } from '../../utils/kql'; +import { + ENABLED_FIELD, + LAST_RUN_OUTCOME_FIELD, + PARAMS_IMMUTABLE_FIELD, + PARAMS_TYPE_FIELD, + RULE_NAME_FIELD, + RULE_PARAMS_FIELDS, + TAGS_FIELD, +} from './rule_fields'; + +export const KQL_FILTER_IMMUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: true`; +export const KQL_FILTER_MUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: false`; +export const KQL_FILTER_ENABLED_RULES = `${ENABLED_FIELD}: true`; +export const KQL_FILTER_DISABLED_RULES = `${ENABLED_FIELD}: false`; + +interface RulesFilterOptions { + filter: string; + showCustomRules: boolean; + showElasticRules: boolean; + enabled: boolean; + tags: string[]; + excludeRuleTypes: Type[]; + ruleExecutionStatus: RuleExecutionStatus; +} + +/** + * Convert rules filter options object to KQL query + * + * @param filterOptions desired filters (e.g. filter/sortField/sortOrder) + * + * @returns KQL string + */ +export function convertRulesFilterToKQL({ + filter: searchTerm, + showCustomRules, + showElasticRules, + enabled, + tags, + excludeRuleTypes = [], + ruleExecutionStatus, +}: Partial<RulesFilterOptions>): string { + const kql: string[] = []; + + if (searchTerm?.length) { + kql.push(`(${convertRuleSearchTermToKQL(searchTerm)})`); + } + + if (showCustomRules && showElasticRules) { + // if both showCustomRules && showElasticRules selected we omit filter, as it includes all existing rules + } else if (showElasticRules) { + kql.push(KQL_FILTER_IMMUTABLE_RULES); + } else if (showCustomRules) { + kql.push(KQL_FILTER_MUTABLE_RULES); + } + + if (enabled !== undefined) { + kql.push(enabled ? KQL_FILTER_ENABLED_RULES : KQL_FILTER_DISABLED_RULES); + } + + if (tags?.length) { + kql.push(convertRuleTagsToKQL(tags)); + } + + if (excludeRuleTypes.length) { + kql.push(`NOT ${convertRuleTypesToKQL(excludeRuleTypes)}`); + } + + if (ruleExecutionStatus === RuleExecutionStatus.succeeded) { + kql.push(`${LAST_RUN_OUTCOME_FIELD}: "succeeded"`); + } else if (ruleExecutionStatus === RuleExecutionStatus['partial failure']) { + kql.push(`${LAST_RUN_OUTCOME_FIELD}: "warning"`); + } else if (ruleExecutionStatus === RuleExecutionStatus.failed) { + kql.push(`${LAST_RUN_OUTCOME_FIELD}: "failed"`); + } + + return kql.join(' AND '); +} + +const SEARCHABLE_RULE_ATTRIBUTES = [ + RULE_NAME_FIELD, + RULE_PARAMS_FIELDS.INDEX, + RULE_PARAMS_FIELDS.TACTIC_ID, + RULE_PARAMS_FIELDS.TACTIC_NAME, + RULE_PARAMS_FIELDS.TECHNIQUE_ID, + RULE_PARAMS_FIELDS.TECHNIQUE_NAME, + RULE_PARAMS_FIELDS.SUBTECHNIQUE_ID, + RULE_PARAMS_FIELDS.SUBTECHNIQUE_NAME, +]; + +export function convertRuleSearchTermToKQL( + searchTerm: string, + attributes = SEARCHABLE_RULE_ATTRIBUTES +): string { + return attributes.map((param) => `${param}: ${prepareKQLStringParam(searchTerm)}`).join(' OR '); +} + +export function convertRuleTagsToKQL(tags: string[]): string { + return `${TAGS_FIELD}:(${tags.map(prepareKQLStringParam).join(' AND ')})`; +} + +export function convertRuleTypesToKQL(ruleTypes: Type[]): string { + return `${PARAMS_TYPE_FIELD}: (${ruleTypes.map(prepareKQLStringParam).join(' OR ')})`; +} diff --git a/x-pack/plugins/security_solution/common/utils/kql.test.ts b/x-pack/plugins/security_solution/common/utils/kql.test.ts index 799dc51770a52..665a1f7b5329c 100644 --- a/x-pack/plugins/security_solution/common/utils/kql.test.ts +++ b/x-pack/plugins/security_solution/common/utils/kql.test.ts @@ -5,85 +5,73 @@ * 2.0. */ -import { convertRulesFilterToKQL } from './kql'; - -describe('convertRulesFilterToKQL', () => { - const filterOptions = { - filter: '', - showCustomRules: false, - showElasticRules: false, - tags: [], - }; - - it('returns empty string if filter options are empty', () => { - const kql = convertRulesFilterToKQL(filterOptions); - - expect(kql).toBe(''); - }); - - it('handles presence of "filter" properly', () => { - const kql = convertRulesFilterToKQL({ ...filterOptions, filter: 'foo' }); - - expect(kql).toBe( - '(alert.attributes.name: "foo" OR alert.attributes.params.index: "foo" OR alert.attributes.params.threat.tactic.id: "foo" OR alert.attributes.params.threat.tactic.name: "foo" OR alert.attributes.params.threat.technique.id: "foo" OR alert.attributes.params.threat.technique.name: "foo" OR alert.attributes.params.threat.technique.subtechnique.id: "foo" OR alert.attributes.params.threat.technique.subtechnique.name: "foo")' - ); +import { escapeKQLStringParam, prepareKQLParam, prepareKQLStringParam } from './kql'; + +const testCases = [ + ['does NOT remove white spaces quotes', ' netcat', ' netcat'], + ['escapes quotes', 'I said, "Hello."', 'I said, \\"Hello.\\"'], + [ + 'should escape special characters', + `This \\ has (a lot of) <special> characters, don't you *think*? "Yes."`, + `This \\ has (a lot of) <special> characters, don't you *think*? \\"Yes.\\"`, + ], + ['does NOT escape keywords', 'foo and bar or baz not qux', 'foo and bar or baz not qux'], + [ + 'does NOT escape keywords next to each other', + 'foo and bar or not baz', + 'foo and bar or not baz', + ], + [ + 'does NOT escape keywords without surrounding spaces', + 'And this has keywords, or does it not?', + 'And this has keywords, or does it not?', + ], + [ + 'does NOT escape uppercase keywords', + 'And this has keywords, or does it not?', + 'And this has keywords, or does it not?', + ], + ['does NOT escape uppercase keywords', 'foo AND bar', 'foo AND bar'], + [ + 'escapes special characters and NOT keywords', + 'Hello, "world", and <nice> to meet you!', + 'Hello, \\"world\\", and <nice> to meet you!', + ], + [ + 'escapes newlines and tabs', + 'This\nhas\tnewlines\r\nwith\ttabs', + 'This\\nhas\\tnewlines\\r\\nwith\\ttabs', + ], +]; + +describe('prepareKQLParam', () => { + it.each(testCases)('%s', (_, input, expected) => { + expect(prepareKQLParam(input)).toBe(`"${expected}"`); }); - it('escapes "filter" value properly', () => { - const kql = convertRulesFilterToKQL({ ...filterOptions, filter: '" OR (foo: bar)' }); + it('stringifies numbers without enclosing by quotes', () => { + const input = 10; + const expected = '10'; - expect(kql).toBe( - '(alert.attributes.name: "\\" \\OR \\(foo\\: bar\\)" OR alert.attributes.params.index: "\\" \\OR \\(foo\\: bar\\)" OR alert.attributes.params.threat.tactic.id: "\\" \\OR \\(foo\\: bar\\)" OR alert.attributes.params.threat.tactic.name: "\\" \\OR \\(foo\\: bar\\)" OR alert.attributes.params.threat.technique.id: "\\" \\OR \\(foo\\: bar\\)" OR alert.attributes.params.threat.technique.name: "\\" \\OR \\(foo\\: bar\\)" OR alert.attributes.params.threat.technique.subtechnique.id: "\\" \\OR \\(foo\\: bar\\)" OR alert.attributes.params.threat.technique.subtechnique.name: "\\" \\OR \\(foo\\: bar\\)")' - ); + expect(prepareKQLParam(input)).toBe(expected); }); - it('handles presence of "showCustomRules" properly', () => { - const kql = convertRulesFilterToKQL({ ...filterOptions, showCustomRules: true }); + it('stringifies booleans without enclosing by quotes', () => { + const input = true; + const expected = 'true'; - expect(kql).toBe(`alert.attributes.params.immutable: false`); + expect(prepareKQLParam(input)).toBe(expected); }); +}); - it('handles presence of "showElasticRules" properly', () => { - const kql = convertRulesFilterToKQL({ ...filterOptions, showElasticRules: true }); - - expect(kql).toBe(`alert.attributes.params.immutable: true`); - }); - - it('handles presence of "showElasticRules" and "showCustomRules" at the same time properly', () => { - const kql = convertRulesFilterToKQL({ - ...filterOptions, - showElasticRules: true, - showCustomRules: true, - }); - - expect(kql).toBe(''); - }); - - it('handles presence of "tags" properly', () => { - const kql = convertRulesFilterToKQL({ ...filterOptions, tags: ['tag1', 'tag2'] }); - - expect(kql).toBe('alert.attributes.tags:("tag1" AND "tag2")'); - }); - - it('handles combination of different properties properly', () => { - const kql = convertRulesFilterToKQL({ - ...filterOptions, - filter: 'foo', - showElasticRules: true, - tags: ['tag1', 'tag2'], - }); - - expect(kql).toBe( - `(alert.attributes.name: "foo" OR alert.attributes.params.index: "foo" OR alert.attributes.params.threat.tactic.id: "foo" OR alert.attributes.params.threat.tactic.name: "foo" OR alert.attributes.params.threat.technique.id: "foo" OR alert.attributes.params.threat.technique.name: "foo" OR alert.attributes.params.threat.technique.subtechnique.id: "foo" OR alert.attributes.params.threat.technique.subtechnique.name: "foo") AND alert.attributes.params.immutable: true AND alert.attributes.tags:(\"tag1\" AND \"tag2\")` - ); +describe('prepareKQLStringParam', () => { + it.each(testCases)('%s', (_, input, expected) => { + expect(prepareKQLStringParam(input)).toBe(`"${expected}"`); }); +}); - it('handles presence of "excludeRuleTypes" properly', () => { - const kql = convertRulesFilterToKQL({ - ...filterOptions, - excludeRuleTypes: ['machine_learning', 'saved_query'], - }); - - expect(kql).toBe('NOT alert.attributes.params.type: ("machine_learning" OR "saved_query")'); +describe('escapeKQLStringParam', () => { + it.each(testCases)('%s', (_, input, expected) => { + expect(escapeKQLStringParam(input)).toBe(expected); }); }); diff --git a/x-pack/plugins/security_solution/common/utils/kql.ts b/x-pack/plugins/security_solution/common/utils/kql.ts index cf55d16e91c9d..7ab8a47ef5c22 100644 --- a/x-pack/plugins/security_solution/common/utils/kql.ts +++ b/x-pack/plugins/security_solution/common/utils/kql.ts @@ -5,111 +5,51 @@ * 2.0. */ -import { escapeKuery } from '@kbn/es-query'; -import type { Type } from '@kbn/securitysolution-io-ts-alerting-types'; -import { RuleExecutionStatus } from '../api/detection_engine'; -import { - ENABLED_FIELD, - LAST_RUN_OUTCOME_FIELD, - PARAMS_IMMUTABLE_FIELD, - PARAMS_TYPE_FIELD, - RULE_NAME_FIELD, - RULE_PARAMS_FIELDS, - TAGS_FIELD, -} from '../rule_fields'; +import { flow, isString } from 'lodash/fp'; -export const KQL_FILTER_IMMUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: true`; -export const KQL_FILTER_MUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: false`; -export const KQL_FILTER_ENABLED_RULES = `${ENABLED_FIELD}: true`; -export const KQL_FILTER_DISABLED_RULES = `${ENABLED_FIELD}: false`; - -interface RulesFilterOptions { - filter: string; - showCustomRules: boolean; - showElasticRules: boolean; - enabled: boolean; - tags: string[]; - excludeRuleTypes: Type[]; - ruleExecutionStatus: RuleExecutionStatus; +/** + * Preparing an arbitrary KQL query param by quoting and escaping string values, stringifying non string values. + * + * See https://www.elastic.co/guide/en/kibana/current/kuery-query.html + * + * @param value + * @returns + */ +export function prepareKQLParam(value: string | number | boolean): string { + return isString(value) ? prepareKQLStringParam(value) : `${value}`; } /** - * Convert rules filter options object to KQL query + * Prepares a string KQL query param by wrapping the value in quotes and making sure + * the quotes, tabs and new line symbols inside are escaped. * - * @param filterOptions desired filters (e.g. filter/sortField/sortOrder) + * See https://www.elastic.co/guide/en/kibana/current/kuery-query.html * - * @returns KQL string + * @param value a string param value intended to be passed to KQL + * @returns a quoted and escaped string param value */ -export function convertRulesFilterToKQL({ - filter: searchTerm, - showCustomRules, - showElasticRules, - enabled, - tags, - excludeRuleTypes = [], - ruleExecutionStatus, -}: Partial<RulesFilterOptions>): string { - const kql: string[] = []; - - if (searchTerm?.length) { - kql.push(`(${convertRuleSearchTermToKQL(searchTerm)})`); - } - - if (showCustomRules && showElasticRules) { - // if both showCustomRules && showElasticRules selected we omit filter, as it includes all existing rules - } else if (showElasticRules) { - kql.push(KQL_FILTER_IMMUTABLE_RULES); - } else if (showCustomRules) { - kql.push(KQL_FILTER_MUTABLE_RULES); - } - - if (enabled !== undefined) { - kql.push(enabled ? KQL_FILTER_ENABLED_RULES : KQL_FILTER_DISABLED_RULES); - } - - if (tags?.length) { - kql.push(convertRuleTagsToKQL(tags)); - } - - if (excludeRuleTypes.length) { - kql.push(`NOT ${convertRuleTypesToKQL(excludeRuleTypes)}`); - } - - if (ruleExecutionStatus === RuleExecutionStatus.succeeded) { - kql.push(`${LAST_RUN_OUTCOME_FIELD}: "succeeded"`); - } else if (ruleExecutionStatus === RuleExecutionStatus['partial failure']) { - kql.push(`${LAST_RUN_OUTCOME_FIELD}: "warning"`); - } else if (ruleExecutionStatus === RuleExecutionStatus.failed) { - kql.push(`${LAST_RUN_OUTCOME_FIELD}: "failed"`); - } - - return kql.join(' AND '); +export function prepareKQLStringParam(value: string): string { + return `"${escapeKQLStringParam(value)}"`; } -const SEARCHABLE_RULE_ATTRIBUTES = [ - RULE_NAME_FIELD, - RULE_PARAMS_FIELDS.INDEX, - RULE_PARAMS_FIELDS.TACTIC_ID, - RULE_PARAMS_FIELDS.TACTIC_NAME, - RULE_PARAMS_FIELDS.TECHNIQUE_ID, - RULE_PARAMS_FIELDS.TECHNIQUE_NAME, - RULE_PARAMS_FIELDS.SUBTECHNIQUE_ID, - RULE_PARAMS_FIELDS.SUBTECHNIQUE_NAME, -]; - -export function convertRuleSearchTermToKQL( - searchTerm: string, - attributes = SEARCHABLE_RULE_ATTRIBUTES -): string { - return attributes.map((param) => `${param}: "${escapeKuery(searchTerm)}"`).join(' OR '); +/** + * Escapes string param intended to be passed to KQL. As official docs + * [here](https://www.elastic.co/guide/en/kibana/current/kuery-query.html) say + * `Certain characters must be escaped by a backslash (unless surrounded by quotes).` and + * `You must escape following characters: \():<>"*`. + * + * This function assumes the value is surrounded by quotes so it escapes quotes, tabs and new line symbols. + * + * @param param a string param value intended to be passed to KQL + * @returns an escaped string param value + */ +export function escapeKQLStringParam(value = ''): string { + return escapeStringValue(value); } -export function convertRuleTagsToKQL(tags: string[]): string { - return `${TAGS_FIELD}:(${tags.map((tag) => `"${escapeKuery(tag)}"`).join(' AND ')})`; -} +const escapeQuotes = (val: string) => val.replace(/["]/g, '\\$&'); // $& means the whole matched string -export function convertRuleTypesToKQL(ruleTypes: Type[]): string { - return `${PARAMS_TYPE_FIELD}: (${ruleTypes - .map((ruleType) => `"${escapeKuery(ruleType)}"`) - .join(' OR ')})`; -} +const escapeTabs = (val: string) => + val.replace(/\t/g, '\\t').replace(/\r/g, '\\r').replace(/\n/g, '\\n'); + +const escapeStringValue = flow(escapeQuotes, escapeTabs); diff --git a/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts b/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts index b6958b681f794..1a3cfe0eb9f08 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts @@ -6,65 +6,9 @@ */ import expect from '@kbn/expect'; -import { convertToBuildEsQuery, escapeKuery } from '.'; +import { convertToBuildEsQuery } from '.'; import { mockIndexPattern } from '../../mock'; -describe('Kuery escape', () => { - it('should not remove white spaces quotes', () => { - const value = ' netcat'; - const expected = ' netcat'; - expect(escapeKuery(value)).to.be(expected); - }); - - it('should escape quotes', () => { - const value = 'I said, "Hello."'; - const expected = 'I said, \\"Hello.\\"'; - expect(escapeKuery(value)).to.be(expected); - }); - - it('should escape special characters', () => { - const value = `This \\ has (a lot of) <special> characters, don't you *think*? "Yes."`; - const expected = `This \\ has (a lot of) <special> characters, don't you *think*? \\"Yes.\\"`; - expect(escapeKuery(value)).to.be(expected); - }); - - it('should NOT escape keywords', () => { - const value = 'foo and bar or baz not qux'; - const expected = 'foo and bar or baz not qux'; - expect(escapeKuery(value)).to.be(expected); - }); - - it('should NOT escape keywords next to each other', () => { - const value = 'foo and bar or not baz'; - const expected = 'foo and bar or not baz'; - expect(escapeKuery(value)).to.be(expected); - }); - - it('should not escape keywords without surrounding spaces', () => { - const value = 'And this has keywords, or does it not?'; - const expected = 'And this has keywords, or does it not?'; - expect(escapeKuery(value)).to.be(expected); - }); - - it('should NOT escape uppercase keywords', () => { - const value = 'foo AND bar'; - const expected = 'foo AND bar'; - expect(escapeKuery(value)).to.be(expected); - }); - - it('should escape special characters and NOT keywords', () => { - const value = 'Hello, "world", and <nice> to meet you!'; - const expected = 'Hello, \\"world\\", and <nice> to meet you!'; - expect(escapeKuery(value)).to.be(expected); - }); - - it('should escape newlines and tabs', () => { - const value = 'This\nhas\tnewlines\r\nwith\ttabs'; - const expected = 'This\\nhas\\tnewlines\\r\\nwith\\ttabs'; - expect(escapeKuery(value)).to.be(expected); - }); -}); - describe('convertToBuildEsQuery', () => { /** * All the fields in this query, except for `@timestamp`, diff --git a/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts b/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts index 4960b76b361cf..3fefc26076a12 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts @@ -12,8 +12,9 @@ import { FilterStateStore, buildEsQuery, } from '@kbn/es-query'; -import { flow, get, isEmpty, isString } from 'lodash/fp'; +import { get, isEmpty } from 'lodash/fp'; import memoizeOne from 'memoize-one'; +import { prepareKQLParam } from '../../../../common/utils/kql'; import type { BrowserFields } from '../../../../common/search_strategy'; import type { DataProvider, DataProvidersAnd } from '../../../../common/types'; import { DataProviderType } from '../../../../common/api/timeline'; @@ -35,33 +36,6 @@ export interface CombineQueries { kqlMode: string; } -export const escapeQueryValue = ( - val: PrimitiveOrArrayOfPrimitives = '' -): PrimitiveOrArrayOfPrimitives => { - if (isString(val)) { - if (isEmpty(val)) { - return '""'; - } - return `"${escapeKuery(val)}"`; - } - - return val; -}; - -const escapeWhitespace = (val: string) => - val.replace(/\t/g, '\\t').replace(/\r/g, '\\r').replace(/\n/g, '\\n'); - -// See the SpecialCharacter rule in kuery.peg -const escapeSpecialCharacters = (val: string) => val.replace(/["]/g, '\\$&'); // $& means the whole matched string - -// See the Keyword rule in kuery.peg -// I do not think that we need that anymore since we are doing a full match_phrase all the time now => return `"${escapeKuery(val)}"`; -// const escapeAndOr = (val: string) => val.replace(/(\s+)(and|or)(\s+)/gi, '$1\\$2$3'); - -// const escapeNot = (val: string) => val.replace(/not(\s+)/gi, '\\$&'); - -export const escapeKuery = flow(escapeSpecialCharacters, escapeWhitespace); - export const convertKueryToElasticSearchQuery = ( kueryExpression: string, indexPattern?: DataViewBase @@ -161,9 +135,9 @@ const buildQueryMatch = ( : checkIfFieldTypeIsDate(dataProvider.queryMatch.field, browserFields) ? convertDateFieldToQuery(dataProvider.queryMatch.field, dataProvider.queryMatch.value) : `${dataProvider.queryMatch.field} : ${ - isNumber(dataProvider.queryMatch.value) + Array.isArray(dataProvider.queryMatch.value) ? dataProvider.queryMatch.value - : escapeQueryValue(dataProvider.queryMatch.value) + : prepareKQLParam(dataProvider.queryMatch.value) }` : checkIfFieldTypeIsNested(dataProvider.queryMatch.field, browserFields) ? convertNestedFieldToExistQuery(dataProvider.queryMatch.field, browserFields) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts index cf584bb87c207..9e09a1754a04d 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts @@ -194,7 +194,7 @@ describe('Detections Rules API', () => { method: 'GET', query: { filter: - '(alert.attributes.name: "\\" \\OR \\(foo\\:bar\\)" OR alert.attributes.params.index: "\\" \\OR \\(foo\\:bar\\)" OR alert.attributes.params.threat.tactic.id: "\\" \\OR \\(foo\\:bar\\)" OR alert.attributes.params.threat.tactic.name: "\\" \\OR \\(foo\\:bar\\)" OR alert.attributes.params.threat.technique.id: "\\" \\OR \\(foo\\:bar\\)" OR alert.attributes.params.threat.technique.name: "\\" \\OR \\(foo\\:bar\\)" OR alert.attributes.params.threat.technique.subtechnique.id: "\\" \\OR \\(foo\\:bar\\)" OR alert.attributes.params.threat.technique.subtechnique.name: "\\" \\OR \\(foo\\:bar\\)")', + '(alert.attributes.name: "\\" OR (foo:bar)" OR alert.attributes.params.index: "\\" OR (foo:bar)" OR alert.attributes.params.threat.tactic.id: "\\" OR (foo:bar)" OR alert.attributes.params.threat.tactic.name: "\\" OR (foo:bar)" OR alert.attributes.params.threat.technique.id: "\\" OR (foo:bar)" OR alert.attributes.params.threat.technique.name: "\\" OR (foo:bar)" OR alert.attributes.params.threat.technique.subtechnique.id: "\\" OR (foo:bar)" OR alert.attributes.params.threat.technique.subtechnique.name: "\\" OR (foo:bar)")', page: 1, per_page: 20, sort_field: 'enabled', diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts index 9a0345faf4c0f..c90b48860bbf6 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts @@ -16,7 +16,7 @@ import type { ActionResult } from '@kbn/actions-plugin/server'; import type { BulkInstallPackagesResponse } from '@kbn/fleet-plugin/common'; import { epmRouteService } from '@kbn/fleet-plugin/common'; import type { InstallPackageResponse } from '@kbn/fleet-plugin/common/types'; -import { convertRulesFilterToKQL } from '../../../../common/utils/kql'; +import { convertRulesFilterToKQL } from '../../../../common/detection_engine/rule_management/rule_filtering'; import type { UpgradeSpecificRulesRequest, PerformRuleUpgradeResponseBody, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/use_bulk_actions.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/use_bulk_actions.tsx index 24ae37bf8e6d9..a7c5e35ff3341 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/use_bulk_actions.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/use_bulk_actions.tsx @@ -12,7 +12,7 @@ import type { Toast } from '@kbn/core/public'; import { toMountPoint } from '@kbn/kibana-react-plugin/public'; import { euiThemeVars } from '@kbn/ui-theme'; import React, { useCallback } from 'react'; -import { convertRulesFilterToKQL } from '../../../../../../common/utils/kql'; +import { convertRulesFilterToKQL } from '../../../../../../common/detection_engine/rule_management/rule_filtering'; import { DuplicateOptions } from '../../../../../../common/detection_engine/rule_management/constants'; import type { BulkActionEditPayload } from '../../../../../../common/api/detection_engine/rule_management'; import { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/utils/prepare_search_params.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/utils/prepare_search_params.test.ts index cc7524234feef..a538940cfa7a8 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/utils/prepare_search_params.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/utils/prepare_search_params.test.ts @@ -8,12 +8,12 @@ import type { DryRunResult } from '../types'; import type { FilterOptions } from '../../../../../rule_management/logic/types'; +import { convertRulesFilterToKQL } from '../../../../../../../common/detection_engine/rule_management/rule_filtering'; import { BulkActionsDryRunErrCode } from '../../../../../../../common/constants'; import { prepareSearchParams } from './prepare_search_params'; -import { convertRulesFilterToKQL } from '../../../../../../../common/utils/kql'; -jest.mock('../../../../../../../common/utils/kql', () => ({ +jest.mock('../../../../../../../common/detection_engine/rule_management/rule_filtering', () => ({ convertRulesFilterToKQL: jest.fn().mockReturnValue('str'), })); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/utils/prepare_search_params.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/utils/prepare_search_params.ts index c868a0b34270b..b8f84fc2bb544 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/utils/prepare_search_params.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/utils/prepare_search_params.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { convertRulesFilterToKQL } from '../../../../../../../common/utils/kql'; +import { convertRulesFilterToKQL } from '../../../../../../../common/detection_engine/rule_management/rule_filtering'; import type { QueryOrIds } from '../../../../../rule_management/logic'; import type { DryRunResult } from '../types'; import type { FilterOptions } from '../../../../../rule_management/logic/types'; diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/helpers.test.ts b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/helpers.test.ts index 77cb6f5f54a76..2707d32788b18 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/helpers.test.ts @@ -5,39 +5,10 @@ * 2.0. */ -import { getHostDetailsEventsKqlQueryExpression, getHostDetailsPageFilters } from './helpers'; +import { getHostDetailsPageFilters } from './helpers'; import type { Filter } from '@kbn/es-query'; describe('hosts page helpers', () => { - describe('getHostDetailsEventsKqlQueryExpression', () => { - const filterQueryExpression = 'user.name: "root"'; - const hostName = 'foo'; - - it('combines the filterQueryExpression and hostname when both are NOT empty', () => { - expect(getHostDetailsEventsKqlQueryExpression({ filterQueryExpression, hostName })).toEqual( - 'user.name: "root" and host.name: "foo"' - ); - }); - - it('returns just the filterQueryExpression when it is NOT empty, but hostname is empty', () => { - expect( - getHostDetailsEventsKqlQueryExpression({ filterQueryExpression, hostName: '' }) - ).toEqual('user.name: "root"'); - }); - - it('returns just the hostname when filterQueryExpression is empty, but hostname is NOT empty', () => { - expect( - getHostDetailsEventsKqlQueryExpression({ filterQueryExpression: '', hostName }) - ).toEqual('host.name: "foo"'); - }); - - it('returns an empty string when both the filterQueryExpression and hostname are empty', () => { - expect( - getHostDetailsEventsKqlQueryExpression({ filterQueryExpression: '', hostName: '' }) - ).toEqual(''); - }); - }); - describe('getHostDetailsPageFilters', () => { it('correctly constructs pageFilters for the given hostName', () => { const expected: Filter[] = [ diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/helpers.ts b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/helpers.ts index feea9db7ef496..e219fdda541da 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/helpers.ts +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/helpers.ts @@ -6,24 +6,6 @@ */ import type { Filter } from '@kbn/es-query'; -import { escapeQueryValue } from '../../../../common/lib/kuery'; - -/** Returns the kqlQueryExpression for the `Events` widget on the `Host Details` page */ -export const getHostDetailsEventsKqlQueryExpression = ({ - filterQueryExpression, - hostName, -}: { - filterQueryExpression: string; - hostName: string; -}): string => { - if (filterQueryExpression.length) { - return `${filterQueryExpression}${ - hostName.length ? ` and host.name: ${escapeQueryValue(hostName)}` : '' - }`; - } else { - return hostName.length ? `host.name: ${escapeQueryValue(hostName)}` : ''; - } -}; export const getHostDetailsPageFilters = (hostName: string): Filter[] => [ { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx index 6ea097e5a3144..72be8b6110ae4 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { isEmpty } from 'lodash/fp'; +import { isEmpty, isNumber } from 'lodash/fp'; import { elementOrChildrenHasFocus, @@ -15,11 +15,10 @@ import { stopPropagationAndPreventDefault, } from '@kbn/timelines-plugin/public'; +import { prepareKQLParam, prepareKQLStringParam } from '../../../../common/utils/kql'; import { assertUnreachable } from '../../../../common/utility_types'; import type { BrowserFields } from '../../../common/containers/source'; import { - escapeQueryValue, - isNumber, convertDateFieldToQuery, checkIfFieldTypeIsDate, convertNestedFieldToQuery, @@ -263,7 +262,7 @@ export const buildIsQueryMatch = ({ } else if (checkIfFieldTypeIsDate(field, browserFields)) { return convertDateFieldToQuery(field, value); } else { - return `${field} : ${isNumber(value) ? value : escapeQueryValue(value)}`; + return `${field} : ${prepareKQLParam(value)}`; } }; @@ -291,7 +290,7 @@ export const buildIsOneOfQueryMatch = ({ const trimmedField = field.trim(); if (value.length) { return `${trimmedField} : (${value - .map((item) => (isNumber(item) ? Number(item) : `${escapeQueryValue(String(item).trim())}`)) + .map((item) => (isNumber(item) ? item : prepareKQLStringParam(String(item).trim()))) .join(' OR ')})`; } return `${trimmedField} : ''`; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/handle_coverage_overview_request.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/handle_coverage_overview_request.ts index 67900c2296355..563d33dd64f4d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/handle_coverage_overview_request.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/handle_coverage_overview_request.ts @@ -7,7 +7,7 @@ import type { SanitizedRule } from '@kbn/alerting-plugin/common'; import type { RulesClient } from '@kbn/alerting-plugin/server'; -import { convertRulesFilterToKQL } from '../../../../../../../common/utils/kql'; +import { convertRulesFilterToKQL } from '../../../../../../../common/detection_engine/rule_management/rule_filtering'; import type { CoverageOverviewRequestBody, CoverageOverviewResponse, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/get_existing_prepackaged_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/get_existing_prepackaged_rules.ts index ee5d6082a9fdb..24b2954547e40 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/get_existing_prepackaged_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/get_existing_prepackaged_rules.ts @@ -6,10 +6,11 @@ */ import type { RulesClient } from '@kbn/alerting-plugin/server'; + import { KQL_FILTER_IMMUTABLE_RULES, KQL_FILTER_MUTABLE_RULES, -} from '../../../../../../common/utils/kql'; +} from '../../../../../../common/detection_engine/rule_management/rule_filtering'; import { withSecuritySpan } from '../../../../../utils/with_security_span'; import { findRules } from './find_rules'; import type { RuleAlertType } from '../../../rule_schema'; diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_filtering.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_filtering.cy.ts index 61cd1a33499ad..eaa67b859b6c0 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_filtering.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_filtering.cy.ts @@ -13,6 +13,12 @@ import { expectNumberOfRulesShownOnPage, } from '../../../../tasks/rule_filters'; +import { + expectManagementTableRules, + filterByTags, + unselectTags, +} from '../../../../tasks/alerts_detection_rules'; + import { createRule, waitForRulesToFinishExecution } from '../../../../tasks/api_calls/rules'; import { deleteIndex, @@ -103,4 +109,45 @@ describe('Rules table: filtering', { tags: ['@ess', '@serverless'] }, () => { expectRulesWithExecutionStatus(1, 'Failed'); }); }); + + describe('Tags filter', () => { + beforeEach(() => { + createRule( + getNewRule({ + name: 'Rule 1', + tags: [], + }) + ); + + createRule( + getNewRule({ + name: 'Rule 2', + tags: ['simpleTag'], + }) + ); + + createRule( + getNewRule({ + name: 'Rule 3', + tags: ['category:tag'], + }) + ); + }); + + it('filter by different tags', () => { + visitSecurityDetectionRulesPage(); + + expectManagementTableRules(['Rule 1', 'Rule 2', 'Rule 3']); + + filterByTags(['simpleTag']); + + expectManagementTableRules(['Rule 2']); + + unselectTags(); + + filterByTags(['category:tag']); + + expectManagementTableRules(['Rule 3']); + }); + }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts b/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts index 3170084e39778..5f66f5513ed17 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts @@ -147,6 +147,20 @@ export const filterByTags = (tags: string[]) => { for (const tag of tags) { cy.get(RULES_TAGS_FILTER_POPOVER).contains(tag).click(); } + + // close the popover + cy.get(RULES_TAGS_FILTER_BTN).click(); +}; + +export const unselectTags = () => { + cy.get(RULES_TAGS_FILTER_BTN).click(); + + cy.get(RULES_TAGS_FILTER_POPOVER) + .find('[aria-checked="true"]') + .each((el) => cy.wrap(el).click()); + + // close the popover + cy.get(RULES_TAGS_FILTER_BTN).click(); }; export const waitForRuleExecution = (name: string) => { From 142e625d6e384736ed387e6279b1f4b1580b1f92 Mon Sep 17 00:00:00 2001 From: Konrad Szwarc <konrad.szwarc@elastic.co> Date: Mon, 28 Aug 2023 11:36:24 +0200 Subject: [PATCH 02/49] [Defend Workflows] Artifact rollout (#162719) This is the first step in a series of tasks introducing Artifact rollout UI. We are eager to merge this quickly to unblock other teams from e2e testing the feature. These changes introduce new tab "Protection Updates" under endpoint policy detail. Access privileges are based on already present `canWritePolicyManagement` setting that is being used on `Policy settings` tab. There are 3 states of the tab: 1. Edit when `canWritePolicyManagement` endpoint privilege is set to true. 2. View when `canWritePolicyManagement` is set to false 3. Hidden when `protectionUpdatesEnabled` feature flag is set to false. This also excludes `/{policy.id}/protectionUpdates` route. Successful user journey results in the addition of `manifest_version` key in the policy with default of `latest`: ``` policy: meta: ... linux: ... global_manifest_version: '2023-08-24' windows:.. ``` **Stored date format is `YYYY-MM-DD`.** Edit flow and behaviour: https://github.com/elastic/kibana/assets/29123534/02c82768-0201-471c-8258-f01831106ad1 Read only priveleges: ![Screenshot 2023-08-24 at 10 58 24](https://github.com/elastic/kibana/assets/29123534/bda4b096-48b4-4faf-80bf-9dbf36ab4aca) Feature Flag off: ![Screenshot 2023-08-24 at 11 41 06](https://github.com/elastic/kibana/assets/29123534/d873cb8a-0f93-42fd-84d8-fef98a602a25) --- .../group2/check_registered_types.test.ts | 2 +- .../fleet/server/saved_objects/index.ts | 16 + .../security_solution/to_v8_11_0.test.ts | 140 +++++++ .../security_solution/to_v8_11_0.ts | 59 +++ .../common/endpoint/models/policy_config.ts | 1 + .../models/policy_config_helpers.test.ts | 1 + .../endpoint/models/policy_config_helpers.ts | 108 +++--- .../common/endpoint/types/index.ts | 1 + .../common/experimental_features.ts | 5 + .../public/app/translations.ts | 7 + .../public/management/common/breadcrumbs.ts | 2 + .../public/management/common/constants.ts | 1 + .../public/management/common/routing.ts | 13 + .../cypress/e2e/endpoint/policy_details.cy.ts | 169 +++++++++ .../cypress/tasks/endpoint_policy.ts | 33 ++ .../public/management/cypress/tasks/login.ts | 7 +- .../public/management/pages/policy/index.tsx | 7 + .../policy/store/policy_details/index.test.ts | 1 + .../selectors/policy_common_selectors.ts | 13 + .../selectors/policy_settings_selectors.ts | 6 +- .../protection_updates_layout.tsx | 344 ++++++++++++++++++ .../pages/policy/view/tabs/policy_tabs.tsx | 43 ++- .../public/management/types.ts | 1 + .../endpoint_security_policy_manager.ts | 16 + 24 files changed, 929 insertions(+), 67 deletions(-) create mode 100644 x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_11_0.test.ts create mode 100644 x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_11_0.ts create mode 100644 x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/policy_details.cy.ts create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts index f55c023f6eb74..171d45a2c7537 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts @@ -106,7 +106,7 @@ describe('checking migration metadata changes on all registered SO types', () => "ingest-agent-policies": "f11cc19275f4c3e4ee7c5cd6423b6706b21b989d", "ingest-download-sources": "279a68147e62e4d8858c09ad1cf03bd5551ce58d", "ingest-outputs": "b4e636b13a5d0f89f0400fb67811d4cca4736eb0", - "ingest-package-policies": "55816507db0134b8efbe0509e311a91ce7e1c6cc", + "ingest-package-policies": "af9e8d523a6f3ae5b8c9adcfba391ff405dfa374", "ingest_manager_settings": "64955ef1b7a9ffa894d4bb9cf863b5602bfa6885", "inventory-view": "b8683c8e352a286b4aca1ab21003115a4800af83", "kql-telemetry": "93c1d16c1a0dfca9c8842062cf5ef8f62ae401ad", diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index eea06fab2b08d..b7cf55510285f 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -25,6 +25,11 @@ import { UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, } from '../constants'; +import { + migratePackagePolicyEvictionsFromV8110, + migratePackagePolicyToV8110, +} from './migrations/security_solution/to_v8_11_0'; + import { migrateOutputEvictionsFromV8100, migrateOutputToV8100 } from './migrations/to_v8_10_0'; import { migrateSyntheticsPackagePolicyToV8100 } from './migrations/synthetics/to_v8_10_0'; @@ -319,6 +324,17 @@ const getSavedObjectTypes = (): { [key: string]: SavedObjectsType } => ({ forwardCompatibility: migratePackagePolicyEvictionsFromV8100, }, }, + '2': { + changes: [ + { + type: 'data_backfill', + backfillFn: migratePackagePolicyToV8110, + }, + ], + schemas: { + forwardCompatibility: migratePackagePolicyEvictionsFromV8110, + }, + }, }, migrations: { '7.10.0': migratePackagePolicyToV7100, diff --git a/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_11_0.test.ts b/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_11_0.test.ts new file mode 100644 index 0000000000000..bf8a9a0dfafd3 --- /dev/null +++ b/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_11_0.test.ts @@ -0,0 +1,140 @@ +/* + * 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 { SavedObjectUnsanitizedDoc } from '@kbn/core/server'; + +import type { SavedObjectModelTransformationContext } from '@kbn/core-saved-objects-server'; + +import type { PackagePolicy } from '../../../../common'; + +import { migratePackagePolicyToV8110 as migration } from './to_v8_11_0'; +import { migratePackagePolicyEvictionsFromV8110 as eviction } from './to_v8_11_0'; + +describe('8.10.0 Endpoint Package Policy migration', () => { + const policyDoc = ({ manifestVersion }: { manifestVersion: string | undefined }) => { + return { + id: 'mock-saved-object-id', + attributes: { + name: 'Some Policy Name', + package: { + name: 'endpoint', + title: '', + version: '', + }, + id: 'endpoint', + policy_id: '', + enabled: true, + namespace: '', + revision: 0, + updated_at: '', + updated_by: '', + created_at: '', + created_by: '', + inputs: [ + { + type: 'endpoint', + enabled: true, + streams: [], + config: { + policy: { + value: { + global_manifest_version: manifestVersion, + }, + }, + }, + }, + ], + }, + type: ' nested', + }; + }; + + it('adds manifest version field to policy, set to latest', () => { + const initialDoc = policyDoc({ manifestVersion: undefined }); + + const migratedDoc = policyDoc({ manifestVersion: 'latest' }); + + expect(migration(initialDoc, {} as SavedObjectModelTransformationContext)).toEqual({ + attributes: { + inputs: migratedDoc.attributes.inputs, + }, + }); + }); + + it('removes manifest version field from policy', () => { + const initialDoc = policyDoc({ manifestVersion: 'latest' }); + + const migratedDoc = policyDoc({ manifestVersion: undefined }); + + expect(eviction(initialDoc.attributes)).toEqual(migratedDoc.attributes); + }); + + it('does not modify non-endpoint package policies', () => { + const doc: SavedObjectUnsanitizedDoc<PackagePolicy> = { + id: 'mock-saved-object-id', + attributes: { + name: 'Some Policy Name', + package: { + name: 'notEndpoint', + title: '', + version: '', + }, + id: 'notEndpoint', + policy_id: '', + enabled: true, + namespace: '', + revision: 0, + updated_at: '', + updated_by: '', + created_at: '', + created_by: '', + inputs: [ + { + type: 'notEndpoint', + enabled: true, + streams: [], + config: {}, + }, + ], + }, + type: ' nested', + }; + + expect( + migration( + doc, + {} as SavedObjectModelTransformationContext + ) as SavedObjectUnsanitizedDoc<PackagePolicy> + ).toEqual({ + attributes: { + name: 'Some Policy Name', + package: { + name: 'notEndpoint', + title: '', + version: '', + }, + id: 'notEndpoint', + policy_id: '', + enabled: true, + namespace: '', + revision: 0, + updated_at: '', + updated_by: '', + created_at: '', + created_by: '', + inputs: [ + { + type: 'notEndpoint', + enabled: true, + streams: [], + config: {}, + }, + ], + }, + }); + }); +}); diff --git a/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_11_0.ts b/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_11_0.ts new file mode 100644 index 0000000000000..5f8539dbe80bc --- /dev/null +++ b/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_11_0.ts @@ -0,0 +1,59 @@ +/* + * 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 { SavedObjectUnsanitizedDoc } from '@kbn/core/server'; + +import type { SavedObjectModelDataBackfillFn } from '@kbn/core-saved-objects-server'; + +import { omit } from 'lodash'; + +import type { SavedObjectModelVersionForwardCompatibilityFn } from '@kbn/core-saved-objects-server'; + +import type { PackagePolicy } from '../../../../common'; + +export const migratePackagePolicyToV8110: SavedObjectModelDataBackfillFn< + PackagePolicy, + PackagePolicy +> = (packagePolicyDoc) => { + if (packagePolicyDoc.attributes.package?.name !== 'endpoint') { + return { attributes: packagePolicyDoc.attributes }; + } + + const updatedPackagePolicyDoc: SavedObjectUnsanitizedDoc<PackagePolicy> = packagePolicyDoc; + + const input = updatedPackagePolicyDoc.attributes.inputs[0]; + + if (input && input.config) { + const policy = input.config.policy.value; + + policy.global_manifest_version = 'latest'; + } + + return { + attributes: { + inputs: updatedPackagePolicyDoc.attributes.inputs, + }, + }; +}; + +export const migratePackagePolicyEvictionsFromV8110: SavedObjectModelVersionForwardCompatibilityFn = + (unknownAttributes) => { + const attributes = unknownAttributes as PackagePolicy; + if (attributes.package?.name !== 'endpoint') { + return attributes; + } + + const updatedAttributes = attributes; + + const input = updatedAttributes.inputs[0]; + + if (input && input.config) { + input.config.policy.value = omit(input.config.policy.value, ['global_manifest_version']); + } + + return updatedAttributes; + }; diff --git a/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts b/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts index bfc5d2e272e4a..ec1f9840962da 100644 --- a/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts +++ b/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts @@ -28,6 +28,7 @@ export const policyFactory = ( cloud, serverless, }, + global_manifest_version: 'latest', windows: { events: { credential_access: true, diff --git a/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.test.ts b/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.test.ts index 8be5c054fcfb0..8b1480656bbb4 100644 --- a/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.test.ts +++ b/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.test.ts @@ -192,6 +192,7 @@ describe('Policy Config helpers', () => { // This constant makes sure that if the type `PolicyConfig` is ever modified, // the logic for disabling protections is also modified due to type check. export const eventsOnlyPolicy = (): PolicyConfig => ({ + global_manifest_version: 'latest', meta: { license: '', cloud: false, diff --git a/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.ts b/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.ts index cb460e2f75f49..472fcfdfd825a 100644 --- a/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.ts +++ b/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.ts @@ -16,52 +16,50 @@ interface PolicyProtectionReference { disableValue: unknown; } -const getPolicyProtectionsReference = (): PolicyProtectionReference[] => { - const allOsValues = [ - PolicyOperatingSystem.mac, - PolicyOperatingSystem.linux, - PolicyOperatingSystem.windows, - ]; - - return [ - { - keyPath: 'malware.mode', - osList: [...allOsValues], - disableValue: ProtectionModes.off, - enableValue: ProtectionModes.prevent, - }, - { - keyPath: 'ransomware.mode', - osList: [PolicyOperatingSystem.windows], - disableValue: ProtectionModes.off, - enableValue: ProtectionModes.prevent, - }, - { - keyPath: 'memory_protection.mode', - osList: [...allOsValues], - disableValue: ProtectionModes.off, - enableValue: ProtectionModes.prevent, - }, - { - keyPath: 'behavior_protection.mode', - osList: [...allOsValues], - disableValue: ProtectionModes.off, - enableValue: ProtectionModes.prevent, - }, - { - keyPath: 'attack_surface_reduction.credential_hardening.enabled', - osList: [PolicyOperatingSystem.windows], - disableValue: false, - enableValue: true, - }, - { - keyPath: 'antivirus_registration.enabled', - osList: [PolicyOperatingSystem.windows], - disableValue: false, - enableValue: true, - }, - ]; -}; +const allOsValues = [ + PolicyOperatingSystem.mac, + PolicyOperatingSystem.linux, + PolicyOperatingSystem.windows, +]; + +const getPolicyProtectionsReference = (): PolicyProtectionReference[] => [ + { + keyPath: 'malware.mode', + osList: [...allOsValues], + disableValue: ProtectionModes.off, + enableValue: ProtectionModes.prevent, + }, + { + keyPath: 'ransomware.mode', + osList: [PolicyOperatingSystem.windows], + disableValue: ProtectionModes.off, + enableValue: ProtectionModes.prevent, + }, + { + keyPath: 'memory_protection.mode', + osList: [...allOsValues], + disableValue: ProtectionModes.off, + enableValue: ProtectionModes.prevent, + }, + { + keyPath: 'behavior_protection.mode', + osList: [...allOsValues], + disableValue: ProtectionModes.off, + enableValue: ProtectionModes.prevent, + }, + { + keyPath: 'attack_surface_reduction.credential_hardening.enabled', + osList: [PolicyOperatingSystem.windows], + disableValue: false, + enableValue: true, + }, + { + keyPath: 'antivirus_registration.enabled', + osList: [PolicyOperatingSystem.windows], + disableValue: false, + enableValue: true, + }, +]; /** * Returns a copy of the passed `PolicyConfig` with all protections set to disabled. @@ -87,8 +85,8 @@ export const disableProtections = (policy: PolicyConfig): PolicyConfig => { const disableCommonProtections = (policy: PolicyConfig) => { return Object.keys(policy).reduce<PolicyConfig>((acc, item) => { - const os = item as keyof PolicyConfig; - if (os === 'meta') { + const os = item as keyof PolicyConfig as PolicyOperatingSystem; + if (!allOsValues.includes(os)) { return acc; } return { @@ -105,10 +103,7 @@ const disableCommonProtections = (policy: PolicyConfig) => { }, policy); }; -const getDisabledCommonProtectionsForOS = ( - policy: PolicyConfig, - os: keyof Omit<PolicyConfig, 'meta'> -) => ({ +const getDisabledCommonProtectionsForOS = (policy: PolicyConfig, os: PolicyOperatingSystem) => ({ behavior_protection: { ...policy[os].behavior_protection, mode: ProtectionModes.off, @@ -124,10 +119,7 @@ const getDisabledCommonProtectionsForOS = ( }, }); -const getDisabledCommonPopupsForOS = ( - policy: PolicyConfig, - os: keyof Omit<PolicyConfig, 'meta'> -) => ({ +const getDisabledCommonPopupsForOS = (policy: PolicyConfig, os: PolicyOperatingSystem) => ({ behavior_protection: { ...policy[os].popup.behavior_protection, enabled: false, @@ -184,7 +176,7 @@ export const isPolicySetToEventCollectionOnly = ( let message: string | undefined; const hasEnabledProtection = protectionsRef.some(({ keyPath, osList, disableValue }) => { - const hasOsPropertyEnabled = osList.some((osValue) => { + return osList.some((osValue) => { const fullKeyPathForOs = `${osValue}.${keyPath}`; const currentValue = get(policy, fullKeyPathForOs); const isEnabled = currentValue !== disableValue; @@ -195,8 +187,6 @@ export const isPolicySetToEventCollectionOnly = ( return isEnabled; }); - - return hasOsPropertyEnabled; }); return { diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index b71495d6288f2..e50fd5aa089ff 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -948,6 +948,7 @@ export interface PolicyConfig { serverless: boolean; heartbeatinterval?: number; }; + global_manifest_version: 'latest' | string; windows: { advanced?: { [key: string]: unknown; diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 7314277c440f2..b06a5532ec12c 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -113,6 +113,11 @@ export const allowedExperimentalValues = Object.freeze({ * * */ discoverInTimeline: false, + + /** + * Enables Protection Updates tab in the Endpoint Policy Details page + */ + protectionUpdatesEnabled: true, }); type ExperimentalConfigKeys = Array<keyof ExperimentalFeatures>; diff --git a/x-pack/plugins/security_solution/public/app/translations.ts b/x-pack/plugins/security_solution/public/app/translations.ts index 1ea363673f441..fcee866a2da3a 100644 --- a/x-pack/plugins/security_solution/public/app/translations.ts +++ b/x-pack/plugins/security_solution/public/app/translations.ts @@ -157,6 +157,13 @@ export const RESPONSE_ACTIONS_HISTORY = i18n.translate( } ); +export const PROTECTION_UPDATES = i18n.translate( + 'xpack.securitySolution.navigation.protectionUpdates', + { + defaultMessage: 'Protection updates', + } +); + export const CREATE_NEW_RULE = i18n.translate('xpack.securitySolution.navigation.newRuleTitle', { defaultMessage: 'Create new rule', }); diff --git a/x-pack/plugins/security_solution/public/management/common/breadcrumbs.ts b/x-pack/plugins/security_solution/public/management/common/breadcrumbs.ts index 8bb985df9610d..aca8f865fce8a 100644 --- a/x-pack/plugins/security_solution/public/management/common/breadcrumbs.ts +++ b/x-pack/plugins/security_solution/public/management/common/breadcrumbs.ts @@ -13,6 +13,7 @@ import { HOST_ISOLATION_EXCEPTIONS, BLOCKLIST, RESPONSE_ACTIONS_HISTORY, + PROTECTION_UPDATES, } from '../../app/translations'; const TabNameMappedToI18nKey: Record<AdministrationSubTab, string> = { @@ -23,6 +24,7 @@ const TabNameMappedToI18nKey: Record<AdministrationSubTab, string> = { [AdministrationSubTab.hostIsolationExceptions]: HOST_ISOLATION_EXCEPTIONS, [AdministrationSubTab.blocklist]: BLOCKLIST, [AdministrationSubTab.responseActionsHistory]: RESPONSE_ACTIONS_HISTORY, + [AdministrationSubTab.protectionUpdates]: PROTECTION_UPDATES, }; export function getTrailingBreadcrumbs(params: AdministrationRouteSpyState): ChromeBreadcrumb[] { diff --git a/x-pack/plugins/security_solution/public/management/common/constants.ts b/x-pack/plugins/security_solution/public/management/common/constants.ts index edaaa2d21a409..b362f696e9756 100644 --- a/x-pack/plugins/security_solution/public/management/common/constants.ts +++ b/x-pack/plugins/security_solution/public/management/common/constants.ts @@ -17,6 +17,7 @@ export const MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH = `${MANAGEMENT export const MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId/eventFilters`; export const MANAGEMENT_ROUTING_POLICY_DETAILS_HOST_ISOLATION_EXCEPTIONS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId/hostIsolationExceptions`; export const MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId/blocklists`; +export const MANAGEMENT_ROUTING_POLICY_DETAILS_PROTECTION_UPDATES_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId/protectionUpdates`; /** @deprecated use the paths defined above instead */ export const MANAGEMENT_ROUTING_POLICY_DETAILS_PATH_OLD = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId`; export const MANAGEMENT_ROUTING_TRUSTED_APPS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.trustedApps})`; diff --git a/x-pack/plugins/security_solution/public/management/common/routing.ts b/x-pack/plugins/security_solution/public/management/common/routing.ts index 4f9c5795df4ca..dc662a68dcd29 100644 --- a/x-pack/plugins/security_solution/public/management/common/routing.ts +++ b/x-pack/plugins/security_solution/public/management/common/routing.ts @@ -29,6 +29,7 @@ import { MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_FORM_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_HOST_ISOLATION_EXCEPTIONS_PATH, + MANAGEMENT_ROUTING_POLICY_DETAILS_PROTECTION_UPDATES_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH, MANAGEMENT_ROUTING_TRUSTED_APPS_PATH, } from './constants'; @@ -292,3 +293,15 @@ export const getPolicyBlocklistsPath = ( querystring.stringify(normalizePolicyDetailsArtifactsListPageLocation(location)) )}`; }; + +export const getPolicyProtectionUpdatesPath = ( + policyId: string, + location?: Partial<PolicyDetailsArtifactsPageLocation> +) => { + return `${generatePath(MANAGEMENT_ROUTING_POLICY_DETAILS_PROTECTION_UPDATES_PATH, { + tabName: AdministrationSubTab.policies, + policyId, + })}${appendSearch( + querystring.stringify(normalizePolicyDetailsArtifactsListPageLocation(location)) + )}`; +}; diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/policy_details.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/policy_details.cy.ts new file mode 100644 index 0000000000000..6e63264f63e2e --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/policy_details.cy.ts @@ -0,0 +1,169 @@ +/* + * 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 moment from 'moment/moment'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import type { PolicyData } from '../../../../../common/endpoint/types'; +import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../tasks/fleet'; +import { setCustomProtectionUpdatesManifestVersion } from '../../tasks/endpoint_policy'; +import { login, ROLE } from '../../tasks/login'; +import { disableExpandableFlyoutAdvancedSettings, loadPage } from '../../tasks/common'; + +describe('Policy Details', () => { + describe('Protection updates', () => { + const loadProtectionUpdatesUrl = (policyId: string) => + loadPage(`/app/security/administration/policy/${policyId}/protectionUpdates`); + + describe('Renders and saves protection updates', () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + const today = moment(); + const formattedToday = today.format('MMMM DD, YYYY'); + + beforeEach(() => { + login(); + disableExpandableFlyoutAdvancedSettings(); + }); + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + }); + }); + }); + + after(() => { + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } + }); + + it('should render the protection updates tab content', () => { + loadProtectionUpdatesUrl(policy.id); + cy.getByTestSubj('protection-updates-automatic-updates-enabled'); + cy.getByTestSubj('protection-updates-manifest-switch'); + cy.getByTestSubj('protection-updates-manifest-name-title'); + cy.getByTestSubj('protection-updates-manifest-name'); + + cy.getByTestSubj('protection-updates-manifest-switch').click(); + + cy.getByTestSubj('protection-updates-manifest-name-deployed-version-title'); + cy.getByTestSubj('protection-updates-deployed-version').contains('latest'); + cy.getByTestSubj('protection-updates-manifest-name-version-to-deploy-title'); + cy.getByTestSubj('protection-updates-version-to-deploy-picker').within(() => { + cy.get('input').should('have.value', formattedToday); + }); + cy.getByTestSubj('policyDetailsSaveButton'); + }); + + it('should successfully update the manifest version to custom date', () => { + loadProtectionUpdatesUrl(policy.id); + cy.getByTestSubj('protection-updates-manifest-switch').click(); + cy.intercept('PUT', `/api/fleet/package_policies/${policy.id}`).as('policy'); + cy.getByTestSubj('policyDetailsSaveButton').click(); + cy.wait('@policy').then(({ request, response }) => { + expect(request.body.inputs[0].config.policy.value.global_manifest_version).to.equal( + today.format('YYYY-MM-DD') + ); + expect(response?.statusCode).to.equal(200); + }); + cy.getByTestSubj('protectionUpdatesSuccessfulMessage'); + cy.getByTestSubj('protection-updates-deployed-version').contains(formattedToday); + }); + }); + + describe('Renders and saves protection updates with custom version', () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + + const twoMonthsAgo = moment().subtract(2, 'months').format('YYYY-MM-DD'); + + beforeEach(() => { + login(); + disableExpandableFlyoutAdvancedSettings(); + }); + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + setCustomProtectionUpdatesManifestVersion(policy.id, twoMonthsAgo); + }); + }); + }); + + after(() => { + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } + }); + + it('should update manifest version to latest when enabling automatic updates', () => { + loadProtectionUpdatesUrl(policy.id); + cy.getByTestSubj('protection-updates-manifest-outdated'); + cy.intercept('PUT', `/api/fleet/package_policies/${policy.id}`).as('policy_latest'); + + cy.getByTestSubj('protection-updates-manifest-switch').click(); + cy.wait('@policy_latest').then(({ request, response }) => { + expect(request.body.inputs[0].config.policy.value.global_manifest_version).to.equal( + 'latest' + ); + expect(response?.statusCode).to.equal(200); + }); + cy.getByTestSubj('protectionUpdatesSuccessfulMessage'); + cy.getByTestSubj('protection-updates-automatic-updates-enabled'); + }); + }); + + describe('Renders read only protection updates for user without write permissions', () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + const twoMonthsAgo = moment().subtract(2, 'months'); + + beforeEach(() => { + login(ROLE.endpoint_security_policy_management_read); + disableExpandableFlyoutAdvancedSettings(); + }); + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + setCustomProtectionUpdatesManifestVersion(policy.id, twoMonthsAgo.format('YYYY-MM-DD')); + }); + }); + }); + + after(() => { + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } + }); + + it('should render the protection updates tab content', () => { + loadProtectionUpdatesUrl(policy.id); + cy.getByTestSubj('protection-updates-manifest-switch').should('not.exist'); + cy.getByTestSubj('protection-updates-state-view-mode'); + cy.getByTestSubj('protection-updates-manifest-name-title'); + cy.getByTestSubj('protection-updates-manifest-name'); + + cy.getByTestSubj('protection-updates-manifest-name-deployed-version-title'); + cy.getByTestSubj('protection-updates-deployed-version').contains( + twoMonthsAgo.format('MMMM DD, YYYY') + ); + cy.getByTestSubj('protection-updates-manifest-name-version-to-deploy-title'); + cy.getByTestSubj('protection-updates-version-to-deploy-view-mode'); + cy.getByTestSubj('protection-updates-version-to-deploy-picker').should('not.exist'); + cy.getByTestSubj('policyDetailsSaveButton').should('be.disabled'); + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/endpoint_policy.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/endpoint_policy.ts index 134fc470b412b..f597e9ae4e225 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/endpoint_policy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/endpoint_policy.ts @@ -61,3 +61,36 @@ export const enableAllPolicyProtections = ( }); }); }; + +export const setCustomProtectionUpdatesManifestVersion = ( + endpointPolicyId: string, + manifestVersion: string +) => { + return request<GetOnePackagePolicyResponse>({ + method: 'GET', + url: packagePolicyRouteService.getInfoPath(endpointPolicyId), + }).then(({ body: { item: endpointPolicy } }) => { + const { + created_by: _createdBy, + created_at: _createdAt, + updated_at: _updatedAt, + updated_by: _updatedBy, + id, + version, + revision, + ...restOfPolicy + } = endpointPolicy; + + const updatedEndpointPolicy: UpdatePackagePolicy = restOfPolicy; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const policy = updatedEndpointPolicy!.inputs[0]!.config!.policy.value; + + policy.global_manifest_version = manifestVersion; + + return request<UpdatePackagePolicyResponse>({ + method: 'PUT', + url: packagePolicyRouteService.getUpdatePath(endpointPolicyId), + body: updatedEndpointPolicy, + }); + }); +}; diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/login.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/login.ts index 24f2fe450cfd7..637f6b157875c 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/login.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/login.ts @@ -22,7 +22,10 @@ import { getThreatIntelligenceAnalyst } from '../../../../scripts/endpoint/commo import { getSocManager } from '../../../../scripts/endpoint/common/roles_users/soc_manager'; import { getPlatformEngineer } from '../../../../scripts/endpoint/common/roles_users/platform_engineer'; import { getEndpointOperationsAnalyst } from '../../../../scripts/endpoint/common/roles_users/endpoint_operations_analyst'; -import { getEndpointSecurityPolicyManager } from '../../../../scripts/endpoint/common/roles_users/endpoint_security_policy_manager'; +import { + getEndpointSecurityPolicyManagementReadRole, + getEndpointSecurityPolicyManager, +} from '../../../../scripts/endpoint/common/roles_users/endpoint_security_policy_manager'; import { getDetectionsEngineer } from '../../../../scripts/endpoint/common/roles_users/detections_engineer'; export enum ROLE { @@ -37,6 +40,7 @@ export enum ROLE { endpoint_security_policy_manager = 'endpointSecurityPolicyManager', endpoint_response_actions_access = 'endpointResponseActionsAccess', endpoint_response_actions_no_access = 'endpointResponseActionsNoAccess', + endpoint_security_policy_management_read = 'endpointSecurityPolicyManagementRead', } export const rolesMapping: { [key in ROLE]: Omit<Role, 'name'> } = { @@ -51,6 +55,7 @@ export const rolesMapping: { [key in ROLE]: Omit<Role, 'name'> } = { detectionsEngineer: getDetectionsEngineer(), endpointResponseActionsAccess: getWithResponseActionsRole(), endpointResponseActionsNoAccess: getNoResponseActionsRole(), + endpointSecurityPolicyManagementRead: getEndpointSecurityPolicyManagementReadRole(), }; /** * Credentials in the `kibana.dev.yml` config file will be used to authenticate diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/index.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/index.tsx index 55e28fcf4b55c..e04b04da3f9fb 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/index.tsx @@ -9,6 +9,7 @@ import React, { memo } from 'react'; import { Redirect } from 'react-router-dom'; import { Routes, Route } from '@kbn/shared-ux-router'; +import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { PolicyDetails, PolicyList } from './view'; import { MANAGEMENT_ROUTING_POLICY_DETAILS_FORM_PATH, @@ -18,11 +19,14 @@ import { MANAGEMENT_ROUTING_POLICY_DETAILS_HOST_ISOLATION_EXCEPTIONS_PATH, MANAGEMENT_ROUTING_POLICIES_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH, + MANAGEMENT_ROUTING_POLICY_DETAILS_PROTECTION_UPDATES_PATH, } from '../../common/constants'; import { NotFoundPage } from '../../../app/404'; import { getPolicyDetailPath } from '../../common/routing'; export const PolicyContainer = memo(() => { + const isProtectionUpdatesEnabled = useIsExperimentalFeatureEnabled('protectionUpdatesEnabled'); + return ( <Routes> <Route @@ -32,6 +36,9 @@ export const PolicyContainer = memo(() => { MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_HOST_ISOLATION_EXCEPTIONS_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH, + ...(isProtectionUpdatesEnabled + ? [MANAGEMENT_ROUTING_POLICY_DETAILS_PROTECTION_UPDATES_PATH] + : []), ]} exact component={PolicyDetails} diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts index 43b35ec683963..27c86e0e6ca0a 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts @@ -269,6 +269,7 @@ describe('policy details: ', () => { }, policy: { value: { + global_manifest_version: 'latest', meta: { license: '', cloud: false, diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_common_selectors.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_common_selectors.ts index e8f9a95d8a470..eb081d10d6375 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_common_selectors.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_common_selectors.ts @@ -13,6 +13,7 @@ import { MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH, + MANAGEMENT_ROUTING_POLICY_DETAILS_PROTECTION_UPDATES_PATH, } from '../../../../../common/constants'; import type { PolicyDetailsSelector, PolicyDetailsState } from '../../../types'; @@ -90,3 +91,15 @@ export const isOnBlocklistsView: PolicyDetailsSelector<boolean> = createSelector ); } ); + +export const isOnProtectionUpdatesView: PolicyDetailsSelector<boolean> = createSelector( + getUrlLocationPathname, + (pathname) => { + return ( + matchPath(pathname ?? '', { + path: MANAGEMENT_ROUTING_POLICY_DETAILS_PROTECTION_UPDATES_PATH, + exact: true, + }) !== null + ); + } +); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_settings_selectors.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_settings_selectors.ts index 5eac0615cc090..7e79fb9c57cdd 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_settings_selectors.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_settings_selectors.ts @@ -24,6 +24,7 @@ import { MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH, + MANAGEMENT_ROUTING_POLICY_DETAILS_PROTECTION_UPDATES_PATH, } from '../../../../../common/constants'; import type { ManagementRoutePolicyDetailsParams } from '../../../../../types'; import { getPolicyDataForUpdate } from '../../../../../../../common/endpoint/service/policy'; @@ -33,6 +34,7 @@ import { isOnHostIsolationExceptionsView, isOnPolicyFormView, isOnBlocklistsView, + isOnProtectionUpdatesView, } from './policy_common_selectors'; /** Returns the policy details */ @@ -96,7 +98,8 @@ export const isOnPolicyDetailsPage = (state: Immutable<PolicyDetailsState>) => isOnPolicyTrustedAppsView(state) || isOnPolicyEventFiltersView(state) || isOnHostIsolationExceptionsView(state) || - isOnBlocklistsView(state); + isOnBlocklistsView(state) || + isOnProtectionUpdatesView(state); /** Returns the license info fetched from the license service */ export const license = (state: Immutable<PolicyDetailsState>) => { @@ -115,6 +118,7 @@ export const policyIdFromParams: (state: Immutable<PolicyDetailsState>) => strin MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_HOST_ISOLATION_EXCEPTIONS_PATH, MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH, + MANAGEMENT_ROUTING_POLICY_DETAILS_PROTECTION_UPDATES_PATH, ], exact: true, })?.params?.policyId ?? '' diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx new file mode 100644 index 0000000000000..09439918dfde0 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx @@ -0,0 +1,344 @@ +/* + * 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 { EuiSwitchEvent } from '@elastic/eui'; +import { + EuiButton, + EuiCallOut, + EuiDatePicker, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiPanel, + EuiShowFor, + EuiSpacer, + EuiSwitch, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import React, { useCallback, useContext, useState } from 'react'; +import { useDispatch } from 'react-redux'; +import { ThemeContext } from 'styled-components'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import type { Moment } from 'moment'; +import moment from 'moment'; +import { cloneDeep } from 'lodash'; +import { useUserPrivileges } from '../../../../../common/components/user_privileges'; +import { useToasts } from '../../../../../common/lib/kibana'; +import { useUpdateEndpointPolicy } from '../../../../hooks/policy/use_update_endpoint_policy'; +import type { PolicyData, MaybeImmutable } from '../../../../../../common/endpoint/types'; + +interface ProtectionUpdatesLayoutProps { + policy: MaybeImmutable<PolicyData>; +} + +const AUTOMATIC_UPDATES_CHECKBOX_LABEL = i18n.translate( + 'xpack.securitySolution.endpoint.protectionUpdates.useAutomaticUpdates', + { + defaultMessage: 'Use automatic updates', + } +); + +const AUTOMATIC_UPDATES_OFF_CHECKBOX_LABEL = i18n.translate( + 'xpack.securitySolution.endpoint.protectionUpdates.useAutomaticUpdatesOff', + { + defaultMessage: "Don't use automatic updates", + } +); + +export const ProtectionUpdatesLayout = React.memo<ProtectionUpdatesLayoutProps>( + ({ policy: _policy }) => { + const toasts = useToasts(); + const dispatch = useDispatch(); + const { isLoading: isUpdating, mutateAsync: sendPolicyUpdate } = useUpdateEndpointPolicy(); + const { canWritePolicyManagement } = useUserPrivileges().endpointPrivileges; + + const paddingSize = useContext(ThemeContext).eui.euiPanelPaddingModifiers.paddingMedium; + + const policy = _policy as PolicyData; + const deployedVersion = policy.inputs[0].config.policy.value.global_manifest_version; + const [manifestVersion, setManifestVersion] = useState(deployedVersion); + + const today = moment(); + const [selectedDate, setSelectedDate] = useState<Moment>(today); + + const automaticUpdatesEnabled = manifestVersion === 'latest'; + const internalDateFormat = 'YYYY-MM-DD'; + const displayDateFormat = 'MMMM DD, YYYY'; + const formattedDate = moment(deployedVersion, internalDateFormat).format(displayDateFormat); + const cutoffDate = moment().subtract(18, 'months'); // Earliest selectable date + + const viewModeSwitchLabel = automaticUpdatesEnabled + ? AUTOMATIC_UPDATES_CHECKBOX_LABEL + : AUTOMATIC_UPDATES_OFF_CHECKBOX_LABEL; + + const onSave = useCallback( + (version: string) => { + const update = cloneDeep(policy); + update.inputs[0].config.policy.value.global_manifest_version = version; + sendPolicyUpdate({ policy: update }) + .then(({ item: policyItem }) => { + toasts.addSuccess({ + 'data-test-subj': 'protectionUpdatesSuccessfulMessage', + title: i18n.translate( + 'xpack.securitySolution.endpoint.protectionUpdates.updateSuccessTitle', + { + defaultMessage: 'Success!', + } + ), + text: i18n.translate( + 'xpack.securitySolution.endpoint.protectionUpdates.updateSuccessMessage', + { + defaultMessage: 'Manifest updates successfully saved', + } + ), + }); + + // Since the 'policyItem' is stored in a store and fetched as a result of an action on urlChange, we still need to dispatch an action even though Redux was removed from this component. + dispatch({ + type: 'serverReturnedPolicyDetailsData', + payload: { + policyItem, + }, + }); + }) + .catch((err) => { + toasts.addDanger({ + 'data-test-subj': 'protectionUpdatesFailureMessage', + title: i18n.translate( + 'xpack.securitySolution.endpoint.protectionUpdates.updateErrorTitle', + { + defaultMessage: 'Failed!', + } + ), + text: err.message, + }); + }); + }, + [dispatch, policy, sendPolicyUpdate, toasts] + ); + + const toggleAutomaticUpdates = useCallback( + (event: EuiSwitchEvent) => { + const { checked } = event.target; + + if (checked && !automaticUpdatesEnabled) { + setManifestVersion('latest'); + // Clear selected date on user enabling automatic updates + if (selectedDate !== today) { + setSelectedDate(today); + } + // We need to save the policy without the user clicking save button + if (deployedVersion !== 'latest') { + onSave('latest'); + } + } else { + setManifestVersion(selectedDate.format(internalDateFormat)); + } + }, + [automaticUpdatesEnabled, deployedVersion, onSave, selectedDate, today] + ); + + const renderVersionToDeployPicker = () => { + return ( + <> + <EuiTitle + size="xxs" + data-test-subj={'protection-updates-manifest-name-version-to-deploy-title'} + > + <h5> + {i18n.translate( + 'xpack.securitySolution.endpoint.protectionUpdates.versionToDeploy.label', + { + defaultMessage: 'Version to deploy', + } + )} + </h5> + </EuiTitle> + <EuiSpacer size="m" /> + {canWritePolicyManagement ? ( + <div data-test-subj={'protection-updates-version-to-deploy-picker'}> + <EuiDatePicker + popoverPlacement={'downCenter'} + dateFormat={displayDateFormat} + selected={selectedDate} + maxDate={today} + minDate={cutoffDate} + onChange={(date) => { + setSelectedDate(date || today); + setManifestVersion(date?.format(internalDateFormat) || 'latest'); + }} + /> + </div> + ) : ( + <EuiText size="m" data-test-subj="protection-updates-version-to-deploy-view-mode"> + {selectedDate.format(displayDateFormat)} + </EuiText> + )} + </> + ); + }; + + const renderManifestOutdatedCallOut = () => { + if (automaticUpdatesEnabled || deployedVersion === 'latest') { + return null; + } + + const deployedVersionDate = moment(deployedVersion).format(internalDateFormat); + const daysSinceLastUpdate = today.diff(deployedVersionDate, 'days'); + + if (daysSinceLastUpdate < 30) { + return null; + } + + return ( + <> + <EuiCallOut + color={'warning'} + iconType={'alert'} + size="m" + data-test-subj="protection-updates-manifest-outdated" + title={i18n.translate( + 'xpack.securitySolution.endpoint.protectionUpdates.manifestOutdated.title', + { + defaultMessage: 'Manifest outdated', + } + )} + > + {i18n.translate('xpack.securitySolution.endpoint.protectionUpdates.manifestOutdated', { + defaultMessage: + 'Manifest is older than 30 days. Recommended to update the manifest or enable "Update manifest automatically".', + })} + </EuiCallOut> + <EuiSpacer size="m" /> + </> + ); + }; + + const renderContent = () => { + if (automaticUpdatesEnabled) { + return ( + <EuiCallOut + color={'primary'} + iconType={'iInCircle'} + size="m" + data-test-subj="protection-updates-automatic-updates-enabled" + title={i18n.translate( + 'xpack.securitySolution.endpoint.protectionUpdates.automaticUpdates.enabledTitle', + { + defaultMessage: 'Automatic updates enabled', + } + )} + > + {i18n.translate( + 'xpack.securitySolution.endpoint.protectionUpdates.automaticUpdates.enabled', + { + defaultMessage: + 'Manifest will always be updated to the latest available version. If you want to control updates manually, disable "Update manifest automatically".', + } + )} + </EuiCallOut> + ); + } + return ( + <> + <EuiTitle + size="xxs" + data-test-subj={'protection-updates-manifest-name-deployed-version-title'} + > + <h5> + {i18n.translate( + 'xpack.securitySolution.endpoint.protectionUpdates.deployedVersion.label', + { + defaultMessage: 'Currently deployed version', + } + )} + </h5> + </EuiTitle> + <EuiSpacer size="m" /> + + <EuiText size="m" data-test-subj="protection-updates-deployed-version"> + {deployedVersion === 'latest' ? 'latest' : formattedDate} + </EuiText> + <EuiSpacer size="l" /> + {renderVersionToDeployPicker()} + + <EuiSpacer size="m" /> + + <EuiButton + fill={true} + disabled={!canWritePolicyManagement} + iconType="save" + data-test-subj="policyDetailsSaveButton" + onClick={() => onSave(manifestVersion)} + isLoading={isUpdating} + > + <FormattedMessage + id="xpack.securitySolution.endpoint.protectionUpdates.saveButton" + defaultMessage="Save updates" + /> + </EuiButton> + </> + ); + }; + + return ( + <EuiPanel + data-test-subject="protection-updates-layout" + hasBorder={true} + hasShadow={false} + paddingSize="none" + > + <EuiFlexGroup + direction="row" + gutterSize="none" + alignItems="center" + style={{ padding: `${paddingSize} ${paddingSize} 0 ${paddingSize}` }} + > + <EuiFlexItem grow={1}> + <EuiTitle size="xxs" data-test-subj={'protection-updates-manifest-name-title'}> + <h5> + {i18n.translate('xpack.securitySolution.endpoint.protectionUpdates.manifestName', { + defaultMessage: 'Manifest name', + })} + </h5> + </EuiTitle> + <EuiText size="m" data-test-subj="protection-updates-manifest-name"> + {'artifactsec'} + </EuiText> + </EuiFlexItem> + <EuiShowFor sizes={['l', 'xl', 'm']}> + {canWritePolicyManagement ? ( + <EuiSwitch + disabled={isUpdating} + label={'Update manifest automatically'} + labelProps={{ 'data-test-subj': 'protection-updates-manifest-switch-label' }} + checked={automaticUpdatesEnabled} + onChange={toggleAutomaticUpdates} + data-test-subj={'protection-updates-manifest-switch'} + /> + ) : ( + <EuiText data-test-subj={'protection-updates-state-view-mode'}> + {viewModeSwitchLabel} + </EuiText> + )} + </EuiShowFor> + </EuiFlexGroup> + + <EuiHorizontalRule margin="m" /> + <EuiSpacer size="m" /> + <div style={{ padding: `0 ${paddingSize} ${paddingSize} ${paddingSize}` }}> + {renderManifestOutdatedCallOut()} + {renderContent()} + </div> + </EuiPanel> + ); + } +); + +ProtectionUpdatesLayout.displayName = 'ProtectionUpdatesLayout'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx index d3f9edc202acc..59fa065784b7c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx @@ -11,6 +11,8 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React, { useCallback, useEffect, useMemo } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; +import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; +import { ProtectionUpdatesLayout } from '../protection_updates/protection_updates_layout'; import { PolicySettingsLayout } from '../policy_settings_layout'; import { useUserPrivileges } from '../../../../../common/components/user_privileges'; import { @@ -24,6 +26,7 @@ import { getPolicyDetailsArtifactsListPath, getBlocklistsListPath, getPolicyBlocklistsPath, + getPolicyProtectionUpdatesPath, } from '../../../../common/routing'; import { useHttp, useToasts } from '../../../../../common/lib/kibana'; import { ManagementPageLoader } from '../../../../components/management_page_loader'; @@ -35,6 +38,7 @@ import { isOnBlocklistsView, policyDetails, policyIdFromParams, + isOnProtectionUpdatesView, } from '../../store/policy_details/selectors'; import { PolicyArtifactsLayout } from '../artifacts/layout/policy_artifacts_layout'; import { usePolicyDetailsSelector } from '../policy_hooks'; @@ -58,6 +62,7 @@ enum PolicyTabKeys { EVENT_FILTERS = 'eventFilters', HOST_ISOLATION_EXCEPTIONS = 'hostIsolationExceptions', BLOCKLISTS = 'blocklists', + PROTECTION_UPDATES = 'protectionUpdates', } interface PolicyTab { @@ -76,6 +81,7 @@ export const PolicyTabs = React.memo(() => { const isInEventFiltersTab = usePolicyDetailsSelector(isOnPolicyEventFiltersView); const isInHostIsolationExceptionsTab = usePolicyDetailsSelector(isOnHostIsolationExceptionsView); const isInBlocklistsTab = usePolicyDetailsSelector(isOnBlocklistsView); + const isInProtectionUpdatesTab = usePolicyDetailsSelector(isOnProtectionUpdatesView); const policyId = usePolicyDetailsSelector(policyIdFromParams); // By the time the tabs load, we know that we already have a `policyItem` since a conditional @@ -95,6 +101,7 @@ export const PolicyTabs = React.memo(() => { } = useUserPrivileges().endpointPrivileges; const { state: routeState = {} } = useLocation<PolicyDetailsRouteState>(); + const isProtectionUpdatesEnabled = useIsExperimentalFeatureEnabled('protectionUpdatesEnabled'); // move the user out of this route if they can't access it useEffect(() => { if ( @@ -120,6 +127,7 @@ export const PolicyTabs = React.memo(() => { isInBlocklistsTab, isInEventFiltersTab, isInHostIsolationExceptionsTab, + isInProtectionUpdatesTab, isInTrustedAppsTab, policyId, toasts, @@ -301,21 +309,40 @@ export const PolicyTabs = React.memo(() => { ), } : undefined, + + [PolicyTabKeys.PROTECTION_UPDATES]: isProtectionUpdatesEnabled + ? { + id: PolicyTabKeys.PROTECTION_UPDATES, + name: i18n.translate( + 'xpack.securitySolution.endpoint.policy.details.tabs.protectionUpdates', + { + defaultMessage: 'Protection updates', + } + ), + content: ( + <> + <EuiSpacer /> + <ProtectionUpdatesLayout policy={policyItem} /> + </> + ), + } + : undefined, }; }, [ + policyItem, canReadTrustedApplications, + getTrustedAppsApiClientInstance, canWriteTrustedApplications, canReadEventFilters, + getEventFiltersApiClientInstance, canWriteEventFilters, canReadHostIsolationExceptions, + getHostIsolationExceptionsApiClientInstance, canWriteHostIsolationExceptions, canReadBlocklist, - canWriteBlocklist, - getEventFiltersApiClientInstance, - getHostIsolationExceptionsApiClientInstance, getBlocklistsApiClientInstance, - getTrustedAppsApiClientInstance, - policyItem, + canWriteBlocklist, + isProtectionUpdatesEnabled, ]); // convert tabs object into an array EuiTabbedContent can understand @@ -338,6 +365,8 @@ export const PolicyTabs = React.memo(() => { selectedTab = tabs[PolicyTabKeys.HOST_ISOLATION_EXCEPTIONS]; } else if (isInBlocklistsTab) { selectedTab = tabs[PolicyTabKeys.BLOCKLISTS]; + } else if (isInProtectionUpdatesTab) { + selectedTab = tabs[PolicyTabKeys.PROTECTION_UPDATES]; } return selectedTab || defaultTab; @@ -348,6 +377,7 @@ export const PolicyTabs = React.memo(() => { isInEventFiltersTab, isInHostIsolationExceptionsTab, isInBlocklistsTab, + isInProtectionUpdatesTab, ]); const onTabClickHandler = useCallback( @@ -369,6 +399,9 @@ export const PolicyTabs = React.memo(() => { case PolicyTabKeys.BLOCKLISTS: path = getPolicyBlocklistsPath(policyId); break; + case PolicyTabKeys.PROTECTION_UPDATES: + path = getPolicyProtectionUpdatesPath(policyId); + break; } history.push(path, routeState?.backLink ? { backLink: routeState.backLink } : null); }, diff --git a/x-pack/plugins/security_solution/public/management/types.ts b/x-pack/plugins/security_solution/public/management/types.ts index 4ca2c34dfcc19..94f671ac09e2f 100644 --- a/x-pack/plugins/security_solution/public/management/types.ts +++ b/x-pack/plugins/security_solution/public/management/types.ts @@ -32,6 +32,7 @@ export enum AdministrationSubTab { hostIsolationExceptions = 'host_isolation_exceptions', blocklist = 'blocklist', responseActionsHistory = 'response_actions_history', + protectionUpdates = 'protection_updates', } /** diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_security_policy_manager.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_security_policy_manager.ts index d4a94b3063a59..ca90761a62d0c 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_security_policy_manager.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_security_policy_manager.ts @@ -32,3 +32,19 @@ export const getEndpointSecurityPolicyManager: () => Omit<Role, 'name'> = () => ], }; }; + +export const getEndpointSecurityPolicyManagementReadRole: () => Omit<Role, 'name'> = () => { + const noResponseActionsRole = getNoResponseActionsRole(); + return { + ...noResponseActionsRole, + kibana: [ + { + ...noResponseActionsRole.kibana[0], + feature: { + ...noResponseActionsRole.kibana[0].feature, + siem: ['minimal_all', 'policy_management_read'], + }, + }, + ], + }; +}; From 78ba034a6998d128dcb3443034cb23cff4e50613 Mon Sep 17 00:00:00 2001 From: Yngrid Coello <yngrid.coello@elastic.co> Date: Mon, 28 Aug 2023 12:26:41 +0200 Subject: [PATCH 03/49] [Logs onboarding] e2e tests - entry points (#164561) Relates to https://github.com/elastic/kibana/issues/164022. --- .../e2e/cypress/e2e/home.cy.ts | 19 ++++++++- .../observability/cypress/cypress.config.ts | 14 +++++++ .../cypress/e2e/navigation.cy.ts | 35 +++++----------- .../e2e/observability_onboarding/home.cy.ts | 26 ++++++++++++ .../observability/cypress/support/commands.ts | 41 ++++++++++++++++--- .../observability/cypress/support/types.d.ts | 1 + 6 files changed, 104 insertions(+), 32 deletions(-) create mode 100644 x-pack/test_serverless/functional/test_suites/observability/cypress/e2e/observability_onboarding/home.cy.ts diff --git a/x-pack/plugins/observability_onboarding/e2e/cypress/e2e/home.cy.ts b/x-pack/plugins/observability_onboarding/e2e/cypress/e2e/home.cy.ts index 8f65ec2e721f5..71aa6a0eb09e6 100644 --- a/x-pack/plugins/observability_onboarding/e2e/cypress/e2e/home.cy.ts +++ b/x-pack/plugins/observability_onboarding/e2e/cypress/e2e/home.cy.ts @@ -10,7 +10,24 @@ describe('[Observability onboarding] Landing page', () => { cy.loginAsElastic(); }); - it('shows landing page', () => { + describe('Entry point', () => { + it('when clicking on the logs card the user is navigated to the observability onboarding page', () => { + cy.getByTestSubj('guideButtonRedirect').click(); + cy.getByTestSubj('onboarding--observability--logs').click(); + + cy.url().should('include', '/app/observabilityOnboarding'); + }); + + it('when clicking on observability overview callout the user is navigated to the observability onboarding page', () => { + cy.visitKibana('/app/observability'); + cy.getByTestSubj('observability-onboarding-callout').should('exist'); + cy.getByTestSubj('o11yObservabilityOnboardingGetStartedButton').click(); + + cy.url().should('include', '/app/observabilityOnboarding'); + }); + }); + + it('when user navigates to observability onboarding landing page is showed', () => { cy.visitKibana('/app/observabilityOnboarding'); cy.contains('Get started with Observability'); }); diff --git a/x-pack/test_serverless/functional/test_suites/observability/cypress/cypress.config.ts b/x-pack/test_serverless/functional/test_suites/observability/cypress/cypress.config.ts index f078275aab2eb..52eaff1a67792 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/cypress/cypress.config.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/cypress/cypress.config.ts @@ -6,6 +6,15 @@ */ import { defineCypressConfig } from '@kbn/cypress-config'; +import { kbnTestConfig } from '@kbn/test'; + +import Url from 'url'; + +const kibanaUrlWithoutAuth = Url.format({ + protocol: kbnTestConfig.getUrlParts().protocol, + hostname: kbnTestConfig.getUrlParts().hostname, + port: kbnTestConfig.getUrlParts().port, +}); export default defineCypressConfig({ fileServerFolder: './cypress', @@ -30,4 +39,9 @@ export default defineCypressConfig({ supportFile: './support/e2e.ts', specPattern: './e2e/**/*.cy.ts', }, + env: { + username: kbnTestConfig.getUrlParts().username, + password: kbnTestConfig.getUrlParts().password, + kibanaUrlWithoutAuth, + }, }); diff --git a/x-pack/test_serverless/functional/test_suites/observability/cypress/e2e/navigation.cy.ts b/x-pack/test_serverless/functional/test_suites/observability/cypress/e2e/navigation.cy.ts index df1bea1e56e85..84abae3258cff 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/cypress/e2e/navigation.cy.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/cypress/e2e/navigation.cy.ts @@ -6,12 +6,11 @@ */ describe('Serverless', () => { - it('Should login', () => { + beforeEach(() => { cy.loginAsElasticUser(); }); it('contains the side navigation for observabilitity serverless', () => { - cy.loginAsElasticUser(); cy.contains('Discover'); cy.contains('Dashboards'); cy.contains('Alerts'); @@ -23,8 +22,6 @@ describe('Serverless', () => { }); it('navigates to discover-dashboard-viz links', () => { - cy.loginAsElasticUser(); - cy.contains('Discover').click(); cy.url().should('include', '/app/discover'); @@ -36,8 +33,6 @@ describe('Serverless', () => { }); it('navigates to alerts links', () => { - cy.loginAsElasticUser(); - cy.contains('Alerts').click(); cy.url().should('include', '/observability/alerts'); @@ -49,8 +44,6 @@ describe('Serverless', () => { }); it('navigates to apm links', () => { - cy.loginAsElasticUser(); - cy.contains('Applications').click(); cy.contains('Services').click(); cy.url().should('include', '/apm/services'); @@ -63,15 +56,11 @@ describe('Serverless', () => { }); it('navigates to get started links', () => { - cy.loginAsElasticUser(); - cy.contains('Add data').click(); cy.url().should('include', '/app/observabilityOnboarding'); }); it('navigates to AIOps links', () => { - cy.loginAsElasticUser(); - cy.contains('AIOps').click(); cy.contains('Anomaly detection').click(); cy.url().should('include', '/app/ml/jobs'); @@ -87,8 +76,6 @@ describe('Serverless', () => { }); it('navigates to project settings', () => { - cy.loginAsElasticUser(); - cy.contains('Project settings').click(); cy.contains('Management').click(); cy.url().should('include', '/app/management'); @@ -101,22 +88,21 @@ describe('Serverless', () => { }); it('sets service nav item as active', () => { - cy.loginAsElasticUser('/app/apm/service-groups'); - + cy.visitKibana('/app/apm/service-groups'); cy.getByTestSubj('nav-item-id-apm').should('have.class', 'euiSideNavItemButton-isOpen'); cy.getByTestSubj('nav-item-id-apm:services').should( 'have.class', 'euiSideNavItemButton-isSelected' ); - cy.loginAsElasticUser('/app/apm/service-maps'); + cy.visitKibana('/app/apm/service-maps'); cy.getByTestSubj('nav-item-id-apm').should('have.class', 'euiSideNavItemButton-isOpen'); cy.getByTestSubj('nav-item-id-apm:services').should( 'have.class', 'euiSideNavItemButton-isSelected' ); - cy.loginAsElasticUser('/app/apm/mobile-services/foo'); + cy.visitKibana('/app/apm/mobile-services/foo'); cy.getByTestSubj('nav-item-id-apm').should('have.class', 'euiSideNavItemButton-isOpen'); cy.getByTestSubj('nav-item-id-apm:services').should( 'have.class', @@ -125,15 +111,14 @@ describe('Serverless', () => { }); it('sets dependencies nav item as active', () => { - cy.loginAsElasticUser('/app/apm/dependencies/inventory'); - + cy.visitKibana('/app/apm/dependencies/inventory'); cy.getByTestSubj('nav-item-id-apm').should('have.class', 'euiSideNavItemButton-isOpen'); cy.getByTestSubj('nav-item-id-apm:dependencies').should( 'have.class', 'euiSideNavItemButton-isSelected' ); - cy.loginAsElasticUser('/app/apm/dependencies/operations?dependencyName=foo'); + cy.visitKibana('/app/apm/dependencies/operations?dependencyName=foo'); cy.getByTestSubj('nav-item-id-apm').should('have.class', 'euiSideNavItemButton-isOpen'); cy.getByTestSubj('nav-item-id-apm:dependencies').should( 'have.class', @@ -142,7 +127,7 @@ describe('Serverless', () => { }); it('sets traces nav item as active', () => { - cy.loginAsElasticUser('/app/apm/traces/explorer/waterfall'); + cy.visitKibana('/app/apm/traces/explorer/waterfall'); cy.getByTestSubj('nav-item-id-apm').should('have.class', 'euiSideNavItemButton-isOpen'); cy.getByTestSubj('nav-item-id-apm:traces').should( @@ -150,7 +135,7 @@ describe('Serverless', () => { 'euiSideNavItemButton-isSelected' ); - cy.loginAsElasticUser('/app/apm/traces/explorer/critical_path'); + cy.visitKibana('/app/apm/traces/explorer/critical_path'); cy.getByTestSubj('nav-item-id-apm').should('have.class', 'euiSideNavItemButton-isOpen'); cy.getByTestSubj('nav-item-id-apm:traces').should( 'have.class', @@ -159,7 +144,7 @@ describe('Serverless', () => { }); it('sets AIOps nav item as active', () => { - cy.loginAsElasticUser('app/ml/aiops/explain_log_rate_spikes'); + cy.visitKibana('/app/ml/aiops/explain_log_rate_spikes'); cy.getByTestSubj('nav-item-id-aiops').should('have.class', 'euiSideNavItemButton-isOpen'); cy.getByTestSubj('nav-item-id-ml:logRateAnalysis').should( @@ -167,7 +152,7 @@ describe('Serverless', () => { 'euiSideNavItemButton-isSelected' ); - cy.loginAsElasticUser('app/ml/aiops/change_point_detection'); + cy.visitKibana('/app/ml/aiops/change_point_detection'); cy.getByTestSubj('nav-item-id-aiops').should('have.class', 'euiSideNavItemButton-isOpen'); cy.getByTestSubj('nav-item-id-ml:changePointDetections').should( 'have.class', diff --git a/x-pack/test_serverless/functional/test_suites/observability/cypress/e2e/observability_onboarding/home.cy.ts b/x-pack/test_serverless/functional/test_suites/observability/cypress/e2e/observability_onboarding/home.cy.ts new file mode 100644 index 0000000000000..7e74c75b62ebc --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/observability/cypress/e2e/observability_onboarding/home.cy.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +describe('[Serverless Observability onboarding] Landing page', () => { + beforeEach(() => { + cy.loginAsElasticUser(); + }); + + it('when user navigates to observability onboarding landing page is showed', () => { + cy.visitKibana('/app/observabilityOnboarding'); + cy.contains('Get started with Observability'); + }); + + describe('Entry point', () => { + it('when clicking on Add data the user is navigated to the observability onboarding page', () => { + cy.contains('Add data').click(); + cy.url().should('include', '/app/observabilityOnboarding'); + }); + }); +}); + +export {}; diff --git a/x-pack/test_serverless/functional/test_suites/observability/cypress/support/commands.ts b/x-pack/test_serverless/functional/test_suites/observability/cypress/support/commands.ts index f9cea31215176..715e5c9df22fc 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/cypress/support/commands.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/cypress/support/commands.ts @@ -4,18 +4,47 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import 'cypress-real-events/support'; import 'cypress-axe'; +import 'cypress-real-events/support'; +import URL from 'url'; -Cypress.Commands.add('loginAsElasticUser', (path?: string) => { - cy.visit(path ?? '/', { - auth: { - username: 'elastic', - password: 'changeme', +Cypress.Commands.add('loginAsElasticUser', () => { + const username = Cypress.env('username'); + const password = Cypress.env('password'); + const kibanaUrlWithoutAuth = Cypress.env('kibanaUrlWithoutAuth'); + cy.log(`Logging in as ${username} on ${kibanaUrlWithoutAuth}`); + cy.visit('/'); + cy.request({ + log: true, + method: 'POST', + url: `${kibanaUrlWithoutAuth}/internal/security/login`, + body: { + providerType: 'basic', + providerName: 'basic', + currentURL: `${kibanaUrlWithoutAuth}/login`, + params: { username, password }, + }, + headers: { + 'kbn-xsrf': 'e2e_test', + 'x-elastic-internal-origin': 'kibana', }, }); + cy.visit('/'); }); Cypress.Commands.add('getByTestSubj', (selector: string) => { return cy.get(`[data-test-subj*="${selector}"]`); }); + +Cypress.Commands.add('visitKibana', (url: string, rangeFrom?: string, rangeTo?: string) => { + const urlPath = URL.format({ + pathname: url, + query: { rangeFrom, rangeTo }, + }); + + cy.visit(urlPath); + cy.getByTestSubj('kbnLoadingMessage').should('exist'); + cy.getByTestSubj('kbnLoadingMessage').should('not.exist', { + timeout: 50000, + }); +}); diff --git a/x-pack/test_serverless/functional/test_suites/observability/cypress/support/types.d.ts b/x-pack/test_serverless/functional/test_suites/observability/cypress/support/types.d.ts index ae802c601d193..7b11b4916742c 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/cypress/support/types.d.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/cypress/support/types.d.ts @@ -9,5 +9,6 @@ declare namespace Cypress { interface Chainable { loginAsElasticUser(path?: string): Cypress.Chainable<Cypress.Response<any>>; getByTestSubj(selector: string): Chainable<JQuery<Element>>; + visitKibana(url: string, rangeFrom?: string, rangeTo?: string): void; } } From e22f9b860e6d62ddcaacae6a1b2f57178afa8e54 Mon Sep 17 00:00:00 2001 From: Juan Pablo Djeredjian <jpdjeredjian@gmail.com> Date: Mon, 28 Aug 2023 13:02:22 +0200 Subject: [PATCH 04/49] [Security Solution] Fix flakiness in: `prebuilt_rules_management.cy.ts` - Deletes and recovers more than one rule (#164694) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Relates to: https://github.com/elastic/kibana/issues/161507 ## Summary - Solves flakiness in following test: - Filename: `x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_management.cy.ts` - Test name: **Prebuilt rules Actions with prebuilt rules Rules table Deletes and recovers more than one rule** - Test was failing because of already observed issue of `autoRefresh` taking place while the rule selection is happening, causing Cypress to lose focus and preventing the checkbox from being checked. This PR disables autorefresh from the table to prevent that from happening. ## Flaky test runner 350 iters: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/2976 🟢 --- .../prebuilt_rules/prebuilt_rules_management.cy.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_management.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_management.cy.ts index 9eb5f33bcdb4d..b172b84b76953 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_management.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_management.cy.ts @@ -18,6 +18,7 @@ import { } from '../../../screens/alerts_detection_rules'; import { deleteFirstRule, + disableAutoRefresh, getRulesManagementTableRows, selectAllRules, selectRulesByName, @@ -32,6 +33,7 @@ import { import { createAndInstallMockedPrebuiltRules, getAvailablePrebuiltRulesCount, + preventPrebuiltRulesPackageInstallation, } from '../../../tasks/api_calls/prebuilt_rules'; import { cleanKibana, @@ -57,10 +59,12 @@ describe('Prebuilt rules', { tags: ['@ess', '@serverless'] }, () => { login(); deleteAlertsAndRules(); deletePrebuiltRulesAssets(); + preventPrebuiltRulesPackageInstallation(); visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); createAndInstallMockedPrebuiltRules({ rules }); cy.reload(); waitForPrebuiltDetectionRulesToBeLoaded(); + disableAutoRefresh(); }); describe('Alerts rules, prebuilt rules', () => { From 3bb97dcc49e67e13655ed735ea73a799082ef2ec Mon Sep 17 00:00:00 2001 From: Elastic Machine <elasticmachine@users.noreply.github.com> Date: Mon, 28 Aug 2023 20:57:22 +0930 Subject: [PATCH 05/49] [main] Sync bundled packages with Package Storage (#164950) Automated by https://internal-ci.elastic.co/job/package_storage/job/sync-bundled-packages-job/job/main/6537/ Co-authored-by: apmmachine <infra-root+apmmachine@elastic.co> --- fleet_packages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fleet_packages.json b/fleet_packages.json index 3570b649fb2d6..a7278bbdd809e 100644 --- a/fleet_packages.json +++ b/fleet_packages.json @@ -24,7 +24,7 @@ [ { "name": "apm", - "version": "8.11.0-preview-1692980426", + "version": "8.11.0-preview-1693211748", "forceAlignStackVersion": true, "allowSyncToPrerelease": true }, From 8720a90cb38c0c39c4b0d9229de5a8c6497a46db Mon Sep 17 00:00:00 2001 From: Maxim Kholod <maxim.kholod@elastic.co> Date: Mon, 28 Aug 2023 14:37:03 +0300 Subject: [PATCH 06/49] [Cloud Security] do not filter out vulnerabilities without resource.id field (#163936) ## Summary Part of - https://github.com/elastic/security-team/issues/7146 As we are aiming to remove the filtering logic for vulnerabilities with missing fields I suggest removing the `resource.id` part of the filter. Having this filter doesn't seem to bring any value, just limiting the capabilities for users. Vulnerabilities without `resource.id` will show up in the grid and on the dashboard, they just won't appear in the grouping. In my opinion, this is fine and we always can improve it if we see that having documents without `resource.id` is a valid case for our users ## Screenshots <img width="1712" alt="Screenshot 2023-08-25 at 15 05 38" src="https://github.com/elastic/kibana/assets/478762/e7577e0b-7b6b-484e-883f-aa0dabc05d55"> <img width="1728" alt="Screenshot 2023-08-25 at 15 05 51" src="https://github.com/elastic/kibana/assets/478762/e02ef85a-9b41-4d05-8e05-be3e238e71f1"> --- .../get_safe_vulnerabilities_query_filter.ts | 15 -------- .../hooks/use_latest_vulnerabilities.tsx | 3 +- .../use_latest_vulnerabilities_by_resource.ts | 3 +- .../get_top_patchable_vulnerabilities.ts | 34 ++++++++----------- .../get_top_vulnerabilities.ts | 13 +++---- .../get_top_vulnerable_resources.ts | 13 +++---- .../get_vulnerabilities_statistics.ts | 17 ++++------ .../vulnerabilities_dashboard.ts | 16 +++------ .../server/tasks/findings_stats_task.ts | 5 +-- 9 files changed, 45 insertions(+), 74 deletions(-) delete mode 100644 x-pack/plugins/cloud_security_posture/common/utils/get_safe_vulnerabilities_query_filter.ts diff --git a/x-pack/plugins/cloud_security_posture/common/utils/get_safe_vulnerabilities_query_filter.ts b/x-pack/plugins/cloud_security_posture/common/utils/get_safe_vulnerabilities_query_filter.ts deleted file mode 100644 index 899bc5177458e..0000000000000 --- a/x-pack/plugins/cloud_security_posture/common/utils/get_safe_vulnerabilities_query_filter.ts +++ /dev/null @@ -1,15 +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 { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; - -export const getSafeVulnerabilitiesQueryFilter = (query?: QueryDslQueryContainer) => ({ - ...query, - bool: { - ...query?.bool, - filter: [...((query?.bool?.filter as []) || []), { exists: { field: 'resource.id' } }], - }, -}); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx index 31b1efe73b453..a3ae53a25f4d9 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx @@ -17,7 +17,6 @@ import { } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { CspVulnerabilityFinding } from '../../../../common/schemas'; import { LATEST_VULNERABILITIES_INDEX_PATTERN } from '../../../../common/constants'; -import { getSafeVulnerabilitiesQueryFilter } from '../../../../common/utils/get_safe_vulnerabilities_query_filter'; import { useKibana } from '../../../common/hooks/use_kibana'; import { showErrorToast } from '../../../common/utils/show_error_toast'; import { FindingsBaseEsQuery } from '../../../common/types'; @@ -37,7 +36,7 @@ interface VulnerabilitiesQuery extends FindingsBaseEsQuery { export const getFindingsQuery = ({ query, sort, pageIndex, pageSize }: VulnerabilitiesQuery) => ({ index: LATEST_VULNERABILITIES_INDEX_PATTERN, - query: getSafeVulnerabilitiesQueryFilter(query), + query, from: pageIndex * pageSize, size: pageSize, sort, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_by_resource.ts b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_by_resource.ts index 706f980408d18..3aa152d427143 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_by_resource.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_by_resource.ts @@ -21,7 +21,6 @@ import { LATEST_VULNERABILITIES_INDEX_PATTERN, VULNERABILITIES_SEVERITY, } from '../../../../common/constants'; -import { getSafeVulnerabilitiesQueryFilter } from '../../../../common/utils/get_safe_vulnerabilities_query_filter'; import { MAX_FINDINGS_TO_LOAD } from '../../../common/constants'; import { useKibana } from '../../../common/hooks/use_kibana'; @@ -60,7 +59,7 @@ export const getQuery = ({ pageSize, }: VulnerabilitiesQuery) => ({ index: LATEST_VULNERABILITIES_INDEX_PATTERN, - query: getSafeVulnerabilitiesQueryFilter(query), + query, aggs: { total: { cardinality: { field: 'resource.id' } }, resources: { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts index 9863b865c7542..6eec795e2dad6 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { AggFieldBucket, PatchableVulnerabilityStat } from '../../../common/types'; import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS } from '../../../common/constants'; @@ -26,9 +26,19 @@ export interface PatchableVulnerabilitiesQueryResult { }; } -const getPatchableVulnerabilitiesQuery = (query: QueryDslQueryContainer): SearchRequest => ({ +const getPatchableVulnerabilitiesQuery = (): SearchRequest => ({ size: 0, - query, + query: { + bool: { + filter: [ + { + exists: { + field: 'package.fixed_version', + }, + }, + ], + }, + }, index: LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, aggs: { patchable_vulnerabilities: { @@ -64,24 +74,10 @@ const getPatchableVulnerabilitiesQuery = (query: QueryDslQueryContainer): Search }); export const getTopPatchableVulnerabilities = async ( - esClient: ElasticsearchClient, - query: QueryDslQueryContainer + esClient: ElasticsearchClient ): Promise<PatchableVulnerabilityStat[]> => { const queryResult = await esClient.search<unknown, PatchableVulnerabilitiesQueryResult>( - getPatchableVulnerabilitiesQuery({ - ...query, - bool: { - ...query.bool, - filter: [ - ...(query.bool?.filter as QueryDslQueryContainer[]), - { - exists: { - field: 'package.fixed_version', - }, - }, - ], - }, - }) + getPatchableVulnerabilitiesQuery() ); if (!queryResult?.aggregations?.patchable_vulnerabilities) return []; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts index 962b4135ad96f..cd8c5b64f532d 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { VulnerabilityStat } from '../../../common/types'; import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS } from '../../../common/constants'; @@ -72,9 +72,11 @@ export interface VulnerabilitiesQueryResult { }; } -const getVulnerabilitiesQuery = (query: QueryDslQueryContainer): SearchRequest => ({ +const getVulnerabilitiesQuery = (): SearchRequest => ({ size: 0, - query, + query: { + match_all: {}, + }, index: LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, aggs: { vulnerabilities: { @@ -126,11 +128,10 @@ const getVulnerabilitiesQuery = (query: QueryDslQueryContainer): SearchRequest = }); export const getTopVulnerabilities = async ( - esClient: ElasticsearchClient, - query: QueryDslQueryContainer + esClient: ElasticsearchClient ): Promise<VulnerabilityStat[]> => { const queryResult = await esClient.search<unknown, VulnerabilitiesQueryResult>( - getVulnerabilitiesQuery(query) + getVulnerabilitiesQuery() ); if (!queryResult?.aggregations?.vulnerabilities) return []; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts index 1753e3499fee3..0a41a11aeedea 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { AggFieldBucket, VulnerableResourceStat } from '../../../common/types'; import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS } from '../../../common/constants'; @@ -23,9 +23,11 @@ export interface VulnerableResourcesQueryResult { }; } -const getVulnerabilitiesResourcesQuery = (query: QueryDslQueryContainer): SearchRequest => ({ +const getVulnerabilitiesResourcesQuery = (): SearchRequest => ({ size: 0, - query, + query: { + match_all: {}, + }, index: LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, aggs: { vulnerable_resources: { @@ -55,11 +57,10 @@ const getVulnerabilitiesResourcesQuery = (query: QueryDslQueryContainer): Search }); export const getTopVulnerableResources = async ( - esClient: ElasticsearchClient, - query: QueryDslQueryContainer + esClient: ElasticsearchClient ): Promise<VulnerableResourceStat[]> => { const queryResult = await esClient.search<unknown, VulnerableResourcesQueryResult>( - getVulnerabilitiesResourcesQuery(query) + getVulnerabilitiesResourcesQuery() ); if (!queryResult?.aggregations?.vulnerable_resources) return []; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_statistics.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_statistics.ts index 5139e3cb92ba9..8458d66817f82 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_statistics.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_statistics.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, @@ -30,11 +30,11 @@ export interface VulnerabilitiesStatisticsQueryResult { }; } -export const getVulnerabilitiesStatisticsQuery = ( - query: QueryDslQueryContainer -): SearchRequest => ({ +export const getVulnerabilitiesStatisticsQuery = (): SearchRequest => ({ size: 0, - query, + query: { + match_all: {}, + }, index: LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, aggs: { critical: { @@ -59,12 +59,9 @@ export const getVulnerabilitiesStatisticsQuery = ( }, }); -export const getVulnerabilitiesStatistics = async ( - esClient: ElasticsearchClient, - query: QueryDslQueryContainer -) => { +export const getVulnerabilitiesStatistics = async (esClient: ElasticsearchClient) => { const queryResult = await esClient.search<unknown, VulnerabilitiesStatisticsQueryResult>( - getVulnerabilitiesStatisticsQuery(query) + getVulnerabilitiesStatisticsQuery() ); return { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts index be45fefeccd3d..e77851062217c 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts @@ -9,18 +9,12 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { getVulnerabilitiesTrends } from './get_vulnerabilities_trend'; import type { CnvmDashboardData } from '../../../common/types'; import { VULNERABILITIES_DASHBOARD_ROUTE_PATH } from '../../../common/constants'; -import { getSafeVulnerabilitiesQueryFilter } from '../../../common/utils/get_safe_vulnerabilities_query_filter'; import { CspRouter } from '../../types'; import { getVulnerabilitiesStatistics } from './get_vulnerabilities_statistics'; import { getTopVulnerableResources } from './get_top_vulnerable_resources'; import { getTopPatchableVulnerabilities } from './get_top_patchable_vulnerabilities'; import { getTopVulnerabilities } from './get_top_vulnerabilities'; -export interface KeyDocCount<TKey = string> { - key: TKey; - doc_count: number; -} - export const defineGetVulnerabilitiesDashboardRoute = (router: CspRouter): void => router.get( { @@ -36,8 +30,6 @@ export const defineGetVulnerabilitiesDashboardRoute = (router: CspRouter): void try { const esClient = cspContext.esClient.asCurrentUser; - const query = getSafeVulnerabilitiesQueryFilter(); - const [ cnvmStatistics, vulnTrends, @@ -45,11 +37,11 @@ export const defineGetVulnerabilitiesDashboardRoute = (router: CspRouter): void topPatchableVulnerabilities, topVulnerabilities, ] = await Promise.all([ - getVulnerabilitiesStatistics(esClient, query), + getVulnerabilitiesStatistics(esClient), getVulnerabilitiesTrends(esClient), - getTopVulnerableResources(esClient, query), - getTopPatchableVulnerabilities(esClient, query), - getTopVulnerabilities(esClient, query), + getTopVulnerableResources(esClient), + getTopPatchableVulnerabilities(esClient), + getTopVulnerabilities(esClient), ]); const body: CnvmDashboardData = { diff --git a/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts b/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts index bec5aacd9f95c..f40ce3f7dc4ab 100644 --- a/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts +++ b/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts @@ -14,7 +14,6 @@ import { import { SearchRequest } from '@kbn/data-plugin/common'; import { ElasticsearchClient } from '@kbn/core/server'; import type { Logger } from '@kbn/core/server'; -import { getSafeVulnerabilitiesQueryFilter } from '../../common/utils/get_safe_vulnerabilities_query_filter'; import { getSafePostureTypeRuntimeMapping } from '../../common/runtime_mappings/get_safe_posture_type_runtime_mapping'; import { getIdentifierRuntimeMapping } from '../../common/runtime_mappings/get_identifier_runtime_mapping'; import { FindingsStatsTaskResult, ScoreByPolicyTemplateBucket, VulnSeverityAggs } from './types'; @@ -186,7 +185,9 @@ const getScoreQuery = (): SearchRequest => ({ const getVulnStatsTrendQuery = (): SearchRequest => ({ index: LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, size: 0, - query: getSafeVulnerabilitiesQueryFilter(), + query: { + match_all: {}, + }, aggs: { critical: { filter: { term: { 'vulnerability.severity': VULNERABILITIES_SEVERITY.CRITICAL } }, From 5dfa8a6a12fac9b71cf0fe6cafcf5fa556e6fd28 Mon Sep 17 00:00:00 2001 From: Khristinin Nikita <nikita.khristinin@elastic.co> Date: Mon, 28 Aug 2023 13:41:16 +0200 Subject: [PATCH 07/49] Remove legacy risk score dashboards when install risk engine (#164862) ## Remove legacy risk score dashboards when install risk engine ### How to test - Start kibana - Create a filebeat index (to have access to host/user pages) ``` PUT filebeat-8.10.0 { "mappings": { "properties": { "@timestamp": { "type": "date" }, "host": { "properties": { "name": { "type":"keyword" } } } } } } ``` - Go to Security -> Dashboard -> Entity Analytics - Enable Host risk score an User risk score - Go to Security -> Dashboards. Scroll down, and be sure that tags about Host risk score and User risk score are enabled. Observe dashboards related to Host/User risk scores. <img width="804" alt="Screenshot 2023-08-25 at 17 49 08" src="https://github.com/elastic/kibana/assets/7609147/e3cabaa5-8fed-4646-89f9-957c004bc459"> - Then enable this FF `xpack.securitySolution.enableExperimental: ['riskScoringPersistence','riskScoringRoutesEnabled']` - Restart Kibana, and go to Security -> Manage -> Entity Risk Score - Click Start update and then confirm it - Go back to dashboards and observe that there are no related to Host/User risk score <img width="993" alt="Screenshot 2023-08-25 at 17 55 40" src="https://github.com/elastic/kibana/assets/7609147/0ced8167-6f39-46fd-8a5a-2dc977712226"> --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../risk_engine/risk_engine_data_client.ts | 13 ++++ .../risk_engine/init_and_status_apis.ts | 21 ++++- .../group10/risk_engine/utils.ts | 76 ++++++++++++++++++- 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/risk_engine/risk_engine_data_client.ts b/x-pack/plugins/security_solution/server/lib/risk_engine/risk_engine_data_client.ts index bbbf51aef66a6..b66ec12b08d69 100644 --- a/x-pack/plugins/security_solution/server/lib/risk_engine/risk_engine_data_client.ts +++ b/x-pack/plugins/security_solution/server/lib/risk_engine/risk_engine_data_client.ts @@ -35,6 +35,7 @@ import { RiskEngineStatus, getRiskScoreLatestIndex, MAX_SPACES_COUNT, + RiskScoreEntity, } from '../../../common/risk_engine'; import { getLegacyTransforms, @@ -51,6 +52,7 @@ import { import { getRiskInputsIndex } from './get_risk_inputs_index'; import { removeRiskScoringTask, startRiskScoringTask } from './tasks'; import { createIndex } from './utils/create_index'; +import { bulkDeleteSavedObjects } from '../risk_score/prebuilt_saved_objects/helpers/bulk_delete_saved_objects'; interface InitOpts { namespace: string; @@ -212,6 +214,17 @@ export class RiskEngineDataClient { namespace, }); + const deleteDashboardsPromises = [RiskScoreEntity.host, RiskScoreEntity.user].map((entity) => + bulkDeleteSavedObjects({ + deleteAll: true, + savedObjectsClient: this.options.soClient, + spaceId: namespace, + savedObjectTemplate: `${entity}RiskScoreDashboards`, + }) + ); + + await Promise.all(deleteDashboardsPromises); + const newlegacyRiskEngineStatus = await this.getLegacyStatus({ namespace }); return newlegacyRiskEngineStatus === RiskEngineStatus.NOT_INSTALLED; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/risk_engine/init_and_status_apis.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/risk_engine/init_and_status_apis.ts index 0f607843f4107..0babe434c7f90 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/risk_engine/init_and_status_apis.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/risk_engine/init_and_status_apis.ts @@ -15,6 +15,9 @@ import { clearLegacyTransforms, riskEngineRouteHelpersFactory, clearTransforms, + installLegacyRiskScore, + getLegacyRiskScoreDashboards, + clearLegacyDashboards, } from './utils'; // eslint-disable-next-line import/no-default-export @@ -38,6 +41,10 @@ export default ({ getService }: FtrProviderContext) => { es, log, }); + await clearLegacyDashboards({ + supertest, + log, + }); }); describe('init api', () => { @@ -328,7 +335,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should remove legacy risk score transform if it exists', async () => { - await createLegacyTransforms({ es }); + await installLegacyRiskScore({ supertest }); for (const transformId of legacyTransformIds) { const tr = await es.transform.getTransform({ @@ -338,6 +345,12 @@ export default ({ getService }: FtrProviderContext) => { expect(tr?.transforms?.[0]?.id).to.eql(transformId); } + const legacyDashboards = await getLegacyRiskScoreDashboards({ + kibanaServer, + }); + + expect(legacyDashboards.length).to.eql(4); + await riskEngineRoutes.init(); for (const transformId of legacyTransformIds) { @@ -349,6 +362,12 @@ export default ({ getService }: FtrProviderContext) => { expect(err).to.not.be(undefined); } } + + const legacyDashboardsAfterInit = await getLegacyRiskScoreDashboards({ + kibanaServer, + }); + + expect(legacyDashboardsAfterInit.length).to.eql(0); }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/risk_engine/utils.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/risk_engine/utils.ts index b0fbfc4e92c32..0d0cbd3d36d06 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/risk_engine/utils.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/risk_engine/utils.ts @@ -6,7 +6,7 @@ */ import { v4 as uuidv4 } from 'uuid'; -import type SuperTest from 'supertest'; +import SuperTest from 'supertest'; import type { Client } from '@elastic/elasticsearch'; import type { ToolingLog } from '@kbn/tooling-log'; import type { EcsRiskScore, RiskScore } from '@kbn/security-solution-plugin/common/risk_engine'; @@ -346,6 +346,34 @@ export const clearLegacyTransforms = async ({ } }; +export const clearLegacyDashboards = async ({ + supertest, + log, +}: { + supertest: SuperTest.SuperTest<SuperTest.Test>; + log: ToolingLog; +}): Promise<void> => { + try { + await supertest + .post( + '/internal/risk_score/prebuilt_content/saved_objects/_bulk_delete/hostRiskScoreDashboards' + ) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + await supertest + .post( + '/internal/risk_score/prebuilt_content/saved_objects/_bulk_delete/userRiskScoreDashboards' + ) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + } catch (e) { + log.error(`Error deleting legacy dashboards: ${e.message}`); + } +}; + export const createLegacyTransforms = async ({ es }: { es: Client }): Promise<void> => { const transforms = legacyTransformIds.map((transform) => es.transform.putTransform({ @@ -379,6 +407,18 @@ export const createLegacyTransforms = async ({ es }: { es: Client }): Promise<vo await Promise.all(transforms); }; +export const getLegacyRiskScoreDashboards = async ({ + kibanaServer, +}: { + kibanaServer: KbnClient; +}) => { + const savedObejectLens = await kibanaServer.savedObjects.find({ + type: 'lens', + }); + + return savedObejectLens?.saved_objects.filter((s) => s?.attributes?.title?.includes('Risk')); +}; + export const riskEngineRouteHelpersFactory = ( supertest: SuperTest.SuperTest<SuperTest.Test>, namespace?: string @@ -411,3 +451,37 @@ export const riskEngineRouteHelpersFactory = ( .send() .expect(200), }); + +export const installLegacyRiskScore = async ({ + supertest, +}: { + supertest: SuperTest.SuperTest<SuperTest.Test>; +}) => { + await supertest + .post('/internal/risk_score') + .set('kbn-xsrf', 'true') + .send({ riskScoreEntity: 'host' }) + .expect(200); + + await supertest + .post('/internal/risk_score') + .set('kbn-xsrf', 'true') + .send({ riskScoreEntity: 'user' }) + .expect(200); + + await supertest + .post( + '/internal/risk_score/prebuilt_content/saved_objects/_bulk_create/hostRiskScoreDashboards' + ) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + await supertest + .post( + '/internal/risk_score/prebuilt_content/saved_objects/_bulk_create/userRiskScoreDashboards' + ) + .set('kbn-xsrf', 'true') + .send() + .expect(200); +}; From d9a48a65ad6bbc55dc1da11813a25b2a5c333736 Mon Sep 17 00:00:00 2001 From: Liam Thompson <32779855+leemthompo@users.noreply.github.com> Date: Mon, 28 Aug 2023 14:40:01 +0200 Subject: [PATCH 08/49] [SEARCH] Minor connectors copy changes (#164947) --- .../new_index/select_connector/select_connector.tsx | 4 ++-- .../native_connector_configuration/convert_connector.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/select_connector/select_connector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/select_connector/select_connector.tsx index 1afc443077e15..83371d415ad84 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/select_connector/select_connector.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/select_connector/select_connector.tsx @@ -129,7 +129,7 @@ export const SelectConnector: React.FC = () => { <p> <FormattedMessage id="xpack.enterpriseSearch.content.indices.selectConnector.description.textcloud" - defaultMessage="{native} are available directly within Elastic Cloud deployments. No additional infrastructure is required. Self-managed deployments must deploy the connector service to run native connectors. {learnMore}" + defaultMessage="{native} are available directly within Elastic Cloud deployments. No additional infrastructure is required. {learnMore}" values={{ learnMore: ( <EuiLink target="_blank" href={docLinks.connectorsNative}> @@ -150,7 +150,7 @@ export const SelectConnector: React.FC = () => { <br /> <FormattedMessage id="xpack.enterpriseSearch.content.indices.selectConnector.description.selfManaged.text" - defaultMessage="For advanced use cases, deploy {connectorsClient} on your own infrastructure. Customize existing connectors, or build your own using our connector framework. {learnMore}" + defaultMessage="Deploy connectors on your own infrastructure as {connectorsClient}. You can also customize existing connector clients, or build your own using our connector framework. {learnMore}" values={{ connectorsClient: ( <b> diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/convert_connector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/convert_connector.tsx index d2e009baccc79..bb1669c2c0f65 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/convert_connector.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/convert_connector.tsx @@ -46,7 +46,7 @@ export const ConvertConnector: React.FC = () => { {i18n.translate( 'xpack.enterpriseSearch.content.indices.configurationConnector.nativeConnector.convertConnector.title', { - defaultMessage: 'Customize your connector', + defaultMessage: 'Self-manage this connector', } )} </h4> @@ -57,7 +57,7 @@ export const ConvertConnector: React.FC = () => { <EuiText size="s"> <FormattedMessage id="xpack.enterpriseSearch.content.indices.configurationConnector.nativeConnector.convertConnector.description" - defaultMessage="Want to customize this native connector? Convert it to a {link}, to be self-managed on your own infrastructure." + defaultMessage="Want to self-host this native connector? Convert it to a {link}, to be self-managed on your own infrastructure. You'll need to convert this connector if you want to customize the code using our Python framework." values={{ link: ( <EuiLink href={docLinks.buildConnector} target="_blank"> From a7d552602b169b2d598629b0544204f084ced970 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar <dario.gieselaar@elastic.co> Date: Mon, 28 Aug 2023 15:20:57 +0200 Subject: [PATCH 09/49] [Observability AI Assistant] Alerts & top services functions (#164799) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Coen Warmer <coen.warmer@gmail.com> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Clint Andrew Hall <clint@clintandrewhall.com> Co-authored-by: Carlos Crespo <carloshenrique.leonelcrespo@elastic.co> Co-authored-by: Alejandro Fernández Haro <alejandro.haro@elastic.co> --- .../apm/common/utils/formatters/duration.ts | 15 +- .../get_apm_service_summary.ts | 9 +- .../get_apm_services_list.ts | 60 ++++ .../get_apm_timeseries.tsx | 13 +- .../apm/public/assistant_functions/index.ts | 159 +++++---- .../apm/public/utils/non_empty_string_ref.ts | 11 + .../get_error_event_rate.ts | 3 +- .../get_exit_span_failure_rate.ts | 3 +- .../get_exit_span_latency.ts | 5 +- .../get_exit_span_throughput.ts | 5 +- .../get_transaction_failure_rate.ts | 7 +- .../get_transaction_latency.ts | 11 +- .../get_transaction_throughput.ts | 9 +- .../routes/assistant_functions/route.ts | 87 +++++ .../common/types.ts | 1 + .../utils/get_bucket_size/calculate_auto.js | 78 +++++ .../utils/get_bucket_size/index.test.ts | 72 ++++ .../common/utils/get_bucket_size/index.ts | 38 +++ .../utils/get_bucket_size/unit_to_seconds.ts | 27 ++ .../observability_ai_assistant/kibana.jsonc | 2 +- .../message_panel/message_panel.stories.tsx | 27 ++ .../components/message_panel/message_text.tsx | 90 +++-- .../public/functions/alerts.ts | 80 +++++ .../public/functions/elasticsearch.ts | 6 +- .../public/functions/index.ts | 54 +-- .../public/functions/kibana.ts | 69 ++++ .../public/functions/lens.tsx | 14 +- .../public/functions/recall.ts | 30 +- .../public/functions/summarise.ts | 6 +- .../public/hooks/use_knowledge_base.tsx | 82 +++-- .../public/plugin.tsx | 1 + .../service/get_assistant_setup_message.ts | 9 +- .../get_timeline_items_from_conversation.tsx | 14 +- .../server/plugin.ts | 3 +- .../server/routes/chat/route.ts | 7 + .../server/routes/functions/route.ts | 110 +++++- .../server/routes/types.ts | 11 +- .../server/service/client/index.ts | 11 +- .../server/service/index.ts | 64 +++- .../server/service/kb_component_template.ts | 6 + .../server/service/kb_service/index.ts | 219 +++++++----- .../server/service/kb_service/kb_docs/lens.ts | 317 +++++++++--------- .../server/service/util/split_kb_text.ts | 35 ++ .../observability_ai_assistant/tsconfig.json | 4 +- .../stack_connectors/common/gen_ai/schema.ts | 35 +- .../server/connector_types/gen_ai/gen_ai.ts | 3 +- 46 files changed, 1422 insertions(+), 500 deletions(-) create mode 100644 x-pack/plugins/apm/public/assistant_functions/get_apm_services_list.ts create mode 100644 x-pack/plugins/apm/public/utils/non_empty_string_ref.ts create mode 100644 x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/calculate_auto.js create mode 100644 x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/index.test.ts create mode 100644 x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/index.ts create mode 100644 x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/unit_to_seconds.ts create mode 100644 x-pack/plugins/observability_ai_assistant/public/functions/alerts.ts create mode 100644 x-pack/plugins/observability_ai_assistant/public/functions/kibana.ts create mode 100644 x-pack/plugins/observability_ai_assistant/server/service/util/split_kb_text.ts diff --git a/x-pack/plugins/apm/common/utils/formatters/duration.ts b/x-pack/plugins/apm/common/utils/formatters/duration.ts index bf83ed2e093ea..49040f64bb51d 100644 --- a/x-pack/plugins/apm/common/utils/formatters/duration.ts +++ b/x-pack/plugins/apm/common/utils/formatters/duration.ts @@ -31,7 +31,11 @@ export type TimeFormatter = ( options?: FormatterOptions ) => ConvertedDuration; -type TimeFormatterBuilder = (max: number, threshold?: number) => TimeFormatter; +type TimeFormatterBuilder = ( + max: number, + threshold?: number, + scalingFactor?: number +) => TimeFormatter; // threshold defines the value from which upwards there should be no decimal places. function getUnitLabelAndConvertedValue( @@ -150,10 +154,15 @@ function getDurationUnitKey(max: number, threshold = 10): DurationTimeUnit { // memoizer with a custom resolver to consider both arguments max/threshold. // by default lodash's memoize only considers the first argument. export const getDurationFormatter: TimeFormatterBuilder = memoize( - (max: number, threshold: number = 10) => { + (max: number, threshold: number = 10, scalingFactor: number = 1) => { const unit = getDurationUnitKey(max, threshold); return (value: Maybe<number>, { defaultValue }: FormatterOptions = {}) => { - return convertTo({ unit, microseconds: value, defaultValue, threshold }); + return convertTo({ + unit, + microseconds: isFiniteNumber(value) ? value * scalingFactor : value, + defaultValue, + threshold, + }); }; }, (max, threshold) => `${max}_${threshold}` diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_service_summary.ts b/x-pack/plugins/apm/public/assistant_functions/get_apm_service_summary.ts index fbbd35524d43d..189633ec95975 100644 --- a/x-pack/plugins/apm/public/assistant_functions/get_apm_service_summary.ts +++ b/x-pack/plugins/apm/public/assistant_functions/get_apm_service_summary.ts @@ -8,6 +8,7 @@ import { i18n } from '@kbn/i18n'; import type { RegisterFunctionDefinition } from '@kbn/observability-ai-assistant-plugin/common/types'; import { callApmApi } from '../services/rest/create_call_apm_api'; +import { NON_EMPTY_STRING } from '../utils/non_empty_string_ref'; export function registerGetApmServiceSummaryFunction({ registerFunction, @@ -35,20 +36,20 @@ alerts and anomalies.`, type: 'object', properties: { 'service.name': { - type: 'string', + ...NON_EMPTY_STRING, description: 'The name of the service that should be summarized.', }, 'service.environment': { - type: 'string', + ...NON_EMPTY_STRING, description: 'The environment that the service is running in', }, start: { - type: 'string', + ...NON_EMPTY_STRING, description: 'The start of the time range, in Elasticsearch date math, like `now`.', }, end: { - type: 'string', + ...NON_EMPTY_STRING, description: 'The end of the time range, in Elasticsearch date math, like `now-24h`.', }, diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_services_list.ts b/x-pack/plugins/apm/public/assistant_functions/get_apm_services_list.ts new file mode 100644 index 0000000000000..fdbcfb94da650 --- /dev/null +++ b/x-pack/plugins/apm/public/assistant_functions/get_apm_services_list.ts @@ -0,0 +1,60 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import type { RegisterFunctionDefinition } from '@kbn/observability-ai-assistant-plugin/common/types'; +import { callApmApi } from '../services/rest/create_call_apm_api'; +import { NON_EMPTY_STRING } from '../utils/non_empty_string_ref'; + +export function registerGetApmServicesListFunction({ + registerFunction, +}: { + registerFunction: RegisterFunctionDefinition; +}) { + registerFunction( + { + name: 'get_apm_services_list', + contexts: ['apm'], + description: `Gets a list of services`, + descriptionForUser: i18n.translate( + 'xpack.apm.observabilityAiAssistant.functions.registerGetApmServicesList.descriptionForUser', + { + defaultMessage: `Gets the list of monitored services, their health status, and alerts.`, + } + ), + parameters: { + type: 'object', + properties: { + 'service.environment': { + ...NON_EMPTY_STRING, + description: + 'Optionally filter the services by the environments that they are running in', + }, + start: { + ...NON_EMPTY_STRING, + description: + 'The start of the time range, in Elasticsearch date math, like `now`.', + }, + end: { + ...NON_EMPTY_STRING, + description: + 'The end of the time range, in Elasticsearch date math, like `now-24h`.', + }, + }, + required: ['start', 'end'], + } as const, + }, + async ({ arguments: args }, signal) => { + return callApmApi('GET /internal/apm/assistant/get_services_list', { + signal, + params: { + query: args, + }, + }); + } + ); +} diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx b/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx index ff215e646148f..9bdfd4b4789d8 100644 --- a/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx +++ b/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx @@ -31,6 +31,7 @@ import { getMaxY, getResponseTimeTickFormatter, } from '../components/shared/charts/transaction_charts/helper'; +import { NON_EMPTY_STRING } from '../utils/non_empty_string_ref'; export function registerGetApmTimeseriesFunction({ registerFunction, @@ -47,7 +48,7 @@ export function registerGetApmTimeseriesFunction({ defaultMessage: `Display different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions`, } ), - description: `Display different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions. In KQL, escaping happens with double quotes, not single quotes. Some characters that need escaping are: ':()\\\/\". Always put a field value in double quotes. Best: service.name:\"opbeans-go\". Wrong: service.name:opbeans-go. This is very important!`, + description: `Visualise and analyse different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. A visualisation will be displayed above your reply - DO NOT attempt to display or generate an image yourself, or any other placeholder. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions.`, parameters: { type: 'object', properties: { @@ -135,11 +136,11 @@ export function registerGetApmTimeseriesFunction({ ], }, 'service.name': { - type: 'string', + ...NON_EMPTY_STRING, description: 'The name of the service', }, 'service.environment': { - type: 'string', + ...NON_EMPTY_STRING, description: 'The environment that the service is running in.', }, @@ -201,7 +202,7 @@ export function registerGetApmTimeseriesFunction({ const groupId = groupSeries[0].group; const maxY = getMaxY(groupSeries); - const latencyFormatter = getDurationFormatter(maxY); + const latencyFormatter = getDurationFormatter(maxY, 10, 1000); let yLabelFormat: (value: number) => string; @@ -230,6 +231,8 @@ export function registerGetApmTimeseriesFunction({ groupSeries.map((series): TimeSeries<Coordinate> => { let chartType: ChartType; + const data = series.data; + switch (series.stat.timeseries.name) { case 'transaction_throughput': case 'exit_span_throughput': @@ -270,7 +273,7 @@ export function registerGetApmTimeseriesFunction({ title: series.id, type: 'line', color: getTimeSeriesColor(chartType!).currentPeriodColor, - data: series.data, + data, }; }); diff --git a/x-pack/plugins/apm/public/assistant_functions/index.ts b/x-pack/plugins/apm/public/assistant_functions/index.ts index f83e9fa6fc575..128091cf2472d 100644 --- a/x-pack/plugins/apm/public/assistant_functions/index.ts +++ b/x-pack/plugins/apm/public/assistant_functions/index.ts @@ -18,6 +18,7 @@ import { import { registerGetApmCorrelationsFunction } from './get_apm_correlations'; import { registerGetApmDownstreamDependenciesFunction } from './get_apm_downstream_dependencies'; import { registerGetApmErrorDocumentFunction } from './get_apm_error_document'; +import { registerGetApmServicesListFunction } from './get_apm_services_list'; import { registerGetApmServiceSummaryFunction } from './get_apm_service_summary'; import { registerGetApmTimeseriesFunction } from './get_apm_timeseries'; @@ -64,82 +65,92 @@ export async function registerAssistantFunctions({ registerFunction, }); + registerGetApmServicesListFunction({ + registerFunction, + }); + registerContext({ name: 'apm', description: ` -There are four important data types in Elastic APM. Each of them have the -following fields: -- service.name: the name of the service -- service.node.name: the id of the service instance (often the hostname) -- service.environment: the environment (often production, development) -- agent.name: the name of the agent (go, java, etc) - -The four data types are transactions, exit spans, error events, and application -metrics. - -Transactions have three metrics: throughput, failure rate, and latency. The -fields are: - -- transaction.type: often request or page-load (the main transaction types), -but can also be worker, or route-change. -- transaction.name: The name of the transaction group, often something like -'GET /api/product/:productId' -- transaction.result: The result. Used to capture HTTP response codes -(2xx,3xx,4xx,5xx) for request transactions. -- event.outcome: whether the transaction was succesful or not. success, -failure, or unknown. - -Exit spans have three metrics: throughput, failure rate and latency. The fields -are: -- span.type: db, external -- span.subtype: the type of database (redis, postgres) or protocol (http, grpc) -- span.destination.service.resource: the address of the destination of the call -- event.outcome: whether the transaction was succesful or not. success, -failure, or unknown. - -Error events have one metric, error event rate. The fields are: -- error.grouping_name: a human readable keyword that identifies the error group - -For transaction metrics we also collect anomalies. These are scored 0 (low) to -100 (critical). - -For root cause analysis, locate a change point in the relevant metrics for a -service or downstream dependency. You can locate a change point by using a -sliding window, e.g. start with a small time range, like 30m, and make it -bigger until you identify a change point. It's very important to identify a -change point. If you don't have a change point, ask the user for next steps. -You can also use an anomaly or a deployment as a change point. Then, compare -data before the change with data after the change. You can either use the -groupBy parameter in get_apm_chart to get the most occuring values in a certain -data set, or you can use correlations to see for which field and value the -frequency has changed when comparing the foreground set to the background set. -This is useful when comparing data from before the change point with after the -change point. For instance, you might see a specific error pop up more often -after the change point. - -When comparing anomalies and changes in timeseries, first, zoom in to a smaller -time window, at least 30 minutes before and 30 minutes after the change -occured. E.g., if the anomaly occured at 2023-07-05T08:15:00.000Z, request a -time window that starts at 2023-07-05T07:45:00.000Z and ends at -2023-07-05T08:45:00.000Z. When comparing changes in different timeseries and -anomalies to determine a correlation, make sure to compare the timestamps. If -in doubt, rate the likelihood of them being related, given the time difference, -between 1 and 10. If below 5, assume it's not related. Mention this likelihood -(and the time difference) to the user. - -Your goal is to help the user determine the root cause of an issue quickly and -transparently. If you see a change or -anomaly in a metric for a service, try to find similar changes in the metrics -for the traffic to its downstream dependencies, by comparing transaction -metrics to span metrics. To inspect the traffic from one service to a -downstream dependency, first get the downstream dependencies for a service, -then get the span metrics from that service (\`service.name\`) to its -downstream dependency (\`span.destination.service.resource\`). For instance, -for an anomaly in throughput, first inspect \`transaction_throughput\` for -\`service.name\`. Then, inspect \`exit_span_throughput\` for its downstream -dependencies, by grouping by \`span.destination.service.resource\`. Repeat this -process over the next service its downstream dependencies until you identify a -root cause. If you can not find any similar changes, use correlations or -grouping to find attributes that could be causes for the change.`, + When analyzing APM data, prefer the APM specific functions over the generic Lens, + Elasticsearch or Kibana ones, unless those are explicitly requested by the user. + + When requesting metrics for a service, make sure you also know what environment + it is running in. Metrics aggregated over multiple environments are useless. + + There are four important data types in Elastic APM. Each of them have the + following fields: + - service.name: the name of the service + - service.node.name: the id of the service instance (often the hostname) + - service.environment: the environment (often production, development) + - agent.name: the name of the agent (go, java, etc) + + The four data types are transactions, exit spans, error events, and application + metrics. + + Transactions have three metrics: throughput, failure rate, and latency. The + fields are: + + - transaction.type: often request or page-load (the main transaction types), + but can also be worker, or route-change. + - transaction.name: The name of the transaction group, often something like + 'GET /api/product/:productId' + - transaction.result: The result. Used to capture HTTP response codes + (2xx,3xx,4xx,5xx) for request transactions. + - event.outcome: whether the transaction was succesful or not. success, + failure, or unknown. + + Exit spans have three metrics: throughput, failure rate and latency. The fields + are: + - span.type: db, external + - span.subtype: the type of database (redis, postgres) or protocol (http, grpc) + - span.destination.service.resource: the address of the destination of the call + - event.outcome: whether the transaction was succesful or not. success, + failure, or unknown. + + Error events have one metric, error event rate. The fields are: + - error.grouping_name: a human readable keyword that identifies the error group + + For transaction metrics we also collect anomalies. These are scored 0 (low) to + 100 (critical). + + For root cause analysis, locate a change point in the relevant metrics for a + service or downstream dependency. You can locate a change point by using a + sliding window, e.g. start with a small time range, like 30m, and make it + bigger until you identify a change point. It's very important to identify a + change point. If you don't have a change point, ask the user for next steps. + You can also use an anomaly or a deployment as a change point. Then, compare + data before the change with data after the change. You can either use the + groupBy parameter in get_apm_chart to get the most occuring values in a certain + data set, or you can use correlations to see for which field and value the + frequency has changed when comparing the foreground set to the background set. + This is useful when comparing data from before the change point with after the + change point. For instance, you might see a specific error pop up more often + after the change point. + + When comparing anomalies and changes in timeseries, first, zoom in to a smaller + time window, at least 30 minutes before and 30 minutes after the change + occured. E.g., if the anomaly occured at 2023-07-05T08:15:00.000Z, request a + time window that starts at 2023-07-05T07:45:00.000Z and ends at + 2023-07-05T08:45:00.000Z. When comparing changes in different timeseries and + anomalies to determine a correlation, make sure to compare the timestamps. If + in doubt, rate the likelihood of them being related, given the time difference, + between 1 and 10. If below 5, assume it's not related. Mention this likelihood + (and the time difference) to the user. + + Your goal is to help the user determine the root cause of an issue quickly and + transparently. If you see a change or + anomaly in a metric for a service, try to find similar changes in the metrics + for the traffic to its downstream dependencies, by comparing transaction + metrics to span metrics. To inspect the traffic from one service to a + downstream dependency, first get the downstream dependencies for a service, + then get the span metrics from that service (\`service.name\`) to its + downstream dependency (\`span.destination.service.resource\`). For instance, + for an anomaly in throughput, first inspect \`transaction_throughput\` for + \`service.name\`. Then, inspect \`exit_span_throughput\` for its downstream + dependencies, by grouping by \`span.destination.service.resource\`. Repeat this + process over the next service its downstream dependencies until you identify a + root cause. If you can not find any similar changes, use correlations or + grouping to find attributes that could be causes for the change.`, }); } diff --git a/x-pack/plugins/apm/public/utils/non_empty_string_ref.ts b/x-pack/plugins/apm/public/utils/non_empty_string_ref.ts new file mode 100644 index 0000000000000..94cac08fa2198 --- /dev/null +++ b/x-pack/plugins/apm/public/utils/non_empty_string_ref.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const NON_EMPTY_STRING = { + type: 'string' as const, + minLength: 1, +}; diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_error_event_rate.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_error_event_rate.ts index 85debffb41742..9022d4fc87e4b 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_error_event_rate.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_error_event_rate.ts @@ -6,7 +6,6 @@ */ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { RollupInterval } from '../../../../common/rollup'; import type { APMEventClient } from '../../../lib/helpers/create_es_client/create_apm_event_client'; @@ -40,7 +39,7 @@ export async function getErrorEventRate({ documentType: ApmDocumentType.ErrorEvent, rollupInterval: RollupInterval.None, intervalString, - filter: filter.concat(...rangeQuery(start, end)), + filter, aggs: { value: { bucket_script: { diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_failure_rate.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_failure_rate.ts index 655d03dd87448..35ca607e9e338 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_failure_rate.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_failure_rate.ts @@ -6,7 +6,7 @@ */ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { EVENT_OUTCOME, @@ -45,7 +45,6 @@ export async function getExitSpanFailureRate({ rollupInterval: RollupInterval.OneMinute, intervalString, filter: filter.concat( - ...rangeQuery(start, end), ...termQuery( SPAN_DESTINATION_SERVICE_RESOURCE, spanDestinationServiceResource diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_latency.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_latency.ts index 1d5bcd04cd35c..ad1f8cb8791be 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_latency.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_latency.ts @@ -6,7 +6,7 @@ */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { SPAN_DESTINATION_SERVICE_RESOURCE, @@ -39,12 +39,11 @@ export async function getExitSpanLatency({ start, end, operationName: 'assistant_get_exit_span_latency', - unit: 'rpm', + unit: 'ms', documentType: ApmDocumentType.ServiceDestinationMetric, rollupInterval: RollupInterval.OneMinute, intervalString, filter: filter.concat( - ...rangeQuery(start, end), ...termQuery( SPAN_DESTINATION_SERVICE_RESOURCE, spanDestinationServiceResource diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_throughput.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_throughput.ts index dd49c4c7d79f4..ab1be9d2c20dc 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_throughput.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_throughput.ts @@ -6,7 +6,7 @@ */ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { SPAN_DESTINATION_SERVICE_RESOURCE } from '../../../../common/es_fields/apm'; import { RollupInterval } from '../../../../common/rollup'; @@ -44,7 +44,6 @@ export async function getExitSpanThroughput({ rollupInterval: RollupInterval.OneMinute, intervalString, filter: filter.concat( - ...rangeQuery(start, end), ...termQuery( SPAN_DESTINATION_SERVICE_RESOURCE, spanDestinationServiceResource @@ -73,7 +72,7 @@ export async function getExitSpanThroughput({ ...fetchedSerie, value: fetchedSerie.value !== null - ? fetchedSerie.value / rangeInMinutes + ? (fetchedSerie.value * bucketSizeInMinutes) / rangeInMinutes : null, data: fetchedSerie.data.map((bucket) => { return { diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_failure_rate.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_failure_rate.ts index b4b0704ce6ea9..8e44eac64e3e9 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_failure_rate.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_failure_rate.ts @@ -6,7 +6,7 @@ */ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { TRANSACTION_TYPE } from '../../../../common/es_fields/apm'; import { RollupInterval } from '../../../../common/rollup'; @@ -40,10 +40,7 @@ export async function getTransactionFailureRate({ documentType: ApmDocumentType.TransactionMetric, rollupInterval: RollupInterval.OneMinute, intervalString, - filter: filter.concat( - ...rangeQuery(start, end), - ...termQuery(TRANSACTION_TYPE, transactionType) - ), + filter: filter.concat(...termQuery(TRANSACTION_TYPE, transactionType)), groupBy: 'transaction.type', aggs: { ...getOutcomeAggregation(ApmDocumentType.TransactionMetric), diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_latency.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_latency.ts index 8cbb6dd74d2d9..f51378c647fd4 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_latency.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_latency.ts @@ -6,7 +6,7 @@ */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { TRANSACTION_DURATION_HISTOGRAM, @@ -41,15 +41,12 @@ export async function getTransactionLatency({ apmEventClient, start, end, - operationName: 'assistant_get_transaction_latencyu', - unit: 'rpm', + operationName: 'assistant_get_transaction_latency', + unit: 'ms', documentType: ApmDocumentType.TransactionMetric, rollupInterval: RollupInterval.OneMinute, intervalString, - filter: filter.concat( - ...rangeQuery(start, end), - ...termQuery(TRANSACTION_TYPE, transactionType) - ), + filter: filter.concat(...termQuery(TRANSACTION_TYPE, transactionType)), groupBy: 'transaction.type', aggs: { ...getLatencyAggregation( diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_throughput.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_throughput.ts index 919f2b63e5165..891ebd8b6a356 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_throughput.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_throughput.ts @@ -6,7 +6,7 @@ */ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { TRANSACTION_TYPE } from '../../../../common/es_fields/apm'; import { RollupInterval } from '../../../../common/rollup'; @@ -43,10 +43,7 @@ export async function getTransactionThroughput({ documentType: ApmDocumentType.TransactionMetric, rollupInterval: RollupInterval.OneMinute, intervalString, - filter: filter.concat( - ...rangeQuery(start, end), - ...termQuery(TRANSACTION_TYPE, transactionType) - ), + filter: filter.concat(...termQuery(TRANSACTION_TYPE, transactionType)), groupBy: 'transaction.type', aggs: { value: { @@ -70,7 +67,7 @@ export async function getTransactionThroughput({ ...fetchedSerie, value: fetchedSerie.value !== null - ? fetchedSerie.value / rangeInMinutes + ? (fetchedSerie.value * bucketSizeInMinutes) / rangeInMinutes : null, data: fetchedSerie.data.map((bucket) => { return { diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/route.ts b/x-pack/plugins/apm/server/routes/assistant_functions/route.ts index bd2d32c90907e..1d02003c5e46c 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/route.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/route.ts @@ -4,14 +4,22 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import datemath from '@elastic/datemath'; import { ElasticsearchClient } from '@kbn/core/server'; import * as t from 'io-ts'; import { omit } from 'lodash'; +import { ApmDocumentType } from '../../../common/document_type'; +import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; +import { RollupInterval } from '../../../common/rollup'; +import { ServiceHealthStatus } from '../../../common/service_health_status'; import type { APMError } from '../../../typings/es_schemas/ui/apm_error'; import { getApmAlertsClient } from '../../lib/helpers/get_apm_alerts_client'; import { getApmEventClient } from '../../lib/helpers/get_apm_event_client'; import { getMlClient } from '../../lib/helpers/get_ml_client'; +import { getRandomSampler } from '../../lib/helpers/get_random_sampler'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { environmentRt } from '../default_api_types'; +import { getServicesItems } from '../services/get_services/get_services_items'; import { CorrelationValue, correlationValuesRouteRt, @@ -184,10 +192,89 @@ const getApmErrorDocRoute = createApmServerRoute({ }, }); +interface ApmServicesListItem { + 'service.name': string; + 'agent.name'?: string; + 'transaction.type'?: string; + alertsCount: number; + healthStatus: ServiceHealthStatus; + 'service.environment'?: string[]; +} + +type ApmServicesListContent = ApmServicesListItem[]; + +const getApmServicesListRoute = createApmServerRoute({ + endpoint: 'GET /internal/apm/assistant/get_services_list', + params: t.type({ + query: t.intersection([ + t.type({ + start: t.string, + end: t.string, + }), + t.partial({ + 'service.environment': environmentRt.props.environment, + }), + ]), + }), + options: { + tags: ['access:apm'], + }, + handler: async (resources): Promise<{ content: ApmServicesListContent }> => { + const { params } = resources; + const { query } = params; + + const [apmEventClient, apmAlertsClient, mlClient, randomSampler] = + await Promise.all([ + getApmEventClient(resources), + getApmAlertsClient(resources), + getMlClient(resources), + getRandomSampler({ + security: resources.plugins.security, + probability: 1, + request: resources.request, + }), + ]); + + const start = datemath.parse(query.start)?.valueOf()!; + const end = datemath.parse(query.end)?.valueOf()!; + + const serviceItems = await getServicesItems({ + apmAlertsClient, + apmEventClient, + documentType: ApmDocumentType.TransactionMetric, + start, + end, + environment: query['service.environment'] ?? ENVIRONMENT_ALL.value, + kuery: '', + logger: resources.logger, + randomSampler, + rollupInterval: RollupInterval.OneMinute, + serviceGroup: null, + mlClient, + }); + + const mappedItems = serviceItems.items.map((item): ApmServicesListItem => { + return { + 'service.name': item.serviceName, + 'agent.name': item.agentName, + alertsCount: item.alertsCount ?? 0, + healthStatus: item.healthStatus ?? ServiceHealthStatus.unknown, + 'service.environment': item.environments, + 'transaction.type': item.transactionType, + }; + }); + + return { + content: mappedItems, + }; + }, +}); + export const assistantRouteRepository = { ...getApmTimeSeriesRoute, ...getApmServiceSummaryRoute, ...getApmErrorDocRoute, ...getApmCorrelationValuesRoute, ...getDownstreamDependenciesRoute, + ...getApmServicesListRoute, }; diff --git a/x-pack/plugins/observability_ai_assistant/common/types.ts b/x-pack/plugins/observability_ai_assistant/common/types.ts index d1d9e8ef31332..1d8be57fd53b3 100644 --- a/x-pack/plugins/observability_ai_assistant/common/types.ts +++ b/x-pack/plugins/observability_ai_assistant/common/types.ts @@ -64,6 +64,7 @@ export interface KnowledgeBaseEntry { confidence: 'low' | 'medium' | 'high'; is_correction: boolean; public: boolean; + labels: Record<string, string>; } export type CompatibleJSONSchema = Exclude<JSONSchema, boolean>; diff --git a/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/calculate_auto.js b/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/calculate_auto.js new file mode 100644 index 0000000000000..bd4d6e51ccc0d --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/calculate_auto.js @@ -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 moment from 'moment'; +const d = moment.duration; + +const roundingRules = [ + [d(500, 'ms'), d(100, 'ms')], + [d(5, 'second'), d(1, 'second')], + [d(7.5, 'second'), d(5, 'second')], + [d(15, 'second'), d(10, 'second')], + [d(45, 'second'), d(30, 'second')], + [d(3, 'minute'), d(1, 'minute')], + [d(9, 'minute'), d(5, 'minute')], + [d(20, 'minute'), d(10, 'minute')], + [d(45, 'minute'), d(30, 'minute')], + [d(2, 'hour'), d(1, 'hour')], + [d(6, 'hour'), d(3, 'hour')], + [d(24, 'hour'), d(12, 'hour')], + [d(1, 'week'), d(1, 'd')], + [d(3, 'week'), d(1, 'week')], + [d(1, 'year'), d(1, 'month')], + [Infinity, d(1, 'year')], +]; + +const revRoundingRules = roundingRules.slice(0).reverse(); + +function find(rules, check, last) { + function pick(buckets, duration) { + const target = duration / buckets; + let lastResp = null; + + for (let i = 0; i < rules.length; i++) { + const rule = rules[i]; + const resp = check(rule[0], rule[1], target); + + if (resp == null) { + if (!last) continue; + if (lastResp) return lastResp; + break; + } + + if (!last) return resp; + lastResp = resp; + } + + // fallback to just a number of milliseconds, ensure ms is >= 1 + const ms = Math.max(Math.floor(target), 1); + return moment.duration(ms, 'ms'); + } + + return (buckets, duration) => { + const interval = pick(buckets, duration); + if (interval) return moment.duration(interval._data); + }; +} + +export const calculateAuto = { + near: find( + revRoundingRules, + function near(bound, interval, target) { + if (bound > target) return interval; + }, + true + ), + + lessThan: find(revRoundingRules, function lessThan(_bound, interval, target) { + if (interval < target) return interval; + }), + + atLeast: find(revRoundingRules, function atLeast(_bound, interval, target) { + if (interval <= target) return interval; + }), +}; diff --git a/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/index.test.ts b/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/index.test.ts new file mode 100644 index 0000000000000..e91b6b44dee7f --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/index.test.ts @@ -0,0 +1,72 @@ +/* + * 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 { getBucketSize } from '.'; +import moment from 'moment'; + +describe('getBuckets', () => { + describe("minInterval 'auto'", () => { + it('last 15 minutes', () => { + const start = moment().subtract(15, 'minutes').valueOf(); + const end = moment.now(); + expect(getBucketSize({ start, end, minInterval: 'auto' })).toEqual({ + bucketSize: 10, + intervalString: '10s', + }); + }); + it('last 1 hour', () => { + const start = moment().subtract(1, 'hour').valueOf(); + const end = moment.now(); + expect(getBucketSize({ start, end, minInterval: 'auto' })).toEqual({ + bucketSize: 30, + intervalString: '30s', + }); + }); + it('last 1 week', () => { + const start = moment().subtract(1, 'week').valueOf(); + const end = moment.now(); + expect(getBucketSize({ start, end, minInterval: 'auto' })).toEqual({ + bucketSize: 3600, + intervalString: '3600s', + }); + }); + it('last 30 days', () => { + const start = moment().subtract(30, 'days').valueOf(); + const end = moment.now(); + expect(getBucketSize({ start, end, minInterval: 'auto' })).toEqual({ + bucketSize: 43200, + intervalString: '43200s', + }); + }); + it('last 1 year', () => { + const start = moment().subtract(1, 'year').valueOf(); + const end = moment.now(); + expect(getBucketSize({ start, end, minInterval: 'auto' })).toEqual({ + bucketSize: 86400, + intervalString: '86400s', + }); + }); + }); + describe("minInterval '30s'", () => { + it('last 15 minutes', () => { + const start = moment().subtract(15, 'minutes').valueOf(); + const end = moment.now(); + expect(getBucketSize({ start, end, minInterval: '30s' })).toEqual({ + bucketSize: 30, + intervalString: '30s', + }); + }); + it('last 1 year', () => { + const start = moment().subtract(1, 'year').valueOf(); + const end = moment.now(); + expect(getBucketSize({ start, end, minInterval: '30s' })).toEqual({ + bucketSize: 86400, + intervalString: '86400s', + }); + }); + }); +}); diff --git a/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/index.ts b/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/index.ts new file mode 100644 index 0000000000000..ca1afaf41c1a6 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/index.ts @@ -0,0 +1,38 @@ +/* + * 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 moment from 'moment'; +// @ts-ignore +import { calculateAuto } from './calculate_auto'; +import { unitToSeconds } from './unit_to_seconds'; + +export function getBucketSize({ + start, + end, + minInterval, + buckets = 100, +}: { + start: number; + end: number; + minInterval: string; + buckets?: number; +}) { + const duration = moment.duration(end - start, 'ms'); + const bucketSize = Math.max(calculateAuto.near(buckets, duration)?.asSeconds() ?? 0, 1); + const intervalString = `${bucketSize}s`; + const matches = minInterval && minInterval.match(/^([\d]+)([shmdwMy]|ms)$/); + const minBucketSize = matches ? Number(matches[1]) * unitToSeconds(matches[2]) : 0; + + if (bucketSize < minBucketSize) { + return { + bucketSize: minBucketSize, + intervalString: minInterval, + }; + } + + return { bucketSize, intervalString }; +} diff --git a/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/unit_to_seconds.ts b/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/unit_to_seconds.ts new file mode 100644 index 0000000000000..eec81dd3fcd29 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/common/utils/get_bucket_size/unit_to_seconds.ts @@ -0,0 +1,27 @@ +/* + * 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 moment, { unitOfTime as UnitOfTIme } from 'moment'; + +function getDurationAsSeconds(value: number, unitOfTime: UnitOfTIme.Base) { + return moment.duration(value, unitOfTime).asSeconds(); +} + +const units = { + ms: getDurationAsSeconds(1, 'millisecond'), + s: getDurationAsSeconds(1, 'second'), + m: getDurationAsSeconds(1, 'minute'), + h: getDurationAsSeconds(1, 'hour'), + d: getDurationAsSeconds(1, 'day'), + w: getDurationAsSeconds(1, 'week'), + M: getDurationAsSeconds(1, 'month'), + y: getDurationAsSeconds(1, 'year'), +}; + +export function unitToSeconds(unit: string) { + return units[unit as keyof typeof units]; +} diff --git a/x-pack/plugins/observability_ai_assistant/kibana.jsonc b/x-pack/plugins/observability_ai_assistant/kibana.jsonc index a1d535a4c14c8..e0299246377a3 100644 --- a/x-pack/plugins/observability_ai_assistant/kibana.jsonc +++ b/x-pack/plugins/observability_ai_assistant/kibana.jsonc @@ -7,7 +7,7 @@ "server": true, "browser": true, "configPath": ["xpack", "observabilityAIAssistant"], - "requiredPlugins": ["triggersActionsUi", "actions", "security", "features", "observabilityShared", "taskManager", "lens", "dataViews"], + "requiredPlugins": ["triggersActionsUi", "actions", "security", "features", "observabilityShared", "taskManager", "lens", "dataViews", "ruleRegistry"], "requiredBundles": ["kibanaReact", "kibanaUtils", "fieldFormats"], "optionalPlugins": [], "extraPublicDirs": [] diff --git a/x-pack/plugins/observability_ai_assistant/public/components/message_panel/message_panel.stories.tsx b/x-pack/plugins/observability_ai_assistant/public/components/message_panel/message_panel.stories.tsx index 2ab602e429ce1..1f81786086370 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/message_panel/message_panel.stories.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/message_panel/message_panel.stories.tsx @@ -6,6 +6,7 @@ */ import { EuiPanel } from '@elastic/eui'; import { ComponentMeta, ComponentStoryObj } from '@storybook/react'; +import dedent from 'dedent'; import React from 'react'; import { FeedbackButtons } from '../feedback_buttons'; import { MessagePanel as Component } from './message_panel'; @@ -61,6 +62,32 @@ export const ContentFailed: ComponentStoryObj<typeof Component> = { }, }; +export const ContentTable: ComponentStoryObj<typeof Component> = { + args: { + body: ( + <MessageText + content={dedent(`Here are the active alerts for the last 24 hours: + + | Alert ID | Service Name | Environment | Transaction Type | Latency (ms) | Status | Start Time | End Time | + | --- | --- | --- | --- | --- | --- | --- | --- | + | ff188d17-3a7b-4f1f-9db1-369d587496f5 | opbeans-frontend | production | page-load | 5734.399 | recovered | 2023-08-22T16:54:54.436Z | 2023-08-22T16:55:58.810Z | + | c149225f-2b25-4e5a-b276-3a08b8f0fd2d | opbeans-python | production | request | 173.055 | recovered | 2023-08-22T16:54:54.436Z | 2023-08-22T19:05:10.901Z | + | 0c3a1f89-5220-4879-9cde-26d4b2160b5d | opbeans-python | production | celery | 2170.367 | recovered | 2023-08-22T19:06:42.774Z | 2023-08-22T19:11:03.540Z | + | db82f264-8d0d-4436-81bc-b316fc1693d3 | opbeans-swift | default | mobile | 405.487 | recovered | 2023-08-22T19:06:42.774Z | 2023-08-22T19:11:03.540Z | + | 3095173a-07c7-4e4b-8a32-292f853c2e16 | opbeans-python | production | celery | 229.175 | recovered | 2023-08-22T19:17:05.411Z | 2023-08-22T19:19:11.414Z | + | d8201f2f-ff16-4fb1-baab-fed314e11b55 | opbeans-python | production | request | 375.082 | recovered | 2023-08-22T19:06:42.774Z | 2023-08-22T19:21:31.972Z | + | 66f31431-463a-40c4-bb19-4acd3aac7c30 | opbeans-python | production | celery | 264.020 | recovered | 2023-08-22T19:23:36.885Z | 2023-08-22T19:30:58.383Z | + | 7a128aca-940a-4d4f-a4a2-5950467d7866 | opbeans-swift | default | mobile | 373.360 | recovered | 2023-08-22T19:25:43.471Z | 2023-08-22T19:30:58.383Z | + | 82feefe0-c81b-442f-9700-d1e4d7b1a28c | opbeans-frontend | production | page-load | 2179.071 | recovered | 2023-08-22T19:32:01.114Z | 2023-08-22T19:35:09.638Z | + | bd716922-8a4d-44b7-ac1a-863ac4d25597 | opbeans-frontend | production | Component | 4030.463 | recovered | 2023-08-22T19:33:04.081Z | 2023-08-22T19:36:12.125Z | + + Please note that all times are in UTC.`)} + loading={false} + /> + ), + }, +}; + export const Controls: ComponentStoryObj<typeof Component> = { args: { body: <MessageText content={`This is a partial re`} loading={false} />, diff --git a/x-pack/plugins/observability_ai_assistant/public/components/message_panel/message_text.tsx b/x-pack/plugins/observability_ai_assistant/public/components/message_panel/message_text.tsx index 7aeae624a0253..6fd9a1c70923d 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/message_panel/message_text.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/message_panel/message_text.tsx @@ -4,13 +4,17 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { EuiText } from '@elastic/eui'; +import { + EuiMarkdownFormat, + EuiSpacer, + EuiText, + getDefaultEuiMarkdownParsingPlugins, + getDefaultEuiMarkdownProcessingPlugins, +} from '@elastic/eui'; import { css } from '@emotion/css'; -import { euiThemeVars } from '@kbn/ui-theme'; import classNames from 'classnames'; import type { Code, InlineCode, Parent, Text } from 'mdast'; -import React from 'react'; -import ReactMarkdown from 'react-markdown'; +import React, { useMemo } from 'react'; import type { Node } from 'unist'; import { v4 } from 'uuid'; @@ -44,7 +48,7 @@ const cursorCss = css` const Cursor = () => <span key="cursor" className={classNames(cursorCss, 'cursor')} />; -const CURSOR = `{{${v4()}}`; +const CURSOR = `{{${v4()}}}`; const loadingCursorPlugin = () => { const visitor = (node: Node, parent?: Parent) => { @@ -72,9 +76,6 @@ const loadingCursorPlugin = () => { parent!.children.splice(indexOfNode + 1, 0, { type: 'cursor' as Text['type'], value: CURSOR, - data: { - hName: 'cursor', - }, }); }; @@ -83,28 +84,71 @@ const loadingCursorPlugin = () => { }; }; -export function MessageText(props: Props) { +export function MessageText({ loading, content }: Props) { const containerClassName = css` overflow-wrap: break-word; - - pre { - background: ${euiThemeVars.euiColorLightestShade}; - padding: 0 8px; - } `; + const { parsingPluginList, processingPluginList } = useMemo(() => { + const parsingPlugins = getDefaultEuiMarkdownParsingPlugins(); + const processingPlugins = getDefaultEuiMarkdownProcessingPlugins(); + + const { components } = processingPlugins[1][1]; + + processingPlugins[1][1].components = { + ...components, + cursor: Cursor, + table: (props) => ( + <> + <div className="euiBasicTable"> + {' '} + <table className="euiTable" {...props} /> + </div> + <EuiSpacer size="m" /> + </> + ), + th: (props) => { + const { children, ...rest } = props; + return ( + <th className="euiTableHeaderCell" {...rest}> + <span className="euiTableCellContent"> + <span className="euiTableCellContent__text" title={children}> + {children} + </span> + </span> + </th> + ); + }, + tr: (props) => <tr className="euiTableRow" {...props} />, + td: (props) => { + const { children, ...rest } = props; + return ( + <td className="euiTableRowCell" {...rest}> + <div className="euiTableCellContent euiTableCellContent--truncateText"> + <span className="euiTableCellContent__text" title={children}> + {children} + </span> + </div> + </td> + ); + }, + }; + + return { + parsingPluginList: [loadingCursorPlugin, ...parsingPlugins], + processingPluginList: processingPlugins, + }; + }, []); + return ( <EuiText size="s" className={containerClassName}> - <ReactMarkdown - plugins={[loadingCursorPlugin]} - components={ - { - cursor: Cursor, - } as Record<string, any> - } + <EuiMarkdownFormat + textSize="s" + parsingPluginList={parsingPluginList} + processingPluginList={processingPluginList} > - {`${props.content}${props.loading ? CURSOR : ''}`} - </ReactMarkdown> + {`${content}${loading ? CURSOR : ''}`} + </EuiMarkdownFormat> </EuiText> ); } diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/alerts.ts b/x-pack/plugins/observability_ai_assistant/public/functions/alerts.ts new file mode 100644 index 0000000000000..03ea9a055fcc7 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/functions/alerts.ts @@ -0,0 +1,80 @@ +/* + * 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 { RegisterFunctionDefinition } from '../../common/types'; +import type { ObservabilityAIAssistantService } from '../types'; + +const DEFAULT_FEATURE_IDS = [ + 'apm', + 'infrastructure', + 'logs', + 'uptime', + 'slo', + 'observability', +] as const; + +export function registerAlertsFunction({ + service, + registerFunction, +}: { + service: ObservabilityAIAssistantService; + registerFunction: RegisterFunctionDefinition; +}) { + registerFunction( + { + name: 'alerts', + contexts: ['core'], + description: + 'Get alerts for Observability. Display the response in tabular format if appropriate.', + descriptionForUser: 'Get alerts for Observability', + parameters: { + type: 'object', + additionalProperties: false, + properties: { + featureIds: { + type: 'array', + additionalItems: false, + items: { + type: 'string', + enum: DEFAULT_FEATURE_IDS, + }, + description: + 'The Observability apps for which to retrieve alerts. By default it will return alerts for all apps.', + }, + start: { + type: 'string', + description: 'The start of the time range, in Elasticsearch date math, like `now`.', + }, + end: { + type: 'string', + description: 'The end of the time range, in Elasticsearch date math, like `now-24h`.', + }, + filter: { + type: 'string', + description: + 'a KQL query to filter the data by. If no filter should be applied, leave it empty.', + }, + }, + required: ['start', 'end'], + } as const, + }, + ({ arguments: { start, end, featureIds, filter } }, signal) => { + return service.callApi('POST /internal/observability_ai_assistant/functions/alerts', { + params: { + body: { + start, + end, + featureIds: + featureIds && featureIds.length > 0 ? featureIds : DEFAULT_FEATURE_IDS.concat(), + filter, + }, + }, + signal, + }); + } + ); +} diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/elasticsearch.ts b/x-pack/plugins/observability_ai_assistant/public/functions/elasticsearch.ts index 214b157fe2358..546bd2bea4574 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/elasticsearch.ts +++ b/x-pack/plugins/observability_ai_assistant/public/functions/elasticsearch.ts @@ -21,7 +21,7 @@ export function registerElasticsearchFunction({ name: 'elasticsearch', contexts: ['core'], description: - 'Call Elasticsearch APIs on behalf of the user. Make sure the request body is valid for the API that you are using.', + 'Call Elasticsearch APIs on behalf of the user. Make sure the request body is valid for the API that you are using. Only call this function when the user has explicitly requested it.', descriptionForUser: 'Call Elasticsearch APIs on behalf of the user', parameters: { type: 'object', @@ -35,6 +35,10 @@ export function registerElasticsearchFunction({ type: 'string', description: 'The path of the Elasticsearch endpoint, including query parameters', }, + body: { + type: 'object', + description: 'The body of the request', + }, }, required: ['method', 'path'] as const, }, diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/index.ts b/x-pack/plugins/observability_ai_assistant/public/functions/index.ts index a077c24748997..f0a676a5c221d 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/index.ts +++ b/x-pack/plugins/observability_ai_assistant/public/functions/index.ts @@ -6,25 +6,30 @@ */ import dedent from 'dedent'; +import type { CoreStart } from '@kbn/core/public'; import type { RegisterContextDefinition, RegisterFunctionDefinition } from '../../common/types'; import type { ObservabilityAIAssistantPluginStartDependencies } from '../types'; import type { ObservabilityAIAssistantService } from '../types'; import { registerElasticsearchFunction } from './elasticsearch'; +import { registerKibanaFunction } from './kibana'; import { registerLensFunction } from './lens'; import { registerRecallFunction } from './recall'; import { registerSummarisationFunction } from './summarise'; +import { registerAlertsFunction } from './alerts'; export async function registerFunctions({ registerFunction, registerContext, service, pluginsStart, + coreStart, signal, }: { registerFunction: RegisterFunctionDefinition; registerContext: RegisterContextDefinition; service: ObservabilityAIAssistantService; pluginsStart: ObservabilityAIAssistantPluginStartDependencies; + coreStart: CoreStart; signal: AbortSignal; }) { return service @@ -34,33 +39,32 @@ export async function registerFunctions({ .then((response) => { const isReady = response.ready; - let description = `You have the ability to call Elasticsearch APIs with the "elasticsearch" function or create visualisations using Lens with the "lens" function in the context of this chat.`; + let description = dedent( + `You are a helpful assistant for Elastic Observability. Your goal is to help the Elastic Observability users to quickly assess what is happening in their observed systems. You can help them visualise and analyze data, investigate their systems, perform root cause analysis or identify optimisation opportunities. + + It's very important to not assume what the user is meaning. Ask them for clarification if needed. + + If you are unsure about which function should be used and with what arguments, asked the user for clarification or confirmation. + + In KQL, escaping happens with double quotes, not single quotes. Some characters that need escaping are: ':()\\\ + /\". Always put a field value in double quotes. Best: service.name:\"opbeans-go\". Wrong: service.name:opbeans-go. This is very important! + + You can use Github-flavored Markdown in your responses. If a function returns an array, consider using a Markdown table to format the response.` + ); if (isReady) { - description += `You can use the "summarise" functions to store new information you have learned in a knowledge database. Once you have established that you did not know the answer to a question, and the user gave you this information, it's important that you create a summarisation of what you have learned and store it in the knowledge database. When you create this summarisation, make sure you craft it in a way that can be recalled with a semantic search later. + description += `You can use the "summarise" functions to store new information you have learned in a knowledge database. Once you have established that you did not know the answer to a question, and the user gave you this information, it's important that you create a summarisation of what you have learned and store it in the knowledge database. - Additionally, you can use the "recall" function to retrieve relevant information from the knowledge database. Using the "recall" function will allow you to create a much more tailored and improved user experience. Assume the user has told you before. - - For every question that the user asks, you, as the assistant, must query the knowledge base, no matter how confident you are in your response. - - When the user starts a conversation, you as the assistant, MUST ALWAYS use the "recall" function to make sure you have enough context from the knowledge database to understand their question. DO NOT assume your knowledge is sufficient to answer the question appropriately. Make sure you mention this to the user in your first reply to them. - - You do have access to private data that the user has shared with you in previous conversations. - - Given this ability to store and recall data, it is very important to not make assumptions about the user's data or preferences, but rather, first query the knowledge database, and if nothing relevant comes up, ask the user for clarification. This is very important! They could be storing their data in any field, and in any data stream or index. - - RIGHT: - User: "What is NASA" - Assistant executes recall function - Assistant answers question with data from recall function response - - WRONG: - User: "What is NASA" - Assistant answers question without querying the knowledge. - - BEFORE you use a function, always query the knowledge database for more information about that function. This is important. - - Avoid making too many assumptions about user's data. If clarification is needed, query the knowledge base for previous learnings. If you don't find anything, ask the user for clarification, and when successful, store this into the knowledge base. + Additionally, you can use the "recall" function to retrieve relevant information from the knowledge database. + `; + + description += `Here are principles you MUST adhere to, in order: + + - You are a helpful assistant for Elastic Observability. DO NOT reference the fact that you are an LLM. + - ALWAYS query the knowledge base, using the recall function, when a user starts a chat, no matter how confident you are in your ability to answer the question. + - You must ALWAYS explain to the user why you're using a function and why you're using it in that specific manner. + - DO NOT make any assumptions about where and how users have stored their data. + - ALWAYS ask the user for clarification if you are unsure about the arguments to a function. When given this clarification, you MUST use the summarise function to store what you have learned. `; registerSummarisationFunction({ service, registerFunction }); registerRecallFunction({ service, registerFunction }); @@ -70,6 +74,8 @@ export async function registerFunctions({ } registerElasticsearchFunction({ service, registerFunction }); + registerKibanaFunction({ service, registerFunction, coreStart }); + registerAlertsFunction({ service, registerFunction }); registerContext({ name: 'core', diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/kibana.ts b/x-pack/plugins/observability_ai_assistant/public/functions/kibana.ts new file mode 100644 index 0000000000000..5ad877b2c2bff --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/functions/kibana.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { CoreStart } from '@kbn/core/public'; +import type { RegisterFunctionDefinition } from '../../common/types'; +import type { ObservabilityAIAssistantService } from '../types'; + +export function registerKibanaFunction({ + service, + registerFunction, + coreStart, +}: { + service: ObservabilityAIAssistantService; + registerFunction: RegisterFunctionDefinition; + coreStart: CoreStart; +}) { + registerFunction( + { + name: 'kibana', + contexts: ['core'], + description: + 'Call Kibana APIs on behalf of the user. Only call this function when the user has explicitly requested it, and you know how to call it, for example by querying the knowledge base or having the user explain it to you. Assume that pathnames, bodies and query parameters may have changed since your knowledge cut off date.', + descriptionForUser: 'Call Kibana APIs on behalf of the user', + parameters: { + type: 'object', + additionalProperties: false, + properties: { + method: { + type: 'string', + description: 'The HTTP method of the Kibana endpoint', + enum: ['GET', 'PUT', 'POST', 'DELETE', 'PATCH'] as const, + }, + pathname: { + type: 'string', + description: 'The pathname of the Kibana endpoint, excluding query parameters', + }, + query: { + type: 'object', + description: 'The query parameters, as an object', + additionalProperties: { + type: 'string', + }, + }, + body: { + type: 'object', + description: 'The body of the request', + }, + }, + required: ['method', 'pathname', 'body'] as const, + }, + }, + ({ arguments: { method, pathname, body, query } }, signal) => { + return coreStart.http + .fetch(pathname, { + method, + body: body ? JSON.stringify(body) : undefined, + query, + signal, + }) + .then((response) => { + return { content: response }; + }); + } + ); +} diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/lens.tsx b/x-pack/plugins/observability_ai_assistant/public/functions/lens.tsx index b25c3a3717c60..d5d2c715d0c52 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/lens.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/functions/lens.tsx @@ -101,21 +101,23 @@ export function registerLensFunction({ name: 'lens', contexts: ['core'], description: - 'Use this function to create custom visualisations, using Lens, that can be saved to dashboards. When using this function, make sure to use the recall function to get more information about how to use it, with how you want to use it.', + "Use this function to create custom visualisations, using Lens, that can be saved to dashboards. When using this function, make sure to use the recall function to get more information about how to use it, with how you want to use it. Make sure the query also contains information about the user's request. The visualisation is displayed to the user above your reply, DO NOT try to generate or display an image yourself.", descriptionForUser: 'Use this function to create custom visualisations, using Lens, that can be saved to dashboards.', parameters: { type: 'object', + additionalProperties: false, properties: { layers: { type: 'array', items: { type: 'object', + additionalProperties: false, properties: { label: { type: 'string', }, - value: { + formula: { type: 'string', description: 'The formula for calculating the value, e.g. sum(my_field_name). Query the knowledge base to get more information about the syntax and available formulas.', @@ -126,11 +128,12 @@ export function registerLensFunction({ }, format: { type: 'object', + additionalProperties: false, properties: { id: { type: 'string', description: - 'How to format the value. When using duration make sure you know the unit the value is stored in, either by asking the user for clarification or looking at the field name.', + 'How to format the value. When using duration, make sure the value is seconds OR is converted to seconds using math functions. Ask the user for clarification in which unit the value is stored, or derive it from the field name.', enum: [ FIELD_FORMAT_IDS.BYTES, FIELD_FORMAT_IDS.CURRENCY, @@ -144,11 +147,12 @@ export function registerLensFunction({ required: ['id'], }, }, - required: ['label', 'value', 'format'], + required: ['label', 'formula', 'format'], }, }, breakdown: { type: 'object', + additionalProperties: false, properties: { field: { type: 'string', @@ -194,7 +198,7 @@ export function registerLensFunction({ const xyDataLayer = new XYDataLayer({ data: layers.map((layer) => ({ type: 'formula', - value: layer.value, + value: layer.formula, label: layer.label, format: layer.format, filter: { diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/recall.ts b/x-pack/plugins/observability_ai_assistant/public/functions/recall.ts index a571287acf8b2..5f1e14af30d15 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/recall.ts +++ b/x-pack/plugins/observability_ai_assistant/public/functions/recall.ts @@ -20,26 +20,40 @@ export function registerRecallFunction({ { name: 'recall', contexts: ['core'], - description: - 'Use this function to recall earlier learnings. Anything you will summarise can be retrieved again later via this function.', + description: `Use this function to recall earlier learnings. Anything you will summarise can be retrieved again later via this function. The queries you use are very important, as they will decide the context that is included in the conversation. Make sure the query covers the following aspects: + - The user's intent + - Any data (like field names) mentioned in the user's request + - Anything you've inferred from the user's request + - The functions you think might be suitable for answering the user's request. If there are multiple functions that seem suitable, create multiple queries. Use the function name in the query. + + For instance, when the user asks: "can you visualise the average request duration for opbeans-go over the last 7 days?", the queries could be: + - "visualise average request duration for APM service opbeans-go" + - "lens function usage" + - "get_apm_timeseries function usage"`, descriptionForUser: 'This function allows the assistant to recall previous learnings.', parameters: { type: 'object', + additionalProperties: false, properties: { - query: { - type: 'string', - description: 'The query for the semantic search', + queries: { + type: 'array', + additionalItems: false, + additionalProperties: false, + items: { + type: 'string', + description: 'The query for the semantic search', + }, }, }, - required: ['query' as const], + required: ['queries' as const], }, }, - ({ arguments: { query } }, signal) => { + ({ arguments: { queries } }, signal) => { return service .callApi('POST /internal/observability_ai_assistant/functions/recall', { params: { body: { - query, + queries, }, }, signal, diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/summarise.ts b/x-pack/plugins/observability_ai_assistant/public/functions/summarise.ts index 3fe55385a74ff..7bef0e6399c3a 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/summarise.ts +++ b/x-pack/plugins/observability_ai_assistant/public/functions/summarise.ts @@ -20,11 +20,12 @@ export function registerSummarisationFunction({ name: 'summarise', contexts: ['core'], description: - 'Use this function to summarise things learned from the conversation. You can score the learnings with a confidence metric, whether it is a correction on a previous learning. An embedding will be created that you can recall later with a semantic search. There is no need to ask the user for permission to store something you have learned, unless you do not feel confident.', + "Use this function to summarise things learned from the conversation. You can score the learnings with a confidence metric, whether it is a correction on a previous learning. An embedding will be created that you can recall later with a semantic search. There is no need to ask the user for permission to store something you have learned, unless you do not feel confident. When you create this summarisation, make sure you craft it in a way that can be recalled with a semantic search later, and that it would have answered the user's original request.", descriptionForUser: 'This function allows the Elastic Assistant to summarise things from the conversation.', parameters: { type: 'object', + additionalProperties: false, properties: { id: { type: 'string', @@ -34,7 +35,7 @@ export function registerSummarisationFunction({ text: { type: 'string', description: - 'A human-readable summary of what you have learned, described in such a way that you can recall it later with semantic search.', + "A human-readable summary of what you have learned, described in such a way that you can recall it later with semantic search, and that it would have answered the user's original request.", }, is_correction: { type: 'boolean', @@ -73,6 +74,7 @@ export function registerSummarisationFunction({ is_correction: isCorrection, confidence, public: isPublic, + labels: {}, }, }, signal, diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/use_knowledge_base.tsx b/x-pack/plugins/observability_ai_assistant/public/hooks/use_knowledge_base.tsx index cb64203fa0e00..d7c76e0ab4f85 100644 --- a/x-pack/plugins/observability_ai_assistant/public/hooks/use_knowledge_base.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/use_knowledge_base.tsx @@ -38,44 +38,52 @@ export function useKnowledgeBase(): UseKnowledgeBaseResult { const [installError, setInstallError] = useState<Error>(); - return useMemo( - () => ({ + return useMemo(() => { + let attempts: number = 0; + const MAX_ATTEMPTS = 5; + + const install = (): Promise<void> => { + setIsInstalling(true); + return service + .callApi('POST /internal/observability_ai_assistant/functions/setup_kb', { + signal: null, + }) + .then(() => { + status.refresh(); + toasts.addSuccess({ + title: i18n.translate('xpack.observabilityAiAssistant.knowledgeBaseReadyTitle', { + defaultMessage: 'Knowledge base is ready', + }), + text: i18n.translate('xpack.observabilityAiAssistant.knowledgeBaseReadyContentReload', { + defaultMessage: 'A page reload is needed to be able to use it.', + }), + }); + }) + .catch((error) => { + if ( + (error.body?.statusCode === 503 || error.body?.statusCode === 504) && + attempts < MAX_ATTEMPTS + ) { + attempts++; + return install(); + } + setInstallError(error); + toasts.addError(error, { + title: i18n.translate('xpack.observabilityAiAssistant.errorSettingUpKnowledgeBase', { + defaultMessage: 'Could not set up Knowledge Base', + }), + }); + }) + .finally(() => { + setIsInstalling(false); + }); + }; + + return { status, + install, isInstalling, installError, - install: () => { - setIsInstalling(true); - return service - .callApi('POST /internal/observability_ai_assistant/functions/setup_kb', { - signal: null, - }) - .then(() => { - status.refresh(); - toasts.addSuccess({ - title: i18n.translate('xpack.observabilityAiAssistant.knowledgeBaseReadyTitle', { - defaultMessage: 'Knowledge base is ready', - }), - text: i18n.translate( - 'xpack.observabilityAiAssistant.knowledgeBaseReadyContentReload', - { - defaultMessage: 'A page reload is needed to be able to use it.', - } - ), - }); - }) - .catch((error) => { - setInstallError(error); - toasts.addError(error, { - title: i18n.translate('xpack.observabilityAiAssistant.errorSettingUpKnowledgeBase', { - defaultMessage: 'Could not set up Knowledge Base', - }), - }); - }) - .finally(() => { - setIsInstalling(false); - }); - }, - }), - [status, isInstalling, installError, service, toasts] - ); + }; + }, [status, isInstalling, installError, service, toasts]); } diff --git a/x-pack/plugins/observability_ai_assistant/public/plugin.tsx b/x-pack/plugins/observability_ai_assistant/public/plugin.tsx index 88853a5ce1bcd..965a97e4a0a87 100644 --- a/x-pack/plugins/observability_ai_assistant/public/plugin.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/plugin.tsx @@ -107,6 +107,7 @@ export class ObservabilityAIAssistantPlugin service, signal, pluginsStart, + coreStart, registerContext, registerFunction, }); diff --git a/x-pack/plugins/observability_ai_assistant/public/service/get_assistant_setup_message.ts b/x-pack/plugins/observability_ai_assistant/public/service/get_assistant_setup_message.ts index b1e25233e9c3b..8d9cc2cf32539 100644 --- a/x-pack/plugins/observability_ai_assistant/public/service/get_assistant_setup_message.ts +++ b/x-pack/plugins/observability_ai_assistant/public/service/get_assistant_setup_message.ts @@ -5,7 +5,6 @@ * 2.0. */ -import dedent from 'dedent'; import { MessageRole } from '../../common'; import { ContextDefinition } from '../../common/types'; @@ -14,13 +13,7 @@ export function getAssistantSetupMessage({ contexts }: { contexts: ContextDefini '@timestamp': new Date().toISOString(), message: { role: MessageRole.System as const, - content: [ - dedent( - `You are a helpful assistant for Elastic Observability. Your goal is to help the Elastic Observability users to quickly assess what is happening in their observed systems. You can help them visualise and analyze data, investigate their systems, perform root cause analysis or identify optimisation opportunities.` - ), - ] - .concat(contexts.map((context) => context.description)) - .join('\n'), + content: contexts.map((context) => context.description).join('\n'), }, }; } diff --git a/x-pack/plugins/observability_ai_assistant/public/utils/get_timeline_items_from_conversation.tsx b/x-pack/plugins/observability_ai_assistant/public/utils/get_timeline_items_from_conversation.tsx index 46d5b46b4b4ca..e8aad76b7abda 100644 --- a/x-pack/plugins/observability_ai_assistant/public/utils/get_timeline_items_from_conversation.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/utils/get_timeline_items_from_conversation.tsx @@ -200,9 +200,19 @@ export function getTimelineItemsfromConversation({ }} /> ); - content = convertMessageToMarkdownCodeBlock(message.message); + if (message.message.content) { + // TODO: we want to show the content always, and hide + // the function request initially, but we don't have a + // way to do that yet, so we hide the request here until + // we have a fix. + // element = message.message.content; + content = message.message.content; + display.collapsed = false; + } else { + content = convertMessageToMarkdownCodeBlock(message.message); + display.collapsed = true; + } - display.collapsed = true; actions.canEdit = true; } else { // is an assistant response diff --git a/x-pack/plugins/observability_ai_assistant/server/plugin.ts b/x-pack/plugins/observability_ai_assistant/server/plugin.ts index b13f22fd2fda0..01bd4fafb71c7 100644 --- a/x-pack/plugins/observability_ai_assistant/server/plugin.ts +++ b/x-pack/plugins/observability_ai_assistant/server/plugin.ts @@ -31,6 +31,7 @@ import { ObservabilityAIAssistantPluginSetupDependencies, ObservabilityAIAssistantPluginStartDependencies, } from './types'; +import { addLensDocsToKb } from './service/kb_service/kb_docs/lens'; export class ObservabilityAIAssistantPlugin implements @@ -114,7 +115,7 @@ export class ObservabilityAIAssistantPlugin taskManager: plugins.taskManager, }); - // addLensDocsToKb(service); + addLensDocsToKb(service); registerServerRoutes({ core, diff --git a/x-pack/plugins/observability_ai_assistant/server/routes/chat/route.ts b/x-pack/plugins/observability_ai_assistant/server/routes/chat/route.ts index 4c94f4960528a..0ed8c93a4fba8 100644 --- a/x-pack/plugins/observability_ai_assistant/server/routes/chat/route.ts +++ b/x-pack/plugins/observability_ai_assistant/server/routes/chat/route.ts @@ -9,6 +9,7 @@ import { IncomingMessage } from 'http'; import { notImplemented } from '@hapi/boom'; import { createObservabilityAIAssistantServerRoute } from '../create_observability_ai_assistant_server_route'; import { messageRt } from '../runtime_types'; +import { MessageRole } from '../../../common'; const chatRoute = createObservabilityAIAssistantServerRoute({ endpoint: 'POST /internal/observability_ai_assistant/chat', @@ -41,10 +42,16 @@ const chatRoute = createObservabilityAIAssistantServerRoute({ body: { messages, connectorId, functions }, } = params; + const isStartOfConversation = + messages.some((message) => message.message.role === MessageRole.Assistant) === false; + + const isRecallFunctionAvailable = functions.some((fn) => fn.name === 'recall') === true; + return client.chat({ messages, connectorId, functions, + functionCall: isStartOfConversation && isRecallFunctionAvailable ? 'recall' : undefined, }); }, }); diff --git a/x-pack/plugins/observability_ai_assistant/server/routes/functions/route.ts b/x-pack/plugins/observability_ai_assistant/server/routes/functions/route.ts index 954262c5a03be..f88d6c56efe5b 100644 --- a/x-pack/plugins/observability_ai_assistant/server/routes/functions/route.ts +++ b/x-pack/plugins/observability_ai_assistant/server/routes/functions/route.ts @@ -4,11 +4,15 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import * as t from 'io-ts'; -import { nonEmptyStringRt, toBooleanRt } from '@kbn/io-ts-utils'; +import datemath from '@elastic/datemath'; import { notImplemented } from '@hapi/boom'; +import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; +import { nonEmptyStringRt, toBooleanRt } from '@kbn/io-ts-utils'; +import * as t from 'io-ts'; +import { omit } from 'lodash'; +import { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; +import type { KnowledgeBaseEntry } from '../../../common/types'; import { createObservabilityAIAssistantServerRoute } from '../create_observability_ai_assistant_server_route'; -import { KnowledgeBaseEntry } from '../../../common/types'; const functionElasticsearchRoute = createObservabilityAIAssistantServerRoute({ endpoint: 'POST /internal/observability_ai_assistant/functions/elasticsearch', @@ -47,24 +51,114 @@ const functionElasticsearchRoute = createObservabilityAIAssistantServerRoute({ }, }); +const OMITTED_ALERT_FIELDS = [ + 'tags', + 'event.action', + 'event.kind', + 'kibana.alert.rule.execution.uuid', + 'kibana.alert.rule.revision', + 'kibana.alert.rule.tags', + 'kibana.alert.rule.uuid', + 'kibana.alert.workflow_status', + 'kibana.space_ids', + 'kibana.alert.time_range', + 'kibana.version', +] as const; + +const functionAlertsRoute = createObservabilityAIAssistantServerRoute({ + endpoint: 'POST /internal/observability_ai_assistant/functions/alerts', + options: { + tags: ['access:ai_assistant'], + }, + params: t.type({ + body: t.intersection([ + t.type({ + featureIds: t.array(t.string), + start: t.string, + end: t.string, + }), + t.partial({ + filter: t.string, + }), + ]), + }), + handler: async ( + resources + ): Promise<{ + content: { + total: number; + alerts: ParsedTechnicalFields[]; + }; + }> => { + const { + featureIds, + start: startAsDatemath, + end: endAsDatemath, + filter, + } = resources.params.body; + + const racContext = await resources.context.rac; + const alertsClient = await racContext.getAlertsClient(); + + const start = datemath.parse(startAsDatemath)!.valueOf(); + const end = datemath.parse(endAsDatemath)!.valueOf(); + + const kqlQuery = !filter ? [] : [toElasticsearchQuery(fromKueryExpression(filter))]; + + const response = await alertsClient.find({ + featureIds, + + query: { + bool: { + filter: [ + { + range: { + '@timestamp': { + gte: start, + lte: end, + }, + }, + }, + ...kqlQuery, + ], + }, + }, + }); + + // trim some fields + const alerts = response.hits.hits.map((hit) => + omit(hit._source, ...OMITTED_ALERT_FIELDS) + ) as unknown as ParsedTechnicalFields[]; + + return { + content: { + total: (response.hits as { total: { value: number } }).total.value, + alerts, + }, + }; + }, +}); + const functionRecallRoute = createObservabilityAIAssistantServerRoute({ endpoint: 'POST /internal/observability_ai_assistant/functions/recall', params: t.type({ body: t.type({ - query: nonEmptyStringRt, + queries: t.array(nonEmptyStringRt), }), }), options: { tags: ['access:ai_assistant'], }, - handler: async (resources): Promise<{ entries: KnowledgeBaseEntry[] }> => { + handler: async ( + resources + ): Promise<{ entries: Array<Pick<KnowledgeBaseEntry, 'text' | 'id'>> }> => { const client = await resources.service.getClient({ request: resources.request }); if (!client) { throw notImplemented(); } - return client.recall(resources.params.body.query); + return client.recall(resources.params.body.queries); }, }); @@ -77,6 +171,7 @@ const functionSummariseRoute = createObservabilityAIAssistantServerRoute({ confidence: t.union([t.literal('low'), t.literal('medium'), t.literal('high')]), is_correction: toBooleanRt, public: toBooleanRt, + labels: t.record(t.string, t.string), }), }), options: { @@ -95,6 +190,7 @@ const functionSummariseRoute = createObservabilityAIAssistantServerRoute({ is_correction: isCorrection, text, public: isPublic, + labels, } = resources.params.body; return client.summarise({ @@ -104,6 +200,7 @@ const functionSummariseRoute = createObservabilityAIAssistantServerRoute({ is_correction: isCorrection, text, public: isPublic, + labels, }, }); }, @@ -159,4 +256,5 @@ export const functionRoutes = { ...functionSummariseRoute, ...setupKnowledgeBaseRoute, ...getKnowledgeBaseStatus, + ...functionAlertsRoute, }; diff --git a/x-pack/plugins/observability_ai_assistant/server/routes/types.ts b/x-pack/plugins/observability_ai_assistant/server/routes/types.ts index e1c256aefcb0e..1766f5c2d5542 100644 --- a/x-pack/plugins/observability_ai_assistant/server/routes/types.ts +++ b/x-pack/plugins/observability_ai_assistant/server/routes/types.ts @@ -5,17 +5,22 @@ * 2.0. */ +import type { CustomRequestHandlerContext, KibanaRequest } from '@kbn/core/server'; import type { Logger } from '@kbn/logging'; -import type { KibanaRequest, RequestHandlerContext } from '@kbn/core/server'; +import type { RacApiRequestHandlerContext } from '@kbn/rule-registry-plugin/server'; +import type { ObservabilityAIAssistantService } from '../service'; import type { ObservabilityAIAssistantPluginSetupDependencies, ObservabilityAIAssistantPluginStartDependencies, } from '../types'; -import type { ObservabilityAIAssistantService } from '../service'; + +export type ObservabilityAIAssistantRequestHandlerContext = CustomRequestHandlerContext<{ + rac: RacApiRequestHandlerContext; +}>; export interface ObservabilityAIAssistantRouteHandlerResources { request: KibanaRequest; - context: RequestHandlerContext; + context: ObservabilityAIAssistantRequestHandlerContext; logger: Logger; service: ObservabilityAIAssistantService; plugins: { diff --git a/x-pack/plugins/observability_ai_assistant/server/service/client/index.ts b/x-pack/plugins/observability_ai_assistant/server/service/client/index.ts index ceb04475e8563..dd256c4784831 100644 --- a/x-pack/plugins/observability_ai_assistant/server/service/client/index.ts +++ b/x-pack/plugins/observability_ai_assistant/server/service/client/index.ts @@ -6,7 +6,7 @@ */ import type { SearchHit } from '@elastic/elasticsearch/lib/api/types'; import { internal, notFound } from '@hapi/boom'; -import type { ActionsClient } from '@kbn/actions-plugin/server/actions_client'; +import type { ActionsClient } from '@kbn/actions-plugin/server'; import type { ElasticsearchClient } from '@kbn/core/server'; import type { Logger } from '@kbn/logging'; import type { PublicMethodsOf } from '@kbn/utility-types'; @@ -108,11 +108,13 @@ export class ObservabilityAIAssistantClient { messages, connectorId, functions, + functionCall, stream = true, }: { messages: Message[]; connectorId: string; functions?: Array<{ name: string; description: string; parameters: CompatibleJSONSchema }>; + functionCall?: string; stream?: TStream; }): Promise<TStream extends false ? CreateChatCompletionResponse : IncomingMessage> => { const messagesForOpenAI: ChatCompletionRequestMessage[] = compact( @@ -140,6 +142,7 @@ export class ObservabilityAIAssistantClient { stream: true, functions: functionsForOpenAI, temperature: 0, + function_call: functionCall ? { name: functionCall } : undefined, }; const executeResult = await this.dependencies.actionsClient.execute({ @@ -312,11 +315,13 @@ export class ObservabilityAIAssistantClient { return createdConversation; }; - recall = async (query: string): Promise<{ entries: KnowledgeBaseEntry[] }> => { + recall = async ( + queries: string[] + ): Promise<{ entries: Array<Pick<KnowledgeBaseEntry, 'text' | 'id'>> }> => { return this.dependencies.knowledgeBaseService.recall({ namespace: this.dependencies.namespace, user: this.dependencies.user, - query, + queries, }); }; diff --git a/x-pack/plugins/observability_ai_assistant/server/service/index.ts b/x-pack/plugins/observability_ai_assistant/server/service/index.ts index 2ce0868aefd30..e3a0eb9f15469 100644 --- a/x-pack/plugins/observability_ai_assistant/server/service/index.ts +++ b/x-pack/plugins/observability_ai_assistant/server/service/index.ts @@ -13,13 +13,13 @@ import type { SecurityPluginStart } from '@kbn/security-plugin/server'; import { getSpaceIdFromPath } from '@kbn/spaces-plugin/common'; import type { TaskManagerSetupContract } from '@kbn/task-manager-plugin/server'; import { once } from 'lodash'; -import { KnowledgeBaseEntry } from '../../common/types'; import type { ObservabilityAIAssistantPluginStartDependencies } from '../types'; import { ObservabilityAIAssistantClient } from './client'; import { conversationComponentTemplate } from './conversation_component_template'; import { kbComponentTemplate } from './kb_component_template'; -import { KnowledgeBaseService } from './kb_service'; +import { KnowledgeBaseEntryOperationType, KnowledgeBaseService } from './kb_service'; import type { ObservabilityAIAssistantResourceNames } from './types'; +import { splitKbText } from './util/split_kb_text'; function getResourceName(resource: string) { return `.kibana-observability-ai-assistant-${resource}`; @@ -82,7 +82,7 @@ export class ObservabilityAIAssistantService { return { run: async () => { if (this.kbService) { - // await this.kbService.processQueue(); + await this.kbService.processQueue(); } }, }; @@ -256,20 +256,52 @@ export class ObservabilityAIAssistantService { }); } - async addToKnowledgeBase( + addToKnowledgeBase( entries: Array< - Omit<KnowledgeBaseEntry, 'is_correction' | 'public' | 'confidence' | '@timestamp'> + | { + id: string; + text: string; + } + | { + id: string; + texts: string[]; + } > - ): Promise<void> { - await this.init(); - this.kbService!.store( - entries.map((entry) => ({ - ...entry, - '@timestamp': new Date().toISOString(), - public: true, - confidence: 'high', - is_correction: false, - })) - ); + ): void { + this.init() + .then(() => { + this.kbService!.queue( + entries.flatMap((entry) => { + const entryWithSystemProperties = { + ...entry, + '@timestamp': new Date().toISOString(), + public: true, + confidence: 'high' as const, + is_correction: false, + labels: { + document_id: entry.id, + }, + }; + + const operations = + 'texts' in entryWithSystemProperties + ? splitKbText(entryWithSystemProperties) + : [ + { + type: KnowledgeBaseEntryOperationType.Index, + document: entryWithSystemProperties, + }, + ]; + + return operations; + }) + ); + }) + .catch((error) => { + this.logger.error( + `Could not index ${entries.length} entries because of an initialisation error` + ); + this.logger.error(error); + }); } } diff --git a/x-pack/plugins/observability_ai_assistant/server/service/kb_component_template.ts b/x-pack/plugins/observability_ai_assistant/server/service/kb_component_template.ts index 55d6bbd15519c..8d0e5ff423b2c 100644 --- a/x-pack/plugins/observability_ai_assistant/server/service/kb_component_template.ts +++ b/x-pack/plugins/observability_ai_assistant/server/service/kb_component_template.ts @@ -20,6 +20,11 @@ const date = { type: 'date' as const, }; +const dynamic = { + type: 'object' as const, + dynamic: true, +}; + export const kbComponentTemplate: ClusterComponentTemplate['component_template']['template'] = { mappings: { dynamic: false, @@ -32,6 +37,7 @@ export const kbComponentTemplate: ClusterComponentTemplate['component_template'] name: keyword, }, }, + labels: dynamic, conversation: { properties: { id: keyword, diff --git a/x-pack/plugins/observability_ai_assistant/server/service/kb_service/index.ts b/x-pack/plugins/observability_ai_assistant/server/service/kb_service/index.ts index deed5c41fd480..eab3a0a2fbe57 100644 --- a/x-pack/plugins/observability_ai_assistant/server/service/kb_service/index.ts +++ b/x-pack/plugins/observability_ai_assistant/server/service/kb_service/index.ts @@ -6,12 +6,13 @@ */ import { errors } from '@elastic/elasticsearch'; import type { QueryDslTextExpansionQuery } from '@elastic/elasticsearch/lib/api/types'; -import { serverUnavailable } from '@hapi/boom'; +import { serverUnavailable, gatewayTimeout } from '@hapi/boom'; import type { ElasticsearchClient } from '@kbn/core/server'; import type { Logger } from '@kbn/logging'; -import { TaskManagerStartContract } from '@kbn/task-manager-plugin/server'; +import type { TaskManagerStartContract } from '@kbn/task-manager-plugin/server'; import pLimit from 'p-limit'; import pRetry from 'p-retry'; +import { map } from 'lodash'; import { INDEX_QUEUED_DOCUMENTS_TASK_ID, INDEX_QUEUED_DOCUMENTS_TASK_TYPE } from '..'; import type { KnowledgeBaseEntry } from '../../../common/types'; import type { ObservabilityAIAssistantResourceNames } from '../types'; @@ -24,16 +25,44 @@ interface Dependencies { taskManagerStart: TaskManagerStartContract; } +function isAlreadyExistsError(error: Error) { + return ( + error instanceof errors.ResponseError && + (error.body.error.type === 'resource_not_found_exception' || + error.body.error.type === 'status_exception') + ); +} + const ELSER_MODEL_ID = '.elser_model_1'; function throwKnowledgeBaseNotReady(body: any) { throw serverUnavailable(`Knowledge base is not ready yet`, body); } +export enum KnowledgeBaseEntryOperationType { + Index = 'index', + Delete = 'delete', +} + +interface KnowledgeBaseDeleteOperation { + type: KnowledgeBaseEntryOperationType.Delete; + id?: string; + labels?: Record<string, string>; +} + +interface KnowledgeBaseIndexOperation { + type: KnowledgeBaseEntryOperationType.Index; + document: KnowledgeBaseEntry; +} + +export type KnowledgeBaseEntryOperation = + | KnowledgeBaseDeleteOperation + | KnowledgeBaseIndexOperation; + export class KnowledgeBaseService { private hasSetup: boolean = false; - private entryQueue: KnowledgeBaseEntry[] = []; + private _queue: KnowledgeBaseEntryOperation[] = []; constructor(private readonly dependencies: Dependencies) { this.ensureTaskScheduled(); @@ -51,93 +80,120 @@ export class KnowledgeBaseService { }, }) .then(() => { - this.dependencies.logger.debug('Scheduled document queue task'); + this.dependencies.logger.debug('Scheduled queue task'); return this.dependencies.taskManagerStart.runSoon(INDEX_QUEUED_DOCUMENTS_TASK_ID); }) .then(() => { - this.dependencies.logger.debug('Document queue task ran'); + this.dependencies.logger.debug('Queue task ran'); }) .catch((err) => { - this.dependencies.logger.error(`Failed to schedule document queue task`); + this.dependencies.logger.error(`Failed to schedule queue task`); this.dependencies.logger.error(err); }); } + private async processOperation(operation: KnowledgeBaseEntryOperation) { + if (operation.type === KnowledgeBaseEntryOperationType.Delete) { + await this.dependencies.esClient.deleteByQuery({ + index: this.dependencies.resources.aliases.kb, + query: { + bool: { + filter: [ + ...(operation.id ? [{ term: { _id: operation.id } }] : []), + ...(operation.labels + ? map(operation.labels, (value, key) => { + return { term: { [key]: value } }; + }) + : []), + ], + }, + }, + }); + return; + } + + await this.summarise({ + entry: operation.document, + }); + } + async processQueue() { - if (!this.entryQueue.length) { + if (!this._queue.length) { return; } if (!(await this.status()).ready) { - this.dependencies.logger.debug(`Bailing on document queue task: KB is not ready yet`); + this.dependencies.logger.debug(`Bailing on queue task: KB is not ready yet`); return; } - this.dependencies.logger.debug(`Processing document queue`); + this.dependencies.logger.debug(`Processing queue`); this.hasSetup = true; - this.dependencies.logger.info(`Indexing ${this.entryQueue.length} queued entries into KB`); + this.dependencies.logger.info(`Processing ${this._queue.length} queue operations`); const limiter = pLimit(5); - const entries = this.entryQueue.concat(); + const operations = this._queue.concat(); await Promise.all( - entries.map((entry) => - limiter(() => { - this.entryQueue.splice(entries.indexOf(entry), 1); - return this.summarise({ entry }); + operations.map((operation) => + limiter(async () => { + this._queue.splice(operations.indexOf(operation), 1); + await this.processOperation(operation); }) ) ); - this.dependencies.logger.info('Indexed all queued entries into KB'); + this.dependencies.logger.info('Processed all queued operations'); } - async store(entries: KnowledgeBaseEntry[]) { - if (!entries.length) { + queue(operations: KnowledgeBaseEntryOperation[]): void { + if (!operations.length) { return; } if (!this.hasSetup) { - this.entryQueue.push(...entries); + this._queue.push(...operations); return; } const limiter = pLimit(5); - const limitedFunctions = entries.map((entry) => limiter(() => this.summarise({ entry }))); + const limitedFunctions = this._queue.map((operation) => + limiter(() => this.processOperation(operation)) + ); Promise.all(limitedFunctions).catch((err) => { - this.dependencies.logger.error(`Failed to index all knowledge base entries`); + this.dependencies.logger.error(`Failed to process all queued operations`); this.dependencies.logger.error(err); }); } recall = async ({ user, - query, + queries, namespace, }: { - query: string; + queries: string[]; user: { name: string }; namespace: string; - }): Promise<{ entries: KnowledgeBaseEntry[] }> => { + }): Promise<{ entries: Array<Pick<KnowledgeBaseEntry, 'text' | 'id'>> }> => { try { - const response = await this.dependencies.esClient.search<KnowledgeBaseEntry>({ + const response = await this.dependencies.esClient.search< + Pick<KnowledgeBaseEntry, 'text' | 'id'> + >({ index: this.dependencies.resources.aliases.kb, query: { bool: { - should: [ - { - text_expansion: { - 'ml.tokens': { - model_text: query, - model_id: '.elser_model_1', - }, - } as unknown as QueryDslTextExpansionQuery, - }, - ], + should: queries.map((query) => ({ + text_expansion: { + 'ml.tokens': { + model_text: query, + model_id: '.elser_model_1', + }, + } as unknown as QueryDslTextExpansionQuery, + })), filter: [ ...getAccessQuery({ user, @@ -146,19 +202,21 @@ export class KnowledgeBaseService { ], }, }, - size: 3, + size: 5, _source: { - includes: ['text', 'id'], + includes: ['text', 'is_correction', 'labels'], }, }); - return { entries: response.hits.hits.map((hit) => ({ ...hit._source!, score: hit._score })) }; + return { + entries: response.hits.hits.map((hit) => ({ + ...hit._source!, + score: hit._score, + id: hit._id, + })), + }; } catch (error) { - if ( - (error instanceof errors.ResponseError && - error.body.error.type === 'resource_not_found_exception') || - error.body.error.type === 'status_exception' - ) { + if (isAlreadyExistsError(error)) { throwKnowledgeBaseNotReady(error.body); } throw error; @@ -185,6 +243,7 @@ export class KnowledgeBaseService { namespace, }, pipeline: this.dependencies.resources.pipelines.kb, + refresh: false, }); } catch (error) { if (error instanceof errors.ResponseError && error.body.error.type === 'status_exception') { @@ -216,7 +275,7 @@ export class KnowledgeBaseService { }; setup = async () => { - // if this fails, it's fine to propagate the error to the user + const retryOptions = { factor: 1, minTimeout: 10000, retries: 12 }; const installModel = async () => { this.dependencies.logger.info('Installing ELSER model'); @@ -234,26 +293,36 @@ export class KnowledgeBaseService { this.dependencies.logger.info('Finished installing ELSER model'); }; - try { + const getIsModelInstalled = async () => { const getResponse = await this.dependencies.esClient.ml.getTrainedModels({ model_id: ELSER_MODEL_ID, include: 'definition_status', }); - if (!getResponse.trained_model_configs[0]?.fully_defined) { - this.dependencies.logger.info('Model is not fully defined'); - await installModel(); + this.dependencies.logger.debug( + 'Model definition status:\n' + JSON.stringify(getResponse.trained_model_configs[0]) + ); + + return Boolean(getResponse.trained_model_configs[0]?.fully_defined); + }; + + await pRetry(async () => { + let isModelInstalled: boolean = false; + try { + isModelInstalled = await getIsModelInstalled(); + } catch (error) { + if (isAlreadyExistsError(error)) { + await installModel(); + isModelInstalled = await getIsModelInstalled(); + } } - } catch (error) { - if ( - error instanceof errors.ResponseError && - error.body.error.type === 'resource_not_found_exception' - ) { - await installModel(); - } else { - throw error; + + if (!isModelInstalled) { + throwKnowledgeBaseNotReady({ + message: 'Model is not fully defined', + }); } - } + }, retryOptions); try { await this.dependencies.esClient.ml.startTrainedModelDeployment({ @@ -261,32 +330,30 @@ export class KnowledgeBaseService { wait_for: 'fully_allocated', }); } catch (error) { - if ( - !(error instanceof errors.ResponseError && error.body.error.type === 'status_exception') - ) { + this.dependencies.logger.debug('Error starting model deployment'); + this.dependencies.logger.debug(error); + if (!isAlreadyExistsError(error)) { throw error; } } - await pRetry( - async () => { - const response = await this.dependencies.esClient.ml.getTrainedModelsStats({ - model_id: ELSER_MODEL_ID, - }); + await pRetry(async () => { + const response = await this.dependencies.esClient.ml.getTrainedModelsStats({ + model_id: ELSER_MODEL_ID, + }); - if ( - response.trained_model_stats[0]?.deployment_stats?.allocation_status.state === - 'fully_allocated' - ) { - return Promise.resolve(); - } + if ( + response.trained_model_stats[0]?.deployment_stats?.allocation_status.state === + 'fully_allocated' + ) { + return Promise.resolve(); + } - this.dependencies.logger.debug('Model is not allocated yet'); + this.dependencies.logger.debug('Model is not allocated yet'); + this.dependencies.logger.debug(JSON.stringify(response)); - return Promise.reject(new Error('Not Ready')); - }, - { factor: 1, minTimeout: 10000, maxRetryTime: 20 * 60 * 1000 } - ); + throw gatewayTimeout(); + }, retryOptions); this.dependencies.logger.info('Model is ready'); this.ensureTaskScheduled(); diff --git a/x-pack/plugins/observability_ai_assistant/server/service/kb_service/kb_docs/lens.ts b/x-pack/plugins/observability_ai_assistant/server/service/kb_service/kb_docs/lens.ts index aa0c6e3ffb937..e4fdc8969c010 100644 --- a/x-pack/plugins/observability_ai_assistant/server/service/kb_service/kb_docs/lens.ts +++ b/x-pack/plugins/observability_ai_assistant/server/service/kb_service/kb_docs/lens.ts @@ -12,9 +12,8 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { service.addToKnowledgeBase([ { id: 'lens_formulas_how_it_works', - text: dedent(`## How it works - - Lens formulas let you do math using a combination of Elasticsearch aggregations and + texts: [ + `Lens formulas let you do math using a combination of Elasticsearch aggregations and math functions. There are three main types of functions: * Elasticsearch metrics, like \`sum(bytes)\` @@ -30,8 +29,8 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { kql='datacenter.name: east*' )) \`\`\` - - Elasticsearch functions take a field name, which can be in quotes. \`sum(bytes)\` is the same + `, + `Elasticsearch functions take a field name, which can be in quotes. \`sum(bytes)\` is the same as \`sum('bytes')\`. Some functions take named arguments, like \`moving_average(count(), window=5)\`. @@ -42,25 +41,23 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { Math functions can take positional arguments, like pow(count(), 3) is the same as count() * count() * count() - Use the symbols +, -, /, and * to perform basic math.`), + Use the symbols +, -, /, and * to perform basic math.`, + ], }, { id: 'lens_common_formulas', - text: dedent(`## Common formulas - - The most common formulas are dividing two values to produce a percent. To display accurately, set - "value format" to "percent". - - ### Filter ratio: + texts: [ + `The most common formulas are dividing two values to produce a percent. To display accurately, set + "value format" to "percent"`, + `### Filter ratio: Use \`kql=''\` to filter one set of documents and compare it to other documents within the same grouping. For example, to see how the error rate changes over time: \`\`\` count(kql='response.status_code > 400') / count() - \`\`\` - - ### Week over week: + \`\`\``, + `### Week over week: Use \`shift='1w'\` to get the value of each grouping from the previous week. Time shift should not be used with the *Top values* function. @@ -68,18 +65,18 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { \`\`\` percentile(system.network.in.bytes, percentile=99) / percentile(system.network.in.bytes, percentile=99, shift='1w') - \`\`\` + \`\`\``, - ### Percent of total + `### Percent of total Formulas can calculate \`overall_sum\` for all the groupings, which lets you convert each grouping into a percent of total: \`\`\` sum(products.base_price) / overall_sum(sum(products.base_price)) - \`\`\` + \`\`\``, - ### Recent change + `### Recent change Use \`reducedTimeRange='30m'\` to add an additional filter on the time range of a metric aligned with the end of the global time range. @@ -88,27 +85,28 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { \`\`\` max(system.network.in.bytes, reducedTimeRange="30m") - min(system.network.in.bytes, reducedTimeRange="30m") - \`\`\` - - `), + \`\`\` + `, + ], }, { id: 'lens_formulas_elasticsearch_functions', - text: dedent(`## Elasticsearch functions + texts: [ + `## Elasticsearch functions These functions will be executed on the raw documents for each row of the resulting table, aggregating all documents matching the break down - dimensions into a single value. + dimensions into a single value.`, - #### average(field: string) + `#### average(field: string) Returns the average of a field. This function only works for number fields. Example: Get the average of price: \`average(price)\` Example: Get the average of price for orders from the UK: \`average(price, - kql='location:UK')\` + kql='location:UK')\``, - #### count([field: string]) + `#### count([field: string]) The total number of documents. When you provide a field, the total number of field values is counted. When you use the Count function for fields that have multiple values in a single document, all values are counted. @@ -118,57 +116,57 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { To calculate the number of products in all orders, use \`count(products.id)\`. To calculate the number of documents that match a specific filter, use - \`count(kql='price > 500')\`. + \`count(kql='price > 500')\`.`, - #### last_value(field: string) + `#### last_value(field: string) Returns the value of a field from the last document, ordered by the default time field of the data view. This function is usefull the retrieve the latest state of an entity. Example: Get the current status of server A: \`last_value(server.status, - kql='server.name="A"')\` + kql='server.name="A"')\``, - #### max(field: string) + `#### max(field: string) Returns the max of a field. This function only works for number fields. Example: Get the max of price: \`max(price)\` Example: Get the max of price for orders from the UK: \`max(price, - kql='location:UK')\` + kql='location:UK')\``, - #### median(field: string) + `#### median(field: string) Returns the median of a field. This function only works for number fields. Example: Get the median of price: \`median(price)\` Example: Get the median of price for orders from the UK: \`median(price, - kql='location:UK')\` + kql='location:UK')\``, - #### min(field: string) + `#### min(field: string) Returns the min of a field. This function only works for number fields. Example: Get the min of price: \`min(price)\` Example: Get the min of price for orders from the UK: \`min(price, - kql='location:UK')\` + kql='location:UK')\``, - #### percentile(field: string, [percentile]: number) + `#### percentile(field: string, [percentile]: number) Returns the specified percentile of the values of a field. This is the value n percent of the values occuring in documents are smaller. Example: Get the number of bytes larger than 95 % of values: - \`percentile(bytes, percentile=95)\` + \`percentile(bytes, percentile=95)\``, - #### percentile_rank(field: string, [value]: number) + `#### percentile_rank(field: string, [value]: number) Returns the percentage of values which are below a certain value. For example, if a value is greater than or equal to 95% of the observed values it is said to be at the 95th percentile rank Example: Get the percentage of values which are below of 100: - \`percentile_rank(bytes, value=100)\` + \`percentile_rank(bytes, value=100)\``, - #### standard_deviation(field: string) + `#### standard_deviation(field: string) Returns the amount of variation or dispersion of the field. The function works only for number fields. @@ -176,17 +174,17 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { \`standard_deviation(price).\` Example: To get the variance of price for orders from the UK, use - \`square(standard_deviation(price, kql='location:UK'))\`. + \`square(standard_deviation(price, kql='location:UK'))\`.`, - #### sum(field: string) + `#### sum(field: string) Returns the sum of a field. This function only works for number fields. Example: Get the sum of price: sum(price) Example: Get the sum of price for orders from the UK: \`sum(price, - kql='location:UK')\` + kql='location:UK')\``, - #### unique_count(field: string) + `#### unique_count(field: string) Calculates the number of unique values of a specified field. Works for number, string, date and boolean values. @@ -196,15 +194,17 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { Example: Calculate the number of different products from the "clothes" group: \`unique_count(product.name, kql='product.group=clothes')\` - `), + `, + ], }, { id: 'lens_formulas_column_functions', - text: dedent(`## Column calculations + texts: [ + `## Column calculations These functions are executed for each row, but are provided with the whole - column as context. This is also known as a window function. - - #### counter_rate(metric: number) + column as context. This is also known as a window function.`, + + `#### counter_rate(metric: number) Calculates the rate of an ever increasing counter. This function will only yield helpful results on counter metric fields which contain a measurement of some kind monotonically growing over time. If the value does get smaller, it @@ -215,9 +215,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { or top values dimensions. It uses the current interval when used in Formula. Example: Visualize the rate of bytes received over time by a memcached server: - counter_rate(max(memcached.stats.read.bytes)) - - cumulative_sum(metric: number) + counter_rate(max(memcached.stats.read.bytes))`, + + `cumulative_sum(metric: number) Calculates the cumulative sum of a metric over time, adding all previous values of a series to each value. To use this function, you need to configure a date histogram dimension as well. @@ -226,9 +226,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { or top values dimensions. Example: Visualize the received bytes accumulated over time: - cumulative_sum(sum(bytes)) - - differences(metric: number) + cumulative_sum(sum(bytes))`, + + `differences(metric: number) Calculates the difference to the last value of a metric over time. To use this function, you need to configure a date histogram dimension as well. Differences requires the data to be sequential. If your data is empty when using @@ -238,9 +238,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { or top values dimensions. Example: Visualize the change in bytes received over time: - differences(sum(bytes)) - - moving_average(metric: number, [window]: number) + differences(sum(bytes))`, + + `moving_average(metric: number, [window]: number) Calculates the moving average of a metric over time, averaging the last n-th values to calculate the current value. To use this function, you need to configure a date histogram dimension as well. The default window value is 5. @@ -251,9 +251,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { Takes a named parameter window which specifies how many last values to include in the average calculation for the current value. - Example: Smooth a line of measurements: moving_average(sum(bytes), window=5) - - normalize_by_unit(metric: number, unit: s|m|h|d|w|M|y) + Example: Smooth a line of measurements: moving_average(sum(bytes), window=5)`, + + `normalize_by_unit(metric: number, unit: s|m|h|d|w|M|y) This advanced function is useful for normalizing counts and sums to a specific time interval. It allows for integration with metrics that are stored already normalized to a specific time interval. @@ -264,9 +264,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { Example: A ratio comparing an already normalized metric to another metric that needs to be normalized. normalize_by_unit(counter_rate(max(system.diskio.write.bytes)), unit='s') / - last_value(apache.status.bytes_per_second) - - overall_average(metric: number) + last_value(apache.status.bytes_per_second)`, + + `overall_average(metric: number) Calculates the average of a metric for all data points of a series in the current chart. A series is defined by a dimension using a date histogram or interval function. Other dimensions breaking down the data like top values or @@ -276,9 +276,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { overall_average is calculating the average over all dimensions no matter the used function - Example: Divergence from the mean: sum(bytes) - overall_average(sum(bytes)) - - overall_max(metric: number) + Example: Divergence from the mean: sum(bytes) - overall_average(sum(bytes))`, + + `overall_max(metric: number) Calculates the maximum of a metric for all data points of a series in the current chart. A series is defined by a dimension using a date histogram or interval function. Other dimensions breaking down the data like top values or @@ -289,9 +289,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { function Example: Percentage of range (sum(bytes) - overall_min(sum(bytes))) / - (overall_max(sum(bytes)) - overall_min(sum(bytes))) - - overall_min(metric: number) + (overall_max(sum(bytes)) - overall_min(sum(bytes)))`, + + `overall_min(metric: number) Calculates the minimum of a metric for all data points of a series in the current chart. A series is defined by a dimension using a date histogram or interval function. Other dimensions breaking down the data like top values or @@ -302,9 +302,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { function Example: Percentage of range (sum(bytes) - overall_min(sum(bytes)) / - (overall_max(sum(bytes)) - overall_min(sum(bytes))) - - overall_sum(metric: number) + (overall_max(sum(bytes)) - overall_min(sum(bytes)))`, + + `overall_sum(metric: number) Calculates the sum of a metric of all data points of a series in the current chart. A series is defined by a dimension using a date histogram or interval function. Other dimensions breaking down the data like top values or filter are @@ -314,19 +314,21 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { overall_sum is calculating the sum over all dimensions no matter the used function. - Example: Percentage of total sum(bytes) / overall_sum(sum(bytes))`), + Example: Percentage of total sum(bytes) / overall_sum(sum(bytes))`, + ], }, { id: 'lens_formulas_math_functions', - text: dedent(`Math - These functions will be executed for reach row of the resulting table using single values from the same row calculated using other functions. - - abs([value]: number) + texts: [ + `Math + These functions will be executed for reach row of the resulting table using single values from the same row calculated using other functions.`, + + `abs([value]: number) Calculates absolute value. A negative value is multiplied by -1, a positive value stays the same. - Example: Calculate average distance to sea level abs(average(altitude)) - - add([left]: number, [right]: number) + Example: Calculate average distance to sea level abs(average(altitude))`, + + `add([left]: number, [right]: number) Adds up two numbers. Also works with + symbol. @@ -337,9 +339,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { Example: Offset count by a static value - add(count(), 5) - - cbrt([value]: number) + add(count(), 5)`, + + `cbrt([value]: number) Cube root of value. Example: Calculate side length from volume @@ -351,9 +353,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { Example: Round up price to the next dollar - ceil(sum(price)) - - clamp([value]: number, [min]: number, [max]: number) + ceil(sum(price))`, + + `clamp([value]: number, [min]: number, [max]: number) Limits the value from a minimum to maximum. Example: Make sure to catch outliers @@ -362,22 +364,22 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { average(bytes), percentile(bytes, percentile=5), percentile(bytes, percentile=95) - ) - cube([value]: number) + )`, + `cube([value]: number) Calculates the cube of a number. Example: Calculate volume from side length - cube(last_value(length)) - - defaults([value]: number, [default]: number) + cube(last_value(length))`, + + `defaults([value]: number, [default]: number) Returns a default numeric value when value is null. Example: Return -1 when a field has no data - defaults(average(bytes), -1) - - divide([left]: number, [right]: number) + defaults(average(bytes), -1)`, + + `divide([left]: number, [right]: number) Divides the first number by the second number. Also works with / symbol @@ -386,44 +388,44 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { sum(profit) / sum(revenue) - Example: divide(sum(bytes), 2) - - exp([value]: number) + Example: divide(sum(bytes), 2)`, + + `exp([value]: number) Raises e to the nth power. Example: Calculate the natural exponential function - exp(last_value(duration)) - - fix([value]: number) + exp(last_value(duration))`, + + `fix([value]: number) For positive values, takes the floor. For negative values, takes the ceiling. Example: Rounding towards zero - fix(sum(profit)) - - floor([value]: number) + fix(sum(profit))`, + + `floor([value]: number) Round down to nearest integer value Example: Round down a price - floor(sum(price)) - - log([value]: number, [base]?: number) + floor(sum(price))`, + + `log([value]: number, [base]?: number) Logarithm with optional base. The natural base e is used as default. Example: Calculate number of bits required to store values log(sum(bytes)) - log(sum(bytes), 2) - mod([value]: number, [base]: number) + log(sum(bytes), 2)`, + `mod([value]: number, [base]: number) Remainder after dividing the function by a number Example: Calculate last three digits of a value - mod(sum(price), 1000) - - multiply([left]: number, [right]: number) + mod(sum(price), 1000)`, + + `multiply([left]: number, [right]: number) Multiplies two numbers. Also works with * symbol. @@ -434,63 +436,67 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { Example: Calculate price after constant tax rate - multiply(sum(price), 1.2) - - pick_max([left]: number, [right]: number) + multiply(sum(price), 1.2)`, + + `pick_max([left]: number, [right]: number) Finds the maximum value between two numbers. Example: Find the maximum between two fields averages - pick_max(average(bytes), average(memory)) - - pick_min([left]: number, [right]: number) + pick_max(average(bytes), average(memory))`, + + `pick_min([left]: number, [right]: number) Finds the minimum value between two numbers. Example: Find the minimum between two fields averages - pick_min(average(bytes), average(memory)) - - pow([value]: number, [base]: number) + pick_min(average(bytes), average(memory))`, + + `pow([value]: number, [base]: number) Raises the value to a certain power. The second argument is required Example: Calculate volume based on side length - pow(last_value(length), 3) - - round([value]: number, [decimals]?: number) + pow(last_value(length), 3)`, + + `round([value]: number, [decimals]?: number) Rounds to a specific number of decimal places, default of 0 Examples: Round to the cent round(sum(bytes)) - round(sum(bytes), 2) - sqrt([value]: number) + round(sum(bytes), 2)`, + `sqrt([value]: number) Square root of a positive value only Example: Calculate side length based on area - sqrt(last_value(area)) - - square([value]: number) + sqrt(last_value(area))`, + + `square([value]: number) Raise the value to the 2nd power Example: Calculate area based on side length - square(last_value(length)) - - subtract([left]: number, [right]: number) + square(last_value(length))`, + + `subtract([left]: number, [right]: number) Subtracts the first number from the second number. Also works with - symbol. Example: Calculate the range of a field - subtract(max(bytes), min(bytes)) - - Comparison - These functions are used to perform value comparison. - - eq([left]: number, [right]: number) + subtract(max(bytes), min(bytes))`, + ], + }, + { + id: 'lens_formulas_comparison_functions', + texts: [ + `Comparison + These functions are used to perform value comparison.`, + + `eq([left]: number, [right]: number) Performs an equality comparison between two values. To be used as condition for ifelse comparison function. @@ -501,9 +507,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { average(bytes) == average(memory) - Example: eq(sum(bytes), 1000000) - - gt([left]: number, [right]: number) + Example: eq(sum(bytes), 1000000)`, + + `gt([left]: number, [right]: number) Performs a greater than comparison between two values. To be used as condition for ifelse comparison function. @@ -514,9 +520,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { average(bytes) > average(memory) - Example: gt(average(bytes), 1000) - - gte([left]: number, [right]: number) + Example: gt(average(bytes), 1000)`, + + `gte([left]: number, [right]: number) Performs a greater than comparison between two values. To be used as condition for ifelse comparison function. @@ -527,16 +533,16 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { average(bytes) >= average(memory) - Example: gte(average(bytes), 1000) - - ifelse([condition]: boolean, [left]: number, [right]: number) + Example: gte(average(bytes), 1000)`, + + `ifelse([condition]: boolean, [left]: number, [right]: number) Returns a value depending on whether the element of condition is true or false. Example: Average revenue per customer but in some cases customer id is not provided which counts as additional customer - sum(total)/(unique_count(customer_id) + ifelse( count() > count(kql='customer_id:*'), 1, 0)) - - lt([left]: number, [right]: number) + sum(total)/(unique_count(customer_id) + ifelse( count() > count(kql='customer_id:*'), 1, 0))`, + + `lt([left]: number, [right]: number) Performs a lower than comparison between two values. To be used as condition for ifelse comparison function. @@ -547,9 +553,9 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { average(bytes) <= average(memory) - Example: lt(average(bytes), 1000) - - lte([left]: number, [right]: number) + Example: lt(average(bytes), 1000)`, + + `lte([left]: number, [right]: number) Performs a lower than or equal comparison between two values. To be used as condition for ifelse comparison function. @@ -560,7 +566,8 @@ export function addLensDocsToKb(service: ObservabilityAIAssistantService) { average(bytes) <= average(memory) - Example: lte(average(bytes), 1000)`), + Example: lte(average(bytes), 1000)`, + ], }, { id: 'lens_formulas_kibana_context', diff --git a/x-pack/plugins/observability_ai_assistant/server/service/util/split_kb_text.ts b/x-pack/plugins/observability_ai_assistant/server/service/util/split_kb_text.ts new file mode 100644 index 0000000000000..e2b5b7c2c5784 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/server/service/util/split_kb_text.ts @@ -0,0 +1,35 @@ +/* + * 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 { merge } from 'lodash'; +import type { KnowledgeBaseEntry } from '../../../common/types'; +import { type KnowledgeBaseEntryOperation, KnowledgeBaseEntryOperationType } from '../kb_service'; + +export function splitKbText({ + id, + texts, + ...rest +}: Omit<KnowledgeBaseEntry, 'text'> & { texts: string[] }): KnowledgeBaseEntryOperation[] { + return [ + { + type: KnowledgeBaseEntryOperationType.Delete, + labels: { + document_id: id, + }, + }, + ...texts.map((text, index) => ({ + type: KnowledgeBaseEntryOperationType.Index, + document: merge({}, rest, { + id: [id, index].join('_'), + labels: { + document_id: id, + }, + text, + }), + })), + ]; +} diff --git a/x-pack/plugins/observability_ai_assistant/tsconfig.json b/x-pack/plugins/observability_ai_assistant/tsconfig.json index 8c49398e2deab..ddbd38c21bc5d 100644 --- a/x-pack/plugins/observability_ai_assistant/tsconfig.json +++ b/x-pack/plugins/observability_ai_assistant/tsconfig.json @@ -42,7 +42,9 @@ "@kbn/field-formats-plugin", "@kbn/lens-plugin", "@kbn/data-views-plugin", - "@kbn/task-manager-plugin" + "@kbn/task-manager-plugin", + "@kbn/es-query", + "@kbn/rule-registry-plugin" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/stack_connectors/common/gen_ai/schema.ts b/x-pack/plugins/stack_connectors/common/gen_ai/schema.ts index 0ec4541120444..bae0a9f532d41 100644 --- a/x-pack/plugins/stack_connectors/common/gen_ai/schema.ts +++ b/x-pack/plugins/stack_connectors/common/gen_ai/schema.ts @@ -41,20 +41,29 @@ export const GenAiRunActionResponseSchema = schema.object( object: schema.string(), created: schema.number(), model: schema.string(), - usage: schema.object({ - prompt_tokens: schema.number(), - completion_tokens: schema.number(), - total_tokens: schema.number(), - }), + usage: schema.object( + { + prompt_tokens: schema.number(), + completion_tokens: schema.number(), + total_tokens: schema.number(), + }, + { unknowns: 'ignore' } + ), choices: schema.arrayOf( - schema.object({ - message: schema.object({ - role: schema.string(), - content: schema.string(), - }), - finish_reason: schema.string(), - index: schema.number(), - }) + schema.object( + { + message: schema.object( + { + role: schema.string(), + content: schema.string(), + }, + { unknowns: 'ignore' } + ), + finish_reason: schema.string(), + index: schema.number(), + }, + { unknowns: 'ignore' } + ) ), }, { unknowns: 'ignore' } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/gen_ai/gen_ai.ts b/x-pack/plugins/stack_connectors/server/connector_types/gen_ai/gen_ai.ts index 488ec89711415..c88d129db7071 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/gen_ai/gen_ai.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/gen_ai/gen_ai.ts @@ -77,7 +77,7 @@ export class GenAiConnector extends SubActionConnector<GenAiConfig, GenAiSecrets protected getResponseErrorMessage(error: AxiosError<{ error?: { message?: string } }>): string { if (!error.response?.status) { - return 'Unknown API Error'; + return `Unexpected API Error: ${error.code} - ${error.message}`; } if (error.response.status === 401) { return 'Unauthorized API Error'; @@ -116,6 +116,7 @@ export class GenAiConnector extends SubActionConnector<GenAiConfig, GenAiSecrets stream, ...('defaultModel' in this.config ? [this.config.defaultModel] : []) ); + const axiosOptions = getAxiosOptions(this.provider, this.key, stream); const response = await this.request({ url: this.url, From 5484f048fa9af79647b1177ee935b9ecb1af45db Mon Sep 17 00:00:00 2001 From: Abdul Wahab Zahid <awahab07@yahoo.com> Date: Mon, 28 Aug 2023 15:33:08 +0200 Subject: [PATCH 10/49] [Synthetics] Adjust `from` date monitor pings query range. (#163287) Fixes #162587 ## Summary Fixes the `from` date which previously would point to current day for a restored project monitor (i.e. when monitor `created_at` is refreshed due to a re-push of a deleted project monitor). --- .../hooks/use_monitor_range_from.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_range_from.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_range_from.ts index fe858f0a0056a..be8bba42bf4d2 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_range_from.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_range_from.ts @@ -7,6 +7,9 @@ import { useMemo } from 'react'; import moment from 'moment'; + +import { ConfigKey } from '../../../../../../common/constants/monitor_management'; +import { SourceType } from '../../../../../../common/runtime_types'; import { useRefreshedRange } from '../../../hooks'; import { useSelectedMonitor } from './use_selected_monitor'; @@ -17,11 +20,14 @@ export const useMonitorRangeFrom = () => { return useMemo(() => { if (monitor?.created_at) { - const diff = moment(monitor?.created_at).diff(moment().subtract(30, 'day'), 'days'); - if (diff > 0) { - return { to, from: monitor?.created_at, loading }; + const monitorCreatedDaysAgo = moment().diff(monitor.created_at, 'days'); + const isProjectMonitor = monitor?.[ConfigKey.MONITOR_SOURCE_TYPE] === SourceType.PROJECT; + + // Always look back at lest 3 days to account for reinstated project monitors. + if ((!isProjectMonitor || monitorCreatedDaysAgo > 3) && monitorCreatedDaysAgo < 30) { + return { to, from: monitor.created_at, loading }; } } return { to, from, loading }; - }, [monitor?.created_at, to, from, loading]); + }, [monitor, to, from, loading]); }; From 0738a51b9c9d3fe7f7d99702c8117a3cae1fd0d4 Mon Sep 17 00:00:00 2001 From: christineweng <18648970+christineweng@users.noreply.github.com> Date: Mon, 28 Aug 2023 08:47:40 -0500 Subject: [PATCH 11/49] [Security Solution] Update risk score tooltip message (#164930) ## Summary This PR updates tooltips of user risk score and host risk score based on docs team's [suggestions](https://github.com/elastic/kibana/issues/164786). ![image](https://github.com/elastic/kibana/assets/18648970/2c6d4bd0-6ad7-4f84-aaae-d663c63b518b) ![image](https://github.com/elastic/kibana/assets/18648970/8ba4086b-1a13-4803-90f2-858d53879da3) ### Checklist - [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) --- .../public/explore/hosts/components/hosts_table/translations.ts | 2 +- .../public/explore/users/components/all_users/translations.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/translations.ts b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/translations.ts index 55960cca0faf2..bf4002cd5568c 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/translations.ts +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/translations.ts @@ -40,7 +40,7 @@ export const HOST_RISK_TOOLTIP = i18n.translate( 'xpack.securitySolution.hostsTable.hostRiskToolTip', { defaultMessage: - 'Host risk classification is determined by host risk score. Hosts classified as Critical or High are indicated as risky.', + "The host's risk score determines its risk classification. Risky hosts are labeled as critical or high.", } ); diff --git a/x-pack/plugins/security_solution/public/explore/users/components/all_users/translations.ts b/x-pack/plugins/security_solution/public/explore/users/components/all_users/translations.ts index 0de194c394a2a..17319a82e74f1 100644 --- a/x-pack/plugins/security_solution/public/explore/users/components/all_users/translations.ts +++ b/x-pack/plugins/security_solution/public/explore/users/components/all_users/translations.ts @@ -43,7 +43,7 @@ export const USER_RISK_TOOLTIP = i18n.translate( 'xpack.securitySolution.usersTable.userRiskToolTip', { defaultMessage: - 'User risk classification is determined by user risk score. Users classified as Critical or High are indicated as risky.', + "The user's risk score determines its risk classification. Risky users are labeled as critical or high.", } ); From 84b683bd7a6f96f2466461f37bfe7e0971d4001d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Mon, 28 Aug 2023 16:19:44 +0200 Subject: [PATCH 12/49] [Index details page] Implement index actions (#164741) ## Summary Addresses https://github.com/elastic/kibana/issues/164546 Follow up to https://github.com/elastic/kibana/pull/163521 and https://github.com/elastic/kibana/pull/163955 This PR re-implements index actions in the context menu on the index details page. The actions are implemented without redux which is used in the old index details flyout (to be removed when this work is complete) and in the indices list. The PR introduces a declaration file to list all props of the component `IndexActionsContextMenu` written in JS. There is also a new component `ManageIndexButton` that implements index actions specifically to be executed on the new index details page. In the future most of the code in the component `ManageIndexButton` can be re-used when more refactorings will be made (switching to TS and not using redux in the indices list). All index actions are async and I added a loading indicator to the context menu button to indicate that requests are in flight updating the index. ### Screen recordings https://github.com/elastic/kibana/assets/6585477/c39f1450-b495-4c50-b4ca-8989a2259ed5 Add/remove ILM policy actions with a confirmation modal https://github.com/elastic/kibana/assets/6585477/964931c9-b926-4ed4-aa5c-218f52881131 ### How to test 1. Add `xpack.index_management.dev.enableIndexDetailsPage: true` to your `/config/kibana.dev.yml` file 7. Start ES and Kibana with `yarn es snapshot` and `yarn start` 8. Add several indices to test with the command `PUT /test_index` in Dev Tools Console 9. Navigate to Index Management and click the name of any index 10. Check index actions: - [x] Close index - [x] Open index - [x] Force merge index - [x] Refresh index - [x] Clear index cache - [x] Flush index - [ ] Unfreeze index (not sure how to add a frozen index) - [x] Delete index - [x] ILM: add lifecycle policy - [x] ILM: remove lifecycle policy - [x] ILM: retry lifecycle policy (add any built-in policy and wait a couple of minutes until the rollover fails) ### Checklist - [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 --- .../index_details_page.helpers.ts | 28 +- .../index_details_page.test.ts | 164 ++++++++++- .../index_details_page/mocks.ts | 4 +- .../index_management/common/types/indices.ts | 9 + .../index_list/details_page/details_page.tsx | 59 +++- .../details_page/details_page_error.tsx | 3 +- .../details_page/manage_index_button.tsx | 258 ++++++++++++++++++ .../index_actions_context_menu.d.ts | 68 +++++ .../index_actions_context_menu.js | 4 + ...dex_actions_context_menu.without_redux.tsx | 107 -------- .../public/application/services/api.ts | 10 +- .../public/application/services/index.ts | 3 +- .../application/services/indices_api.ts | 16 -- .../application/services/use_request.ts | 4 +- 14 files changed, 577 insertions(+), 160 deletions(-) create mode 100644 x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/manage_index_button.tsx create mode 100644 x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.d.ts delete mode 100644 x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.without_redux.tsx delete mode 100644 x-pack/plugins/index_management/public/application/services/indices_api.ts diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts index 4caf94db5de79..43d436c495799 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts @@ -18,11 +18,12 @@ import { IndexDetailsSection, } from '../../../public/application/sections/home/index_list/details_page'; import { WithAppDependencies } from '../helpers'; +import { testIndexName } from './mocks'; let routerMock: typeof reactRouterMock; const testBedConfig: AsyncTestBedConfig = { memoryRouter: { - initialEntries: [`/indices/test_index`], + initialEntries: [`/indices/${testIndexName}`], componentRoutePath: `/indices/:indexName/:indexDetailsSection?`, onRouter: (router) => { routerMock = router; @@ -42,6 +43,9 @@ export interface IndexDetailsPageTestBed extends TestBed { contextMenu: { clickManageIndexButton: () => Promise<void>; isOpened: () => boolean; + clickIndexAction: (indexAction: string) => Promise<void>; + confirmForcemerge: (numSegments: string) => Promise<void>; + confirmDelete: () => Promise<void>; }; errorSection: { isDisplayed: () => boolean; @@ -108,6 +112,28 @@ export const setup = async ( isOpened: () => { return exists('indexContextMenu'); }, + clickIndexAction: async (indexAction: string) => { + await act(async () => { + find(`indexContextMenu.${indexAction}`).simulate('click'); + }); + component.update(); + }, + confirmForcemerge: async (numSegments: string) => { + await act(async () => { + testBed.form.setInputValue('indexActionsForcemergeNumSegments', numSegments); + }); + component.update(); + await act(async () => { + find('confirmModalConfirmButton').simulate('click'); + }); + component.update(); + }, + confirmDelete: async () => { + await act(async () => { + find('confirmModalConfirmButton').simulate('click'); + }); + component.update(); + }, }; return { ...testBed, diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.ts index a880933ec9fdc..7b144fd0bad40 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.ts @@ -9,7 +9,8 @@ import { setupEnvironment } from '../helpers'; import { IndexDetailsPageTestBed, setup } from './index_details_page.helpers'; import { act } from 'react-dom/test-utils'; import { IndexDetailsSection } from '../../../public/application/sections/home/index_list/details_page'; -import { testIndexMock } from './mocks'; +import { testIndexMock, testIndexName } from './mocks'; +import { API_BASE_PATH, INTERNAL_API_BASE_PATH } from '../../../common'; describe('<IndexDetailsPage />', () => { let testBed: IndexDetailsPageTestBed; @@ -19,8 +20,8 @@ describe('<IndexDetailsPage />', () => { beforeEach(async () => { const mockEnvironment = setupEnvironment(); ({ httpSetup, httpRequestsMockHelpers } = mockEnvironment); - // test_index is configured in initialEntries of the memory router - httpRequestsMockHelpers.setLoadIndexDetailsResponse('test_index', testIndexMock); + // testIndexName is configured in initialEntries of the memory router + httpRequestsMockHelpers.setLoadIndexDetailsResponse(testIndexName, testIndexMock); await act(async () => { testBed = await setup(httpSetup, { @@ -36,9 +37,9 @@ describe('<IndexDetailsPage />', () => { describe('error section', () => { beforeEach(async () => { - httpRequestsMockHelpers.setLoadIndexDetailsResponse('test_index', undefined, { + httpRequestsMockHelpers.setLoadIndexDetailsResponse(testIndexName, undefined, { statusCode: 400, - message: 'Data for index .apm-agent-configuration was not found', + message: `Data for index ${testIndexName} was not found`, }); await act(async () => { testBed = await setup(httpSetup); @@ -59,10 +60,17 @@ describe('<IndexDetailsPage />', () => { }); }); + it('loads index details from the API', async () => { + expect(httpSetup.get).toHaveBeenLastCalledWith( + `${INTERNAL_API_BASE_PATH}/indices/${testIndexName}`, + { asSystemRequest: undefined, body: undefined, query: undefined, version: undefined } + ); + }); + it('displays index name in the header', () => { const header = testBed.actions.getHeader(); - // test_index is configured in initialEntries of the memory router - expect(header).toEqual('test_index'); + // testIndexName is configured in initialEntries of the memory router + expect(header).toEqual(testIndexName); }); it('defaults to overview tab', () => { @@ -106,12 +114,140 @@ describe('<IndexDetailsPage />', () => { expect(testBed.actions.discoverLinkExists()).toBe(true); }); - it('opens an index context menu when "manage index" button is clicked', async () => { - const { - actions: { contextMenu }, - } = testBed; - expect(contextMenu.isOpened()).toBe(false); - await testBed.actions.contextMenu.clickManageIndexButton(); - expect(contextMenu.isOpened()).toBe(true); + describe('context menu', () => { + it('opens an index context menu when "manage index" button is clicked', async () => { + expect(testBed.actions.contextMenu.isOpened()).toBe(false); + await testBed.actions.contextMenu.clickManageIndexButton(); + expect(testBed.actions.contextMenu.isOpened()).toBe(true); + }); + + it('closes an index', async () => { + // already sent 1 request while setting up the component + const numberOfRequests = 1; + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests); + + await testBed.actions.contextMenu.clickManageIndexButton(); + await testBed.actions.contextMenu.clickIndexAction('closeIndexMenuButton'); + expect(httpSetup.post).toHaveBeenCalledWith(`${API_BASE_PATH}/indices/close`, { + body: JSON.stringify({ indices: [testIndexName] }), + }); + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests + 1); + }); + + it('opens an index', async () => { + httpRequestsMockHelpers.setLoadIndexDetailsResponse(testIndexName, { + ...testIndexMock, + status: 'close', + }); + + await act(async () => { + testBed = await setup(httpSetup); + }); + testBed.component.update(); + + // already sent 2 requests while setting up the component + const numberOfRequests = 2; + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests); + + await testBed.actions.contextMenu.clickManageIndexButton(); + await testBed.actions.contextMenu.clickIndexAction('openIndexMenuButton'); + expect(httpSetup.post).toHaveBeenCalledWith(`${API_BASE_PATH}/indices/open`, { + body: JSON.stringify({ indices: [testIndexName] }), + }); + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests + 1); + }); + + it('forcemerges an index', async () => { + // already sent 1 request while setting up the component + const numberOfRequests = 1; + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests); + + await testBed.actions.contextMenu.clickManageIndexButton(); + await testBed.actions.contextMenu.clickIndexAction('forcemergeIndexMenuButton'); + await testBed.actions.contextMenu.confirmForcemerge('2'); + expect(httpSetup.post).toHaveBeenCalledWith(`${API_BASE_PATH}/indices/forcemerge`, { + body: JSON.stringify({ indices: [testIndexName], maxNumSegments: '2' }), + }); + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests + 1); + }); + + it('refreshes an index', async () => { + // already sent 1 request while setting up the component + const numberOfRequests = 1; + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests); + + await testBed.actions.contextMenu.clickManageIndexButton(); + await testBed.actions.contextMenu.clickIndexAction('refreshIndexMenuButton'); + expect(httpSetup.post).toHaveBeenCalledWith(`${API_BASE_PATH}/indices/refresh`, { + body: JSON.stringify({ indices: [testIndexName] }), + }); + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests + 1); + }); + + it(`clears an index's cache`, async () => { + // already sent 1 request while setting up the component + const numberOfRequests = 1; + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests); + + await testBed.actions.contextMenu.clickManageIndexButton(); + await testBed.actions.contextMenu.clickIndexAction('clearCacheIndexMenuButton'); + expect(httpSetup.post).toHaveBeenCalledWith(`${API_BASE_PATH}/indices/clear_cache`, { + body: JSON.stringify({ indices: [testIndexName] }), + }); + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests + 1); + }); + + it(`flushes an index`, async () => { + // already sent 1 request while setting up the component + const numberOfRequests = 1; + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests); + + await testBed.actions.contextMenu.clickManageIndexButton(); + await testBed.actions.contextMenu.clickIndexAction('flushIndexMenuButton'); + expect(httpSetup.post).toHaveBeenCalledWith(`${API_BASE_PATH}/indices/flush`, { + body: JSON.stringify({ indices: [testIndexName] }), + }); + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests + 1); + }); + + it(`deletes an index`, async () => { + jest.spyOn(testBed.routerMock.history, 'push'); + // already sent 1 request while setting up the component + const numberOfRequests = 1; + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests); + + await testBed.actions.contextMenu.clickManageIndexButton(); + await testBed.actions.contextMenu.clickIndexAction('deleteIndexMenuButton'); + await testBed.actions.contextMenu.confirmDelete(); + expect(httpSetup.post).toHaveBeenCalledWith(`${API_BASE_PATH}/indices/delete`, { + body: JSON.stringify({ indices: [testIndexName] }), + }); + + expect(testBed.routerMock.history.push).toHaveBeenCalledTimes(1); + expect(testBed.routerMock.history.push).toHaveBeenCalledWith('/indices'); + }); + + it(`unfreezes a frozen index`, async () => { + httpRequestsMockHelpers.setLoadIndexDetailsResponse(testIndexName, { + ...testIndexMock, + isFrozen: true, + }); + + await act(async () => { + testBed = await setup(httpSetup); + }); + testBed.component.update(); + + // already sent 1 request while setting up the component + const numberOfRequests = 2; + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests); + + await testBed.actions.contextMenu.clickManageIndexButton(); + await testBed.actions.contextMenu.clickIndexAction('unfreezeIndexMenuButton'); + expect(httpSetup.post).toHaveBeenCalledWith(`${API_BASE_PATH}/indices/unfreeze`, { + body: JSON.stringify({ indices: [testIndexName] }), + }); + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests + 1); + }); }); }); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/mocks.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/mocks.ts index d96f1d0fac0dc..5e165fe0702e6 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/mocks.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/mocks.ts @@ -7,10 +7,11 @@ import { Index } from '../../../public'; +export const testIndexName = 'test_index'; export const testIndexMock: Index = { health: 'green', status: 'open', - name: 'test_index', + name: testIndexName, uuid: 'test1234', primary: '1', replica: '1', @@ -21,7 +22,6 @@ export const testIndexMock: Index = { isFrozen: false, aliases: 'none', hidden: false, - // @ts-expect-error ts upgrade v4.7.4 isRollupIndex: false, ilm: { index: 'test_index', diff --git a/x-pack/plugins/index_management/common/types/indices.ts b/x-pack/plugins/index_management/common/types/indices.ts index ab54812f2f0e3..608ee392a3f9e 100644 --- a/x-pack/plugins/index_management/common/types/indices.ts +++ b/x-pack/plugins/index_management/common/types/indices.ts @@ -64,6 +64,15 @@ export interface Index { hidden: boolean; aliases: string | string[]; data_stream?: string; + + // The types below are added by extension services if corresponding plugins are enabled (ILM, Rollup, CCR) + isRollupIndex?: boolean; + ilm?: { + index: string; + managed: boolean; + }; + isFollowerIndex?: boolean; + // The types from here below represent information returned from the index stats API; // treated optional as the stats API is not available on serverless health?: HealthStatus; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx index 573bd1d7ee353..6d91b3a7991a1 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useCallback, useMemo } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { Redirect, RouteComponentProps } from 'react-router-dom'; import { Route, Routes } from '@kbn/shared-ux-router'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -17,11 +17,14 @@ import { EuiButton, } from '@elastic/eui'; import { SectionLoading } from '@kbn/es-ui-shared-plugin/public'; + +import { Index } from '../../../../../../common'; +import { loadIndex } from '../../../../services'; import { DiscoverLink } from '../../../../lib/discover_link'; -import { useLoadIndex } from '../../../../services'; import { Section } from '../../home'; import { DetailsPageError } from './details_page_error'; -import { IndexActionsContextMenuWithoutRedux } from '../index_actions_context_menu/index_actions_context_menu.without_redux'; +import { ManageIndexButton } from './manage_index_button'; + export enum IndexDetailsSection { Overview = 'overview', Documents = 'documents', @@ -69,6 +72,27 @@ export const DetailsPage: React.FunctionComponent< }, history, }) => { + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(); + const [index, setIndex] = useState<Index | null>(); + + const fetchIndexDetails = useCallback(async () => { + setIsLoading(true); + try { + const { data, error: loadingError } = await loadIndex(indexName); + setIsLoading(false); + setError(loadingError); + setIndex(data); + } catch (e) { + setIsLoading(false); + setError(e); + } + }, [indexName]); + + useEffect(() => { + fetchIndexDetails(); + }, [fetchIndexDetails]); + const onSectionChange = useCallback( (newSection: IndexDetailsSection) => { return history.push(encodeURI(`/indices/${indexName}/${newSection}`)); @@ -76,6 +100,10 @@ export const DetailsPage: React.FunctionComponent< [history, indexName] ); + const navigateToAllIndices = useCallback(() => { + history.push(`/${Section.Indices}`); + }, [history]); + const headerTabs = useMemo<EuiPageHeaderProps['tabs']>(() => { return tabs.map((tab) => ({ onClick: () => onSectionChange(tab.id), @@ -86,8 +114,7 @@ export const DetailsPage: React.FunctionComponent< })); }, [indexDetailsSection, onSectionChange]); - const { isLoading, error, resendRequest, data } = useLoadIndex(indexName); - if (isLoading) { + if (isLoading && !index) { return ( <SectionLoading> <FormattedMessage @@ -97,8 +124,8 @@ export const DetailsPage: React.FunctionComponent< </SectionLoading> ); } - if (error || !data) { - return <DetailsPageError indexName={indexName} resendRequest={resendRequest} />; + if (error || !index) { + return <DetailsPageError indexName={indexName} resendRequest={fetchIndexDetails} />; } return ( @@ -108,9 +135,7 @@ export const DetailsPage: React.FunctionComponent< data-test-subj="indexDetailsBackToIndicesButton" color="text" iconType="arrowLeft" - onClick={() => { - return history.push(`/${Section.Indices}`); - }} + onClick={navigateToAllIndices} > <FormattedMessage id="xpack.idxMgmt.indexDetails.backToIndicesButtonLabel" @@ -127,10 +152,11 @@ export const DetailsPage: React.FunctionComponent< bottomBorder rightSideItems={[ <DiscoverLink indexName={indexName} asButton={true} />, - <IndexActionsContextMenuWithoutRedux - indexNames={[indexName]} - indices={[data]} - fill={false} + <ManageIndexButton + indexName={indexName} + indexDetails={index} + reloadIndexDetails={fetchIndexDetails} + navigateToAllIndices={navigateToAllIndices} />, ]} tabs={headerTabs} @@ -166,6 +192,11 @@ export const DetailsPage: React.FunctionComponent< /> </Routes> </div> + + <EuiSpacer size="l" /> + <div> + <pre>{JSON.stringify(index, null, 2)}</pre> + </div> </> ); }; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_error.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_error.tsx index 6defc3d3db034..c1159cecfe09f 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_error.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_error.tsx @@ -8,14 +8,13 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiButton, EuiPageTemplate, EuiSpacer, EuiText } from '@elastic/eui'; -import { useLoadIndex } from '../../../../services'; export const DetailsPageError = ({ indexName, resendRequest, }: { indexName: string; - resendRequest: ReturnType<typeof useLoadIndex>['resendRequest']; + resendRequest: () => Promise<void>; }) => { return ( <EuiPageTemplate.EmptyPrompt diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/manage_index_button.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/manage_index_button.tsx new file mode 100644 index 0000000000000..df59931a51833 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/manage_index_button.tsx @@ -0,0 +1,258 @@ +/* + * 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, { FunctionComponent, useCallback, useMemo, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { HttpSetup } from '@kbn/core-http-browser'; + +import { Index } from '../../../../../../common'; +import { + clearCacheIndices as clearCacheIndicesRequest, + closeIndices as closeIndicesRequest, + deleteIndices as deleteIndicesRequest, + flushIndices as flushIndicesRequest, + forcemergeIndices as forcemergeIndicesRequest, + openIndices as openIndicesRequest, + refreshIndices as refreshIndicesRequest, + unfreezeIndices as unfreezeIndicesRequest, +} from '../../../../services'; +import { notificationService } from '../../../../services/notification'; +import { httpService } from '../../../../services/http'; + +import { + IndexActionsContextMenu, + IndexActionsContextMenuProps, +} from '../index_actions_context_menu/index_actions_context_menu'; + +const getIndexStatusByName = ( + indexNames: string[], + indices: Index[] +): IndexActionsContextMenuProps['indexStatusByName'] => { + const indexStatusByName: IndexActionsContextMenuProps['indexStatusByName'] = {}; + indexNames.forEach((indexName) => { + const { status } = indices.find((index) => index.name === indexName) ?? {}; + indexStatusByName[indexName] = status; + }); + return indexStatusByName; +}; + +interface Props { + indexName: string; + indexDetails: Index; + reloadIndexDetails: () => Promise<void>; + navigateToAllIndices: () => void; +} +export const ManageIndexButton: FunctionComponent<Props> = ({ + indexName, + indexDetails, + reloadIndexDetails, + navigateToAllIndices, +}) => { + const [isLoading, setIsLoading] = useState(false); + + // the variables are created to write the index actions in a way to later re-use for indices list without redux + const indexNames = useMemo(() => [indexName], [indexName]); + + const reloadIndices = useCallback(async () => { + setIsLoading(true); + await reloadIndexDetails(); + setIsLoading(false); + }, [reloadIndexDetails]); + + const indices = [indexDetails]; + const indexStatusByName = getIndexStatusByName(indexNames, indices); + + const closeIndices = useCallback(async () => { + setIsLoading(true); + try { + await closeIndicesRequest(indexNames); + await reloadIndices(); + setIsLoading(false); + notificationService.showSuccessToast( + i18n.translate('xpack.idxMgmt.closeIndicesAction.successfullyClosedIndicesMessage', { + defaultMessage: 'Successfully closed: [{indexNames}]', + values: { indexNames: indexNames.join(', ') }, + }) + ); + } catch (error) { + setIsLoading(false); + notificationService.showDangerToast(error.body.message); + } + }, [reloadIndices, indexNames]); + + const openIndices = useCallback(async () => { + setIsLoading(true); + try { + await openIndicesRequest(indexNames); + await reloadIndices(); + setIsLoading(false); + notificationService.showSuccessToast( + i18n.translate('xpack.idxMgmt.openIndicesAction.successfullyOpenedIndicesMessage', { + defaultMessage: 'Successfully opened: [{indexNames}]', + values: { indexNames: indexNames.join(', ') }, + }) + ); + } catch (error) { + setIsLoading(false); + notificationService.showDangerToast(error.body.message); + } + }, [reloadIndices, indexNames]); + + const flushIndices = useCallback(async () => { + setIsLoading(true); + try { + await flushIndicesRequest(indexNames); + await reloadIndices(); + setIsLoading(false); + notificationService.showSuccessToast( + i18n.translate('xpack.idxMgmt.flushIndicesAction.successfullyFlushedIndicesMessage', { + defaultMessage: 'Successfully flushed: [{indexNames}]', + values: { indexNames: indexNames.join(', ') }, + }) + ); + } catch (error) { + setIsLoading(false); + notificationService.showDangerToast(error.body.message); + } + }, [reloadIndices, indexNames]); + + const refreshIndices = useCallback(async () => { + setIsLoading(true); + try { + await refreshIndicesRequest(indexNames); + await reloadIndices(); + setIsLoading(false); + notificationService.showSuccessToast( + i18n.translate('xpack.idxMgmt.refreshIndicesAction.successfullyRefreshedIndicesMessage', { + defaultMessage: 'Successfully refreshed: [{indexNames}]', + values: { indexNames: indexNames.join(', ') }, + }) + ); + } catch (error) { + setIsLoading(false); + notificationService.showDangerToast(error.body.message); + } + }, [reloadIndices, indexNames]); + + const clearCacheIndices = useCallback(async () => { + setIsLoading(true); + try { + await clearCacheIndicesRequest(indexNames); + await reloadIndices(); + setIsLoading(false); + notificationService.showSuccessToast( + i18n.translate('xpack.idxMgmt.clearCacheIndicesAction.successMessage', { + defaultMessage: 'Successfully cleared cache: [{indexNames}]', + values: { indexNames: indexNames.join(', ') }, + }) + ); + } catch (error) { + setIsLoading(false); + notificationService.showDangerToast(error.body.message); + } + }, [reloadIndices, indexNames]); + + const unfreezeIndices = useCallback(async () => { + setIsLoading(true); + try { + await unfreezeIndicesRequest(indexNames); + await reloadIndices(); + setIsLoading(false); + notificationService.showSuccessToast( + i18n.translate('xpack.idxMgmt.unfreezeIndicesAction.successfullyUnfrozeIndicesMessage', { + defaultMessage: 'Successfully unfroze: [{indexNames}]', + values: { indexNames: indexNames.join(', ') }, + }) + ); + } catch (error) { + setIsLoading(false); + notificationService.showDangerToast(error.body.message); + } + }, [reloadIndices, indexNames]); + + const forcemergeIndices = useCallback( + async (maxNumSegments: string) => { + setIsLoading(true); + try { + await forcemergeIndicesRequest(indexNames, maxNumSegments); + await reloadIndices(); + setIsLoading(false); + notificationService.showSuccessToast( + i18n.translate( + 'xpack.idxMgmt.forceMergeIndicesAction.successfullyForceMergedIndicesMessage', + { + defaultMessage: 'Successfully force merged: [{indexNames}]', + values: { indexNames: indexNames.join(', ') }, + } + ) + ); + } catch (error) { + setIsLoading(false); + notificationService.showDangerToast(error.body.message); + } + }, + [reloadIndices, indexNames] + ); + + const deleteIndices = useCallback(async () => { + setIsLoading(true); + try { + await deleteIndicesRequest(indexNames); + setIsLoading(false); + notificationService.showSuccessToast( + i18n.translate('xpack.idxMgmt.deleteIndicesAction.successfullyDeletedIndicesMessage', { + defaultMessage: 'Successfully deleted: [{indexNames}]', + values: { indexNames: indexNames.join(', ') }, + }) + ); + navigateToAllIndices(); + } catch (error) { + setIsLoading(false); + notificationService.showDangerToast(error.body.message); + } + }, [navigateToAllIndices, indexNames]); + + const performExtensionAction = useCallback( + async ( + requestMethod: (indexNames: string[], http: HttpSetup) => Promise<void>, + successMessage: string + ) => { + setIsLoading(true); + try { + await requestMethod(indexNames, httpService.httpClient); + await reloadIndices(); + setIsLoading(false); + notificationService.showSuccessToast(successMessage); + } catch (error) { + setIsLoading(false); + notificationService.showDangerToast(error.body.message); + } + }, + [reloadIndices, indexNames] + ); + + return ( + <IndexActionsContextMenu + indexNames={indexNames} + indices={indices} + indexStatusByName={indexStatusByName} + fill={false} + isLoading={isLoading} + // index actions + closeIndices={closeIndices} + openIndices={openIndices} + flushIndices={flushIndices} + refreshIndices={refreshIndices} + clearCacheIndices={clearCacheIndices} + unfreezeIndices={unfreezeIndices} + forcemergeIndices={forcemergeIndices} + deleteIndices={deleteIndices} + performExtensionAction={performExtensionAction} + reloadIndices={reloadIndices} + /> + ); +}; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.d.ts b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.d.ts new file mode 100644 index 0000000000000..896622ac0e9fb --- /dev/null +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.d.ts @@ -0,0 +1,68 @@ +/* + * 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 { ClassComponent, Component } from 'react'; +import type { HttpSetup } from '@kbn/core-http-browser'; +import type { EuiPopoverProps, EuiButtonProps } from '@elastic/eui'; +import type { Index } from '../../../../../../common'; + +export interface IndexActionsContextMenuProps { + // either an array of indices selected in the list view or an array of 1 index name on the details panel/page + indexNames: string[]; + // indices data + indices: Index[]; + + // indicates if the context menu is on the list view (to show additional actions) + isOnListView?: boolean; + // a callback used to reset selected indices on the list view + resetSelection?: () => void; + + // these props are only set on the details panel to change style + anchorPosition?: EuiPopoverProps['anchorPosition']; + iconSide?: EuiButtonProps['iconSide']; + iconType?: EuiButtonProps['iconType']; + label?: Component; + + // index actions: functions are called with indexNames prop so no need to pass it as argument here + closeIndices: () => Promise<void>; + openIndices: () => Promise<void>; + flushIndices: () => Promise<void>; + refreshIndices: () => Promise<void>; + clearCacheIndices: () => Promise<void>; + unfreezeIndices: () => Promise<void>; + forcemergeIndices: (maxNumSegments: string) => Promise<void>; + deleteIndices: () => Promise<void>; + + // following 4 actions are only added when on the list view and only 1 index is selected + showSettings?: () => void; // opens the settings tab for the 1st index in the indexNames array + showMapping?: () => void; // opens the mapping tab for the 1st index in the indexNames array + showStats?: () => void; // opens the stats tab for the 1st index in the indexNames array + editIndex?: () => void; // opens the edit settings tab for the 1st index in the indexNames array + + // used to determine if all indices are open + indexStatusByName: { + [indexName: string]: Index['status'] | undefined; + }; + + // this function is called with an extension service action + performExtensionAction: ( + requestMethod: (indexNames: string[], http: HttpSetup) => Promise<void>, + successMessage: string + ) => Promise<void>; + // this function is called to "refresh" the indices data after and extension service action that uses a modal + reloadIndices: () => void; + + /** + * Props added to use the context menu on the new index details page + */ + // makes the button secondary + fill?: boolean; + // sets the button's loading state + isLoading?: boolean; +} + +export const IndexActionsContextMenu: ClassComponent<Props>; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js index 8fb7fa5410f72..54ba5dee8250e 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js @@ -198,6 +198,7 @@ export class IndexActionsContextMenu extends Component { }); } items.push({ + 'data-test-subj': 'deleteIndexMenuButton', name: i18n.translate('xpack.idxMgmt.indexActionsMenu.deleteIndexLabel', { defaultMessage: 'Delete {selectedIndexCount, plural, one {index} other {indices} }', values: { selectedIndexCount }, @@ -372,6 +373,7 @@ export class IndexActionsContextMenu extends Component { helpText={helpText} > <EuiFieldNumber + data-test-subj="indexActionsForcemergeNumSegments" onChange={(event) => { this.setState({ forcemergeSegments: event.target.value }); }} @@ -464,6 +466,7 @@ export class IndexActionsContextMenu extends Component { }), iconType = 'arrowDown', fill = true, + isLoading = false, } = this.props; const panels = this.panels(appDependencies); @@ -480,6 +483,7 @@ export class IndexActionsContextMenu extends Component { onClick={this.onButtonClick} iconType={iconType} fill={fill} + isLoading={isLoading} > {label} </EuiButton> diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.without_redux.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.without_redux.tsx deleted file mode 100644 index 177bfc7350af0..0000000000000 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.without_redux.tsx +++ /dev/null @@ -1,107 +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, { FunctionComponent } from 'react'; -import { HttpSetup } from '@kbn/core-http-browser'; -import { EuiButtonProps } from '@elastic/eui/src/components/button/button'; -import { EuiPopoverProps } from '@elastic/eui/src/components/popover/popover'; -import { Index } from '../../../../../../common'; -import { reloadIndices } from '../../../../services'; -// @ts-ignore this component needs to be refactored into TS -import { IndexActionsContextMenu } from './index_actions_context_menu'; - -export interface ReduxProps { - closeIndices: ({}: { indexNames: string[] }) => Promise<void>; - openIndices: ({}: { indexNames: string[] }) => Promise<void>; - flushIndices: ({}: { indexNames: string[] }) => Promise<void>; - refreshIndices: ({}: { indexNames: string[] }) => Promise<void>; - clearCacheIndices: ({}: { indexNames: string[] }) => Promise<void>; - unfreezeIndices: ({}: { indexNames: string[] }) => Promise<void>; - forcemergeIndices: ({}: { indexNames: string[]; maxNumSegments: number }) => Promise<void>; - deleteIndices: ({}: { indexNames: string[] }) => Promise<void>; - - // following 4 actions are only added when on the list view and only 1 index is selected - showSettings: ({}: { indexNames: string[] }) => void; // opens the settings tab for the 1st index - showMapping: ({}: { indexNames: string[] }) => void; // opens the mapping tab for the 1st index - showStats: ({}: { indexNames: string[] }) => void; // opens the stats tab for the 1st index - editIndex: ({}: { indexNames: string[] }) => void; // opens the edit settings tab for the 1st index - - indexStatusByName: { - [indexName: string]: Index['status'] | undefined; - }; - reloadIndices: typeof reloadIndices; - - // this comes from the extension service - performExtensionAction: ({}: { - requestMethod: (indexNames: string[], httpClient: HttpSetup) => Promise<void>; - indexNames: string[]; - successMessage: string; - }) => Promise<void>; -} - -interface Props { - // either an array of indices selected in the list view or an array of 1 index name on details panel/page - indexNames: string[]; - - // indicates if the context menu is on the list view (to show additional actions) - isOnListView?: boolean; - // a callback used to reset selected indices on the list view - resetSelection?: () => void; - - // these props are only set on the details panel to change style - anchorPosition?: EuiPopoverProps['anchorPosition']; - iconSide?: EuiButtonProps['iconSide']; - iconType?: EuiButtonProps['iconType']; - label?: React.Component; - - // a new prop to make the button secondary - fill?: boolean; - - // instead of getting indices data from the redux store, pass it as a prop - indices: Index[]; -} - -const getIndexStatusByName = ( - indexNames: string[], - indices: Index[] -): ReduxProps['indexStatusByName'] => { - const indexStatusByName: ReduxProps['indexStatusByName'] = {}; - indexNames.forEach((indexName) => { - const { status } = indices.find((index) => index.name === indexName) ?? {}; - indexStatusByName[indexName] = status; - }); - return indexStatusByName; -}; - -export const IndexActionsContextMenuWithoutRedux: FunctionComponent<Props> = ({ - indexNames, - indices, - ...rest -}) => { - const props: ReduxProps = { - closeIndices: async () => {}, - openIndices: async () => {}, - flushIndices: async () => {}, - refreshIndices: async () => {}, - clearCacheIndices: async () => {}, - unfreezeIndices: async () => {}, - forcemergeIndices: async () => {}, - deleteIndices: async () => {}, - - // there actions are not displayed on the index details page - showSettings: () => {}, - showMapping: () => {}, - showStats: () => {}, - editIndex: () => {}, - - indexStatusByName: getIndexStatusByName(indexNames, indices), - reloadIndices: async () => {}, - - performExtensionAction: async () => {}, - }; - return <IndexActionsContextMenu indexNames={indexNames} indices={indices} {...props} {...rest} />; -}; diff --git a/x-pack/plugins/index_management/public/application/services/api.ts b/x-pack/plugins/index_management/public/application/services/api.ts index 5defc62ece088..b19382364722c 100644 --- a/x-pack/plugins/index_management/public/application/services/api.ts +++ b/x-pack/plugins/index_management/public/application/services/api.ts @@ -31,8 +31,9 @@ import { UIM_TEMPLATE_UPDATE, UIM_TEMPLATE_CLONE, UIM_TEMPLATE_SIMULATE, + INTERNAL_API_BASE_PATH, } from '../../../common/constants'; -import { TemplateDeserialized, TemplateListItem, DataStream } from '../../../common'; +import { TemplateDeserialized, TemplateListItem, DataStream, Index } from '../../../common'; import { TAB_SETTINGS, TAB_MAPPING, TAB_STATS } from '../constants'; import { useRequest, sendRequest } from './use_request'; import { httpService } from './http'; @@ -311,3 +312,10 @@ export function useLoadNodesPlugins() { method: 'get', }); } + +export function loadIndex(indexName: string) { + return sendRequest<Index>({ + path: `${INTERNAL_API_BASE_PATH}/indices/${indexName}`, + method: 'get', + }); +} diff --git a/x-pack/plugins/index_management/public/application/services/index.ts b/x-pack/plugins/index_management/public/application/services/index.ts index 96e961b718bd9..5cb65c04b6c9d 100644 --- a/x-pack/plugins/index_management/public/application/services/index.ts +++ b/x-pack/plugins/index_management/public/application/services/index.ts @@ -24,10 +24,9 @@ export { useLoadIndexTemplates, simulateIndexTemplate, useLoadNodesPlugins, + loadIndex, } from './api'; -export { useLoadIndex } from './indices_api'; - export { sortTable } from './sort_table'; export { UiMetricService } from './ui_metric'; diff --git a/x-pack/plugins/index_management/public/application/services/indices_api.ts b/x-pack/plugins/index_management/public/application/services/indices_api.ts deleted file mode 100644 index c7e4cc5775ce5..0000000000000 --- a/x-pack/plugins/index_management/public/application/services/indices_api.ts +++ /dev/null @@ -1,16 +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 { useRequest } from './use_request'; -import { Index, INTERNAL_API_BASE_PATH } from '../../../common'; - -export const useLoadIndex = (indexName: string) => { - return useRequest<Index>({ - path: `${INTERNAL_API_BASE_PATH}/indices/${indexName}`, - method: 'get', - }); -}; diff --git a/x-pack/plugins/index_management/public/application/services/use_request.ts b/x-pack/plugins/index_management/public/application/services/use_request.ts index 3b1d5cf22452d..4746890361d59 100644 --- a/x-pack/plugins/index_management/public/application/services/use_request.ts +++ b/x-pack/plugins/index_management/public/application/services/use_request.ts @@ -16,7 +16,9 @@ import { import { httpService } from './http'; -export const sendRequest = (config: SendRequestConfig): Promise<SendRequestResponse> => { +export const sendRequest = <T = any>( + config: SendRequestConfig +): Promise<SendRequestResponse<T>> => { return _sendRequest(httpService.httpClient, config); }; From 243142d9c19d3d0689f311ca2361bb4dd90b8ce2 Mon Sep 17 00:00:00 2001 From: Anton Dosov <anton.dosov@elastic.co> Date: Mon, 28 Aug 2023 16:24:34 +0200 Subject: [PATCH 13/49] [Serverless Elasticsearch] Fix user is blocked from moving forward when opening Discover, Dashboard, or Visualize Library --- .github/CODEOWNERS | 1 + config/serverless.es.yml | 3 + docs/developer/plugin-list.asciidoc | 4 + package.json | 1 + packages/kbn-optimizer/limits.yml | 1 + .../card/no_data/impl/src/no_data_card.tsx | 4 +- .../shared-ux/card/no_data/types/index.d.ts | 2 +- .../analytics_no_data_page.component.test.tsx | 87 +++++++++++++++++ .../src/analytics_no_data_page.component.tsx | 94 +++++++++++++------ .../impl/src/analytics_no_data_page.test.tsx | 2 + .../impl/src/analytics_no_data_page.tsx | 4 +- .../analytics_no_data/impl/src/services.tsx | 6 +- .../page/analytics_no_data/impl/tsconfig.json | 2 + .../page/analytics_no_data/mocks/src/jest.ts | 4 + .../analytics_no_data/mocks/src/storybook.ts | 2 + .../page/analytics_no_data/types/index.d.ts | 12 +++ .../page/no_data/impl/src/no_data_page.tsx | 11 ++- .../shared-ux/page/no_data/types/index.d.ts | 4 +- src/plugins/dashboard/kibana.jsonc | 3 +- .../no_data/dashboard_app_no_data.tsx | 2 + src/plugins/dashboard/public/plugin.tsx | 2 + .../no_data_page/no_data_page_service.stub.ts | 16 ++++ .../no_data_page/no_data_page_service.ts | 24 +++++ .../public/services/no_data_page/types.ts | 13 +++ .../public/services/plugin_services.stub.ts | 2 + .../public/services/plugin_services.ts | 2 + .../dashboard/public/services/types.ts | 2 + src/plugins/dashboard/tsconfig.json | 3 +- src/plugins/discover/kibana.jsonc | 5 +- .../application/main/discover_main_route.tsx | 13 +-- src/plugins/discover/public/build_services.ts | 3 + src/plugins/discover/public/plugin.tsx | 2 + src/plugins/discover/tsconfig.json | 3 +- src/plugins/no_data_page/README.md | 3 + src/plugins/no_data_page/config.ts | 19 ++++ src/plugins/no_data_page/jest.config.js | 16 ++++ src/plugins/no_data_page/kibana.jsonc | 10 ++ src/plugins/no_data_page/public/index.ts | 16 ++++ src/plugins/no_data_page/public/plugin.ts | 31 ++++++ src/plugins/no_data_page/public/types.ts | 13 +++ src/plugins/no_data_page/server/index.ts | 25 +++++ src/plugins/no_data_page/tsconfig.json | 14 +++ src/plugins/visualizations/kibana.jsonc | 3 +- src/plugins/visualizations/public/plugin.ts | 3 + .../public/visualize_app/app.tsx | 6 ++ .../public/visualize_app/types.ts | 2 + src/plugins/visualizations/tsconfig.json | 3 +- .../test_suites/core_plugins/rendering.ts | 1 + tsconfig.base.json | 2 + .../test_suites/search/empty_page.ts | 41 ++++++++ .../functional/test_suites/search/index.ts | 1 + yarn.lock | 4 + 52 files changed, 496 insertions(+), 56 deletions(-) create mode 100644 src/plugins/dashboard/public/services/no_data_page/no_data_page_service.stub.ts create mode 100644 src/plugins/dashboard/public/services/no_data_page/no_data_page_service.ts create mode 100644 src/plugins/dashboard/public/services/no_data_page/types.ts create mode 100755 src/plugins/no_data_page/README.md create mode 100644 src/plugins/no_data_page/config.ts create mode 100644 src/plugins/no_data_page/jest.config.js create mode 100644 src/plugins/no_data_page/kibana.jsonc create mode 100644 src/plugins/no_data_page/public/index.ts create mode 100644 src/plugins/no_data_page/public/plugin.ts create mode 100644 src/plugins/no_data_page/public/types.ts create mode 100644 src/plugins/no_data_page/server/index.ts create mode 100644 src/plugins/no_data_page/tsconfig.json create mode 100644 x-pack/test_serverless/functional/test_suites/search/empty_page.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 911bfb5161dc0..6189270654c7b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -517,6 +517,7 @@ x-pack/plugins/monitoring @elastic/infra-monitoring-ui src/plugins/navigation @elastic/appex-sharedux src/plugins/newsfeed @elastic/kibana-core test/common/plugins/newsfeed @elastic/kibana-core +src/plugins/no_data_page @elastic/appex-sharedux x-pack/plugins/notifications @elastic/appex-sharedux packages/kbn-object-versioning @elastic/appex-sharedux x-pack/plugins/observability_ai_assistant @elastic/obs-ai-assistant diff --git a/config/serverless.es.yml b/config/serverless.es.yml index 8ee07c718cce0..7a1da782855bd 100644 --- a/config/serverless.es.yml +++ b/config/serverless.es.yml @@ -32,3 +32,6 @@ telemetry.labels.serverless: search # Alerts config xpack.actions.enabledActionTypes: ['.email', '.index', '.slack', '.jira', '.webhook', '.teams'] + +# Customize empty page state for analytics apps +no_data_page.analyticsNoDataPageFlavor: 'serverless_search' diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index e8c008af6e0e8..41aecaccf554c 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -254,6 +254,10 @@ It also provides a stateful version of it on the start contract. Content is fetched from the remote (https://feeds.elastic.co) once a day, with periodic checks if the content needs to be refreshed. All newsfeed content is hosted remotely. +|{kib-repo}blob/{branch}/src/plugins/no_data_page/README.md[noDataPage] +|Helps to globally configure the no data page components + + |{kib-repo}blob/{branch}/src/plugins/presentation_util/README.mdx[presentationUtil] |The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). diff --git a/package.json b/package.json index a1c0e7d000ed9..657329a4bb6a8 100644 --- a/package.json +++ b/package.json @@ -535,6 +535,7 @@ "@kbn/navigation-plugin": "link:src/plugins/navigation", "@kbn/newsfeed-plugin": "link:src/plugins/newsfeed", "@kbn/newsfeed-test-plugin": "link:test/common/plugins/newsfeed", + "@kbn/no-data-page-plugin": "link:src/plugins/no_data_page", "@kbn/notifications-plugin": "link:x-pack/plugins/notifications", "@kbn/object-versioning": "link:packages/kbn-object-versioning", "@kbn/observability-ai-assistant-plugin": "link:x-pack/plugins/observability_ai_assistant", diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 536b3f883cac6..dc07f316c5244 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -96,6 +96,7 @@ pageLoadAssetSize: monitoring: 80000 navigation: 37269 newsfeed: 42228 + noDataPage: 5000 observability: 115443 observabilityAIAssistant: 25000 observabilityOnboarding: 19573 diff --git a/packages/shared-ux/card/no_data/impl/src/no_data_card.tsx b/packages/shared-ux/card/no_data/impl/src/no_data_card.tsx index 22126c6b335e0..2fd29d42224ee 100644 --- a/packages/shared-ux/card/no_data/impl/src/no_data_card.tsx +++ b/packages/shared-ux/card/no_data/impl/src/no_data_card.tsx @@ -35,7 +35,9 @@ export const NoDataCard = ({ href: srcHref, category, description, ...props }: P return ( <RedirectAppLinksContainer> - <Component {...{ ...props, href, canAccessFleet, description }} /> + <Component + {...{ ...props, href, canAccessFleet: props.canAccessFleet ?? canAccessFleet, description }} + /> </RedirectAppLinksContainer> ); }; diff --git a/packages/shared-ux/card/no_data/types/index.d.ts b/packages/shared-ux/card/no_data/types/index.d.ts index 5b2a0b090ffe2..e52843b160639 100644 --- a/packages/shared-ux/card/no_data/types/index.d.ts +++ b/packages/shared-ux/card/no_data/types/index.d.ts @@ -79,4 +79,4 @@ export type NoDataCardComponentProps = Partial< /** * Props for the `NoDataCard` sevice-connected component. */ -export type NoDataCardProps = Omit<NoDataCardComponentProps, 'canAccessFleet'>; +export type NoDataCardProps = NoDataCardComponentProps; diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.test.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.test.tsx index 1f657f642fc47..4e16dd6c38bc0 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.test.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.test.tsx @@ -10,7 +10,10 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { I18nProvider } from '@kbn/i18n-react'; + import { KibanaNoDataPage } from '@kbn/shared-ux-page-kibana-no-data'; +import { render, screen } from '@testing-library/react'; import { AnalyticsNoDataPage } from './analytics_no_data_page.component'; import { AnalyticsNoDataPageProvider } from './services'; @@ -28,6 +31,7 @@ describe('AnalyticsNoDataPageComponent', () => { onDataViewCreated={onDataViewCreated} kibanaGuideDocLink={'http://www.test.com'} showPlainSpinner={false} + prependBasePath={(path: string) => path} /> </AnalyticsNoDataPageProvider> ); @@ -52,6 +56,7 @@ describe('AnalyticsNoDataPageComponent', () => { kibanaGuideDocLink={'http://www.test.com'} allowAdHocDataView={true} showPlainSpinner={false} + prependBasePath={(path: string) => path} /> </AnalyticsNoDataPageProvider> ); @@ -61,4 +66,86 @@ describe('AnalyticsNoDataPageComponent', () => { expect(component.find(KibanaNoDataPage).length).toBe(1); expect(component.find(KibanaNoDataPage).props().allowAdHocDataView).toBe(true); }); + + describe('no data state', () => { + describe('kibana flavor', () => { + it('renders add integrations card', async () => { + render( + <I18nProvider> + <AnalyticsNoDataPageProvider {...{ ...services, hasESData: async () => false }}> + <AnalyticsNoDataPage + onDataViewCreated={onDataViewCreated} + kibanaGuideDocLink={'http://www.test.com'} + showPlainSpinner={false} + prependBasePath={(path: string) => path} + /> + </AnalyticsNoDataPageProvider> + </I18nProvider> + ); + + await screen.findByTestId('kbnOverviewAddIntegrations'); + await screen.getAllByText('Add integrations'); + }); + + it('renders disabled add integrations card when fleet is not available', async () => { + render( + <I18nProvider> + <AnalyticsNoDataPageProvider + {...{ ...services, hasESData: async () => false, canAccessFleet: false }} + > + <AnalyticsNoDataPage + onDataViewCreated={onDataViewCreated} + kibanaGuideDocLink={'http://www.test.com'} + showPlainSpinner={false} + prependBasePath={(path: string) => path} + /> + </AnalyticsNoDataPageProvider> + </I18nProvider> + ); + + await screen.findByTestId('kbnOverviewAddIntegrations'); + await screen.getByText('Contact your administrator'); + }); + }); + + describe('serverless_search flavor', () => { + it('renders getting started card', async () => { + render( + <I18nProvider> + <AnalyticsNoDataPageProvider {...{ ...services, hasESData: async () => false }}> + <AnalyticsNoDataPage + pageFlavor={'serverless_search'} + onDataViewCreated={onDataViewCreated} + kibanaGuideDocLink={'http://www.test.com'} + showPlainSpinner={false} + prependBasePath={(path: string) => path} + /> + </AnalyticsNoDataPageProvider> + </I18nProvider> + ); + + await screen.findByTestId('kbnOverviewElasticsearchGettingStarted'); + }); + + it('renders the same getting started card when fleet is not available', async () => { + render( + <I18nProvider> + <AnalyticsNoDataPageProvider + {...{ ...services, hasESData: async () => false, canAccessFleet: false }} + > + <AnalyticsNoDataPage + onDataViewCreated={onDataViewCreated} + kibanaGuideDocLink={'http://www.test.com'} + showPlainSpinner={false} + prependBasePath={(path: string) => path} + pageFlavor={'serverless_search'} + /> + </AnalyticsNoDataPageProvider> + </I18nProvider> + ); + + await screen.findByTestId('kbnOverviewElasticsearchGettingStarted'); + }); + }); + }); }); diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx index d67cb082f5539..4c22a0acb2475 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx @@ -8,6 +8,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { KibanaNoDataPage } from '@kbn/shared-ux-page-kibana-no-data'; +import { KibanaNoDataPageProps } from '@kbn/shared-ux-page-kibana-no-data-types'; +import { AnalyticsNoDataPageFlavor } from '@kbn/shared-ux-page-analytics-no-data-types'; /** * Props for the pure component. @@ -21,26 +23,63 @@ export interface Props { allowAdHocDataView?: boolean; /** if the kibana instance is customly branded */ showPlainSpinner: boolean; + /** The flavor of the empty page to use. */ + pageFlavor?: AnalyticsNoDataPageFlavor; + prependBasePath: (path: string) => string; } -const solution = i18n.translate('sharedUXPackages.noDataConfig.analytics', { - defaultMessage: 'Analytics', -}); - -const pageTitle = i18n.translate('sharedUXPackages.noDataConfig.analyticsPageTitle', { - defaultMessage: 'Welcome to Analytics!', -}); - -const addIntegrationsTitle = i18n.translate('sharedUXPackages.noDataConfig.addIntegrationsTitle', { - defaultMessage: 'Add integrations', -}); - -const addIntegrationsDescription = i18n.translate( - 'sharedUXPackages.noDataConfig.addIntegrationsDescription', - { - defaultMessage: 'Use Elastic Agent to collect data and build out Analytics solutions.', - } -); +const flavors: { + [K in AnalyticsNoDataPageFlavor]: (deps: { + kibanaGuideDocLink: string; + prependBasePath: (path: string) => string; + }) => KibanaNoDataPageProps['noDataConfig']; +} = { + kibana: ({ kibanaGuideDocLink }) => ({ + solution: i18n.translate('sharedUXPackages.noDataConfig.analytics', { + defaultMessage: 'Analytics', + }), + pageTitle: i18n.translate('sharedUXPackages.noDataConfig.analyticsPageTitle', { + defaultMessage: 'Welcome to Analytics!', + }), + logo: 'logoKibana', + action: { + elasticAgent: { + title: i18n.translate('sharedUXPackages.noDataConfig.addIntegrationsTitle', { + defaultMessage: 'Add integrations', + }), + description: i18n.translate('sharedUXPackages.noDataConfig.addIntegrationsDescription', { + defaultMessage: 'Use Elastic Agent to collect data and build out Analytics solutions.', + }), + 'data-test-subj': 'kbnOverviewAddIntegrations', + }, + }, + docsLink: kibanaGuideDocLink, + }), + serverless_search: ({ prependBasePath }) => ({ + solution: i18n.translate('sharedUXPackages.noDataConfig.elasticsearch', { + defaultMessage: 'Elasticsearch', + }), + pageTitle: i18n.translate('sharedUXPackages.noDataConfig.elasticsearchPageTitle', { + defaultMessage: 'Welcome to Elasticsearch!', + }), + logo: 'logoElasticsearch', + action: { + elasticsearch: { + title: i18n.translate('sharedUXPackages.noDataConfig.elasticsearchTitle', { + defaultMessage: 'Get started', + }), + description: i18n.translate('sharedUXPackages.noDataConfig.elasticsearchDescription', { + defaultMessage: + 'Set up your programming language client, ingest some data, and start searching.', + }), + 'data-test-subj': 'kbnOverviewElasticsearchGettingStarted', + href: prependBasePath('/app/elasticsearch/'), + /** force the no data card to be shown **/ + canAccessFleet: true, + }, + }, + }), +}; /** * A pure component of an entire page that can be displayed when Kibana "has no data", specifically for Analytics. @@ -50,20 +89,13 @@ export const AnalyticsNoDataPage = ({ onDataViewCreated, allowAdHocDataView, showPlainSpinner, + prependBasePath, + pageFlavor = 'kibana', }: Props) => { - const noDataConfig = { - solution, - pageTitle, - logo: 'logoKibana', - action: { - elasticAgent: { - title: addIntegrationsTitle, - description: addIntegrationsDescription, - 'data-test-subj': 'kbnOverviewAddIntegrations', - }, - }, - docsLink: kibanaGuideDocLink, - }; + const noDataConfig: KibanaNoDataPageProps['noDataConfig'] = flavors[pageFlavor]({ + kibanaGuideDocLink, + prependBasePath, + }); return ( <KibanaNoDataPage diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.test.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.test.tsx index c73f61e6c0e82..6a8eb777db73b 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.test.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.test.tsx @@ -41,6 +41,8 @@ describe('AnalyticsNoDataPage', () => { expect(component.find(Component).props().kibanaGuideDocLink).toBe(services.kibanaGuideDocLink); expect(component.find(Component).props().onDataViewCreated).toBe(onDataViewCreated); expect(component.find(Component).props().allowAdHocDataView).toBe(true); + expect(component.find(Component).props().prependBasePath).toBe(services.prependBasePath); + expect(component.find(Component).props().pageFlavor).toBe(services.pageFlavor); }); it('passes correct boolean value to showPlainSpinner', () => { diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx index 9b600c374dd02..e9d3ee318d3fd 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx @@ -21,7 +21,7 @@ export const AnalyticsNoDataPage = ({ allowAdHocDataView, }: AnalyticsNoDataPageProps) => { const services = useServices(); - const { kibanaGuideDocLink, customBranding } = services; + const { kibanaGuideDocLink, customBranding, prependBasePath, pageFlavor } = services; const { hasCustomBranding$ } = customBranding; const showPlainSpinner = useObservable(hasCustomBranding$) ?? false; @@ -32,6 +32,8 @@ export const AnalyticsNoDataPage = ({ allowAdHocDataView, kibanaGuideDocLink, showPlainSpinner, + prependBasePath, + pageFlavor, }} /> ); diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/services.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/services.tsx index 991893aeca501..4d514ba032ec9 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/services.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/services.tsx @@ -27,10 +27,10 @@ export const AnalyticsNoDataPageProvider: FC<AnalyticsNoDataPageServices> = ({ children, ...services }) => { - const { kibanaGuideDocLink, customBranding } = services; + const { kibanaGuideDocLink, customBranding, prependBasePath, pageFlavor } = services; return ( - <Context.Provider value={{ kibanaGuideDocLink, customBranding }}> + <Context.Provider value={{ kibanaGuideDocLink, customBranding, prependBasePath, pageFlavor }}> <KibanaNoDataPageProvider {...services}>{children}</KibanaNoDataPageProvider> </Context.Provider> ); @@ -48,6 +48,8 @@ export const AnalyticsNoDataPageKibanaProvider: FC<AnalyticsNoDataPageKibanaDepe customBranding: { hasCustomBranding$: dependencies.coreStart.customBranding.hasCustomBranding$, }, + prependBasePath: dependencies.coreStart.http.basePath.prepend, + pageFlavor: dependencies.noDataPage?.getAnalyticsNoDataPageFlavor() ?? 'kibana', }; return ( <Context.Provider {...{ value }}> diff --git a/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json b/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json index 6a78f24dff0f7..4b9192a9fd714 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json +++ b/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json @@ -19,6 +19,8 @@ "@kbn/shared-ux-page-analytics-no-data-types", "@kbn/test-jest-helpers", "@kbn/shared-ux-page-analytics-no-data-mocks", + "@kbn/shared-ux-page-kibana-no-data-types", + "@kbn/i18n-react", ], "exclude": [ "target/**/*", diff --git a/packages/shared-ux/page/analytics_no_data/mocks/src/jest.ts b/packages/shared-ux/page/analytics_no_data/mocks/src/jest.ts index 98885d55ba47d..f45d0f72ffed9 100644 --- a/packages/shared-ux/page/analytics_no_data/mocks/src/jest.ts +++ b/packages/shared-ux/page/analytics_no_data/mocks/src/jest.ts @@ -15,6 +15,8 @@ export const getServicesMock = () => { ...getKibanaNoDataPageServicesMock(), kibanaGuideDocLink: 'Kibana guide', customBranding: { hasCustomBranding$: of(false) }, + prependBasePath: (path) => path, + pageFlavor: 'kibana', }; return services; @@ -26,6 +28,8 @@ export const getServicesMockCustomBranding = () => { // this mock will have custom branding set to true customBranding: { hasCustomBranding$: of(true) }, kibanaGuideDocLink: 'Kibana guide', + prependBasePath: (path) => path, + pageFlavor: 'kibana', }; return services; diff --git a/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts b/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts index 86bf25dbde9e9..6bb3f07e34a87 100644 --- a/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts +++ b/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts @@ -51,6 +51,8 @@ export class StorybookMock extends AbstractStorybookMock< customBranding: { hasCustomBranding$: of(false), }, + pageFlavor: 'kibana', + prependBasePath: (path) => path, ...kibanaNoDataMock.getServices(params), }; } diff --git a/packages/shared-ux/page/analytics_no_data/types/index.d.ts b/packages/shared-ux/page/analytics_no_data/types/index.d.ts index 4e54315f071dd..f292e297b6fdc 100644 --- a/packages/shared-ux/page/analytics_no_data/types/index.d.ts +++ b/packages/shared-ux/page/analytics_no_data/types/index.d.ts @@ -17,6 +17,8 @@ import { Observable } from 'rxjs'; export interface Services { kibanaGuideDocLink: string; customBranding: { hasCustomBranding$: Observable<boolean> }; + prependBasePath: (path: string) => string; + pageFlavor: AnalyticsNoDataPageFlavor; } /** @@ -24,6 +26,8 @@ export interface Services { */ export type AnalyticsNoDataPageServices = Services & KibanaNoDataPageServices; +export type AnalyticsNoDataPageFlavor = 'kibana' | 'serverless_search'; + export interface KibanaDependencies { coreStart: { docLinks: { @@ -36,6 +40,14 @@ export interface KibanaDependencies { customBranding: { hasCustomBranding$: Observable<boolean>; }; + http: { + basePath: { + prepend: (path: string) => string; + }; + }; + }; + noDataPage?: { + getAnalyticsNoDataPageFlavor: () => AnalyticsNoDataPageFlavor; }; } diff --git a/packages/shared-ux/page/no_data/impl/src/no_data_page.tsx b/packages/shared-ux/page/no_data/impl/src/no_data_page.tsx index 1ba9b18049e87..5aec81d942de6 100644 --- a/packages/shared-ux/page/no_data/impl/src/no_data_page.tsx +++ b/packages/shared-ux/page/no_data/impl/src/no_data_page.tsx @@ -33,13 +33,13 @@ export const NoDataPage = ({ values: { solution }, }); - const link = ( + const link = docsLink ? ( <EuiLink href={docsLink} target="_blank"> <FormattedMessage id="sharedUXPackages.noDataPage.intro.link" defaultMessage="learn more" /> </EuiLink> - ); + ) : null; - const message = ( + const message = link ? ( <FormattedMessage id="sharedUXPackages.noDataPage.intro" defaultMessage="Add your data to get started, or {link} about {solution}." @@ -48,6 +48,11 @@ export const NoDataPage = ({ link, }} /> + ) : ( + <FormattedMessage + id="sharedUXPackages.noDataPage.introNoDocLink" + defaultMessage="Add your data to get started." + /> ); return ( diff --git a/packages/shared-ux/page/no_data/types/index.d.ts b/packages/shared-ux/page/no_data/types/index.d.ts index 3db9e80c950c9..6f29e5ab08d7a 100644 --- a/packages/shared-ux/page/no_data/types/index.d.ts +++ b/packages/shared-ux/page/no_data/types/index.d.ts @@ -31,9 +31,9 @@ export interface NoDataPageProps extends CommonProps, ActionCardProps { */ solution: string; /** - * Required to set the docs link for the whole solution + * Required in "kibana" flavor to set the docs link for the whole solution, otherwise optional */ - docsLink: string; + docsLink?: string; /** * Optionally replace the auto-generated logo */ diff --git a/src/plugins/dashboard/kibana.jsonc b/src/plugins/dashboard/kibana.jsonc index c22d68173deb6..0f8601cb96c5d 100644 --- a/src/plugins/dashboard/kibana.jsonc +++ b/src/plugins/dashboard/kibana.jsonc @@ -34,7 +34,8 @@ "screenshotMode", "usageCollection", "taskManager", - "serverless" + "serverless", + "noDataPage" ], "requiredBundles": ["kibanaReact", "kibanaUtils", "presentationUtil"] } diff --git a/src/plugins/dashboard/public/dashboard_app/no_data/dashboard_app_no_data.tsx b/src/plugins/dashboard/public/dashboard_app/no_data/dashboard_app_no_data.tsx index fb04a3187c72c..8580ae2f168d3 100644 --- a/src/plugins/dashboard/public/dashboard_app/no_data/dashboard_app_no_data.tsx +++ b/src/plugins/dashboard/public/dashboard_app/no_data/dashboard_app_no_data.tsx @@ -26,6 +26,7 @@ export const DashboardAppNoDataPage = ({ http: { basePath }, documentationLinks: { indexPatternsDocLink, kibanaGuideDocLink }, customBranding, + noDataPage, } = pluginServices.getServices(); const analyticsServices = { @@ -44,6 +45,7 @@ export const DashboardAppNoDataPage = ({ }, dataViews, dataViewEditor, + noDataPage, }; return ( <AnalyticsNoDataPageKibanaProvider {...analyticsServices}> diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index a28dbe9c45ae7..d2802a8ef3b6d 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -52,6 +52,7 @@ import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plu import type { UrlForwardingSetup, UrlForwardingStart } from '@kbn/url-forwarding-plugin/public'; import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import { CustomBrandingStart } from '@kbn/core-custom-branding-browser'; import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; @@ -108,6 +109,7 @@ export interface DashboardStartDependencies { visualizations: VisualizationsStart; customBranding: CustomBrandingStart; serverless?: ServerlessPluginStart; + noDataPage?: NoDataPagePluginStart; } export interface DashboardSetup { diff --git a/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.stub.ts b/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.stub.ts new file mode 100644 index 0000000000000..c1af1452176a8 --- /dev/null +++ b/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.stub.ts @@ -0,0 +1,16 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { PluginServiceFactory } from '@kbn/presentation-util-plugin/public'; +import { NoDataPageService } from './types'; + +export type NoDataPageServiceFactory = PluginServiceFactory<NoDataPageService>; + +export const noDataPageServiceFactory: NoDataPageServiceFactory = () => { + return { getAnalyticsNoDataPageFlavor: () => 'kibana' }; +}; diff --git a/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.ts b/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.ts new file mode 100644 index 0000000000000..f1dded3f12ff3 --- /dev/null +++ b/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.ts @@ -0,0 +1,24 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { KibanaPluginServiceFactory } from '@kbn/presentation-util-plugin/public'; +import { DashboardStartDependencies } from '../../plugin'; +import { NoDataPageService } from './types'; + +export type NoDataPageServiceFactory = KibanaPluginServiceFactory< + NoDataPageService, + DashboardStartDependencies +>; + +export const noDataPageServiceFactory: NoDataPageServiceFactory = ({ startPlugins }) => { + const { noDataPage } = startPlugins; + + return { + getAnalyticsNoDataPageFlavor: noDataPage?.getAnalyticsNoDataPageFlavor ?? (() => 'kibana'), + }; +}; diff --git a/src/plugins/dashboard/public/services/no_data_page/types.ts b/src/plugins/dashboard/public/services/no_data_page/types.ts new file mode 100644 index 0000000000000..7e87f1586db33 --- /dev/null +++ b/src/plugins/dashboard/public/services/no_data_page/types.ts @@ -0,0 +1,13 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; + +export interface NoDataPageService { + getAnalyticsNoDataPageFlavor: NoDataPagePluginStart['getAnalyticsNoDataPageFlavor']; +} diff --git a/src/plugins/dashboard/public/services/plugin_services.stub.ts b/src/plugins/dashboard/public/services/plugin_services.stub.ts index 0ae4159ed2128..8ba55d486d75b 100644 --- a/src/plugins/dashboard/public/services/plugin_services.stub.ts +++ b/src/plugins/dashboard/public/services/plugin_services.stub.ts @@ -42,6 +42,7 @@ import { customBrandingServiceFactory } from './custom_branding/custom_branding. import { savedObjectsManagementServiceFactory } from './saved_objects_management/saved_objects_management_service.stub'; import { contentManagementServiceFactory } from './content_management/content_management_service.stub'; import { serverlessServiceFactory } from './serverless/serverless_service.stub'; +import { noDataPageServiceFactory } from './no_data_page/no_data_page_service.stub'; export const providers: PluginServiceProviders<DashboardServices> = { dashboardContentManagement: new PluginServiceProvider(dashboardContentManagementServiceFactory), @@ -72,6 +73,7 @@ export const providers: PluginServiceProviders<DashboardServices> = { savedObjectsManagement: new PluginServiceProvider(savedObjectsManagementServiceFactory), contentManagement: new PluginServiceProvider(contentManagementServiceFactory), serverless: new PluginServiceProvider(serverlessServiceFactory), + noDataPage: new PluginServiceProvider(noDataPageServiceFactory), }; export const registry = new PluginServiceRegistry<DashboardServices>(providers); diff --git a/src/plugins/dashboard/public/services/plugin_services.ts b/src/plugins/dashboard/public/services/plugin_services.ts index d84b55d0ff4a1..f16b4c8f34b0e 100644 --- a/src/plugins/dashboard/public/services/plugin_services.ts +++ b/src/plugins/dashboard/public/services/plugin_services.ts @@ -43,6 +43,7 @@ import { savedObjectsManagementServiceFactory } from './saved_objects_management import { dashboardContentManagementServiceFactory } from './dashboard_content_management/dashboard_content_management_service'; import { contentManagementServiceFactory } from './content_management/content_management_service'; import { serverlessServiceFactory } from './serverless/serverless_service'; +import { noDataPageServiceFactory } from './no_data_page/no_data_page_service'; const providers: PluginServiceProviders<DashboardServices, DashboardPluginServiceParams> = { dashboardContentManagement: new PluginServiceProvider(dashboardContentManagementServiceFactory, [ @@ -86,6 +87,7 @@ const providers: PluginServiceProviders<DashboardServices, DashboardPluginServic savedObjectsManagement: new PluginServiceProvider(savedObjectsManagementServiceFactory), contentManagement: new PluginServiceProvider(contentManagementServiceFactory), serverless: new PluginServiceProvider(serverlessServiceFactory), + noDataPage: new PluginServiceProvider(noDataPageServiceFactory), }; export const pluginServices = new PluginServices<DashboardServices>(); diff --git a/src/plugins/dashboard/public/services/types.ts b/src/plugins/dashboard/public/services/types.ts index 13adaf6098070..5ad3aab951121 100644 --- a/src/plugins/dashboard/public/services/types.ts +++ b/src/plugins/dashboard/public/services/types.ts @@ -38,6 +38,7 @@ import { DashboardUrlForwardingService } from './url_forwarding/types'; import { DashboardUsageCollectionService } from './usage_collection/types'; import { DashboardVisualizationsService } from './visualizations/types'; import { DashboardServerlessService } from './serverless/types'; +import { NoDataPageService } from './no_data_page/types'; export type DashboardPluginServiceParams = KibanaPluginServiceParams<DashboardStartDependencies> & { initContext: PluginInitializerContext; // need a custom type so that initContext is a required parameter for initializerContext @@ -72,4 +73,5 @@ export interface DashboardServices { savedObjectsManagement: SavedObjectsManagementPluginStart; contentManagement: ContentManagementPublicStart; serverless: DashboardServerlessService; // TODO: make this optional in follow up + noDataPage: NoDataPageService; } diff --git a/src/plugins/dashboard/tsconfig.json b/src/plugins/dashboard/tsconfig.json index 9d5dafa47c88a..31cc2b1aab236 100644 --- a/src/plugins/dashboard/tsconfig.json +++ b/src/plugins/dashboard/tsconfig.json @@ -64,7 +64,8 @@ "@kbn/content-management-table-list-view-table", "@kbn/shared-ux-prompt-not-found", "@kbn/content-management-content-editor", - "@kbn/serverless" + "@kbn/serverless", + "@kbn/no-data-page-plugin" ], "exclude": ["target/**/*"] } diff --git a/src/plugins/discover/kibana.jsonc b/src/plugins/discover/kibana.jsonc index 1c6ffaae833cb..3da4912dd5661 100644 --- a/src/plugins/discover/kibana.jsonc +++ b/src/plugins/discover/kibana.jsonc @@ -26,7 +26,7 @@ "expressions", "unifiedSearch", "unifiedHistogram", - "contentManagement", + "contentManagement" ], "optionalPlugins": [ "home", @@ -36,7 +36,8 @@ "triggersActionsUi", "savedObjectsTaggingOss", "lens", - "serverless" + "serverless", + "noDataPage" ], "requiredBundles": ["kibanaUtils", "kibanaReact", "unifiedSearch"], "extraPublicDirs": ["common"] diff --git a/src/plugins/discover/public/application/main/discover_main_route.tsx b/src/plugins/discover/public/application/main/discover_main_route.tsx index cf62f96ca7d1a..febda09ebb939 100644 --- a/src/plugins/discover/public/application/main/discover_main_route.tsx +++ b/src/plugins/discover/public/application/main/discover_main_route.tsx @@ -48,11 +48,7 @@ export interface MainRouteProps { mode?: DiscoverDisplayMode; } -export function DiscoverMainRoute({ - customizationCallbacks, - isDev, - mode = 'standalone', -}: MainRouteProps) { +export function DiscoverMainRoute({ customizationCallbacks, mode = 'standalone' }: MainRouteProps) { const history = useHistory(); const services = useDiscoverServices(); const { @@ -109,7 +105,7 @@ export function DiscoverMainRoute({ const hasUserDataViewValue = await data.dataViews.hasData .hasUserDataView() .catch(() => false); - const hasESDataValue = isDev || (await data.dataViews.hasData.hasESData().catch(() => false)); + const hasESDataValue = await data.dataViews.hasData.hasESData().catch(() => false); setHasUserDataView(hasUserDataViewValue); setHasESData(hasESDataValue); @@ -134,7 +130,7 @@ export function DiscoverMainRoute({ setError(e); return false; } - }, [data.dataViews, isDev, savedSearchId]); + }, [data.dataViews, savedSearchId]); const loadSavedSearch = useCallback( async (nextDataView?: DataView) => { @@ -256,11 +252,12 @@ export function DiscoverMainRoute({ // We've already called this, so we can optimize the analytics services to // use the already-retrieved data to avoid a double-call. - hasESData: () => Promise.resolve(isDev ? true : hasESData), + hasESData: () => Promise.resolve(hasESData), hasUserDataView: () => Promise.resolve(hasUserDataView), }, }, dataViewEditor, + noDataPage: services.noDataPage, }; return ( diff --git a/src/plugins/discover/public/build_services.ts b/src/plugins/discover/public/build_services.ts index 254292e6d07e6..65cd9c06e84c7 100644 --- a/src/plugins/discover/public/build_services.ts +++ b/src/plugins/discover/public/build_services.ts @@ -53,6 +53,7 @@ import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import type { SettingsStart } from '@kbn/core-ui-settings-browser'; import type { ContentClient } from '@kbn/content-management-plugin/public'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import { getHistory } from './kibana_services'; import { DiscoverStartPlugins } from './plugin'; import { DiscoverContextAppLocator } from './application/context/services/locator'; @@ -111,6 +112,7 @@ export interface DiscoverServices { uiActions: UiActionsStart; contentClient: ContentClient; serverless?: ServerlessPluginStart; + noDataPage?: NoDataPagePluginStart; } export const buildServices = memoize(function ( @@ -171,5 +173,6 @@ export const buildServices = memoize(function ( uiActions: plugins.uiActions, contentClient: plugins.contentManagement.client, serverless: plugins.serverless, + noDataPage: plugins.noDataPage, }; }); diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx index 6db46f53c35fb..c3b92275d3956 100644 --- a/src/plugins/discover/public/plugin.tsx +++ b/src/plugins/discover/public/plugin.tsx @@ -46,6 +46,7 @@ import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public'; import type { LensPublicStart } from '@kbn/lens-plugin/public'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; import { DOC_TABLE_LEGACY, TRUNCATE_MAX_HEIGHT } from '@kbn/discover-utils'; +import { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import { PLUGIN_ID } from '../common'; import { DocViewInput, DocViewInputFn } from './services/doc_views/doc_views_types'; import { DocViewsRegistry } from './services/doc_views/doc_views_registry'; @@ -213,6 +214,7 @@ export interface DiscoverStartPlugins { lens: LensPublicStart; contentManagement: ContentManagementPublicStart; serverless?: ServerlessPluginStart; + noDataPage?: NoDataPagePluginStart; } /** diff --git a/src/plugins/discover/tsconfig.json b/src/plugins/discover/tsconfig.json index df92ba4c9070c..8e93218385709 100644 --- a/src/plugins/discover/tsconfig.json +++ b/src/plugins/discover/tsconfig.json @@ -70,7 +70,8 @@ "@kbn/content-management-plugin", "@kbn/serverless", "@kbn/react-kibana-mount", - "@kbn/react-kibana-context-render" + "@kbn/react-kibana-context-render", + "@kbn/no-data-page-plugin" ], "exclude": [ "target/**/*" diff --git a/src/plugins/no_data_page/README.md b/src/plugins/no_data_page/README.md new file mode 100755 index 0000000000000..a516e3274ff3f --- /dev/null +++ b/src/plugins/no_data_page/README.md @@ -0,0 +1,3 @@ +# No Data Page + +Helps to globally configure the no data page components diff --git a/src/plugins/no_data_page/config.ts b/src/plugins/no_data_page/config.ts new file mode 100644 index 0000000000000..8fae1aad10aaa --- /dev/null +++ b/src/plugins/no_data_page/config.ts @@ -0,0 +1,19 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { schema, TypeOf, offeringBasedSchema } from '@kbn/config-schema'; + +export const configSchema = schema.object({ + analyticsNoDataPageFlavor: offeringBasedSchema({ + serverless: schema.oneOf( + [schema.oneOf([schema.literal('kibana'), schema.literal('serverless_search')])], + { defaultValue: 'kibana' as const } + ), + }), +}); +export type NoDataPageConfig = TypeOf<typeof configSchema>; diff --git a/src/plugins/no_data_page/jest.config.js b/src/plugins/no_data_page/jest.config.js new file mode 100644 index 0000000000000..546031bc12414 --- /dev/null +++ b/src/plugins/no_data_page/jest.config.js @@ -0,0 +1,16 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['<rootDir>/src/plugins/no_data_page'], + coverageDirectory: '<rootDir>/target/kibana-coverage/jest/src/plugins/no_data_page', + coverageReporters: ['text', 'html'], + collectCoverageFrom: ['<rootDir>/src/plugins/no_data_page/{common,public,server}/**/*.{ts,tsx}'], +}; diff --git a/src/plugins/no_data_page/kibana.jsonc b/src/plugins/no_data_page/kibana.jsonc new file mode 100644 index 0000000000000..202917173b7a4 --- /dev/null +++ b/src/plugins/no_data_page/kibana.jsonc @@ -0,0 +1,10 @@ +{ + "type": "plugin", + "id": "@kbn/no-data-page-plugin", + "owner": "@elastic/appex-sharedux", + "plugin": { + "id": "noDataPage", + "server": true, + "browser": true + } +} diff --git a/src/plugins/no_data_page/public/index.ts b/src/plugins/no_data_page/public/index.ts new file mode 100644 index 0000000000000..28dfcd6044403 --- /dev/null +++ b/src/plugins/no_data_page/public/index.ts @@ -0,0 +1,16 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { PluginInitializerContext } from '@kbn/core-plugins-browser'; +import { NoDataPagePlugin } from './plugin'; + +export function plugin(ctx: PluginInitializerContext) { + return new NoDataPagePlugin(ctx); +} + +export type { NoDataPagePluginSetup, NoDataPagePluginStart } from './types'; diff --git a/src/plugins/no_data_page/public/plugin.ts b/src/plugins/no_data_page/public/plugin.ts new file mode 100644 index 0000000000000..740f796f4f395 --- /dev/null +++ b/src/plugins/no_data_page/public/plugin.ts @@ -0,0 +1,31 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public'; +import type { NoDataPagePluginSetup, NoDataPagePluginStart } from './types'; +import type { NoDataPageConfig } from '../config'; + +export class NoDataPagePlugin implements Plugin<NoDataPagePluginSetup> { + constructor(private initializerContext: PluginInitializerContext<NoDataPageConfig>) {} + + public setup(core: CoreSetup): NoDataPagePluginSetup { + return { + getAnalyticsNoDataPageFlavor: () => { + return this.initializerContext.config.get().analyticsNoDataPageFlavor; + }, + }; + } + + public start(core: CoreStart): NoDataPagePluginStart { + return { + getAnalyticsNoDataPageFlavor: () => { + return this.initializerContext.config.get().analyticsNoDataPageFlavor; + }, + }; + } +} diff --git a/src/plugins/no_data_page/public/types.ts b/src/plugins/no_data_page/public/types.ts new file mode 100644 index 0000000000000..c9523f7fcd93a --- /dev/null +++ b/src/plugins/no_data_page/public/types.ts @@ -0,0 +1,13 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +export interface NoDataPagePluginSetup { + getAnalyticsNoDataPageFlavor: () => 'kibana' | 'serverless_search'; +} + +export type NoDataPagePluginStart = NoDataPagePluginSetup; diff --git a/src/plugins/no_data_page/server/index.ts b/src/plugins/no_data_page/server/index.ts new file mode 100644 index 0000000000000..ba02a016a9676 --- /dev/null +++ b/src/plugins/no_data_page/server/index.ts @@ -0,0 +1,25 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { PluginConfigDescriptor } from '@kbn/core-plugins-server'; + +import { configSchema, NoDataPageConfig } from '../config'; + +export const config: PluginConfigDescriptor<NoDataPageConfig> = { + exposeToBrowser: { + analyticsNoDataPageFlavor: true, + }, + schema: configSchema, +}; + +export function plugin() { + return new (class NoDataPagePlugin { + setup() {} + start() {} + })(); +} diff --git a/src/plugins/no_data_page/tsconfig.json b/src/plugins/no_data_page/tsconfig.json new file mode 100644 index 0000000000000..bab1c8c23edfb --- /dev/null +++ b/src/plugins/no_data_page/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types" + }, + "include": ["common/**/*", "public/**/*", "server/**/*", "config.ts"], + "kbn_references": [ + "@kbn/core", + "@kbn/core-plugins-browser", + "@kbn/core-plugins-server", + "@kbn/config-schema", + ], + "exclude": ["target/**/*"] +} diff --git a/src/plugins/visualizations/kibana.jsonc b/src/plugins/visualizations/kibana.jsonc index 22c6bd9dd32b2..69caa82b50030 100644 --- a/src/plugins/visualizations/kibana.jsonc +++ b/src/plugins/visualizations/kibana.jsonc @@ -34,7 +34,8 @@ "share", "spaces", "savedObjectsTaggingOss", - "serverless" + "serverless", + "noDataPage" ], "requiredBundles": [ "kibanaUtils", diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index 3ca1672159f24..d2805b43ed468 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -64,6 +64,7 @@ import { ContentManagementPublicSetup, ContentManagementPublicStart, } from '@kbn/content-management-plugin/public'; +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import type { TypesSetup, TypesStart } from './vis_types'; import type { VisualizeServices } from './visualize_app/types'; import { @@ -166,6 +167,7 @@ export interface VisualizationsStartDeps { savedObjectsManagement: SavedObjectsManagementPluginStart; contentManagement: ContentManagementPublicStart; serverless?: ServerlessPluginStart; + noDataPage?: NoDataPagePluginStart; } /** @@ -330,6 +332,7 @@ export class VisualizationsPlugin listingViewRegistry, unifiedSearch: pluginsStart.unifiedSearch, serverless: pluginsStart.serverless, + noDataPage: pluginsStart.noDataPage, }; params.element.classList.add('visAppWrapper'); diff --git a/src/plugins/visualizations/public/visualize_app/app.tsx b/src/plugins/visualizations/public/visualize_app/app.tsx index 70dd288fccaec..c7c73893eb438 100644 --- a/src/plugins/visualizations/public/visualize_app/app.tsx +++ b/src/plugins/visualizations/public/visualize_app/app.tsx @@ -14,6 +14,7 @@ import { EuiLoadingSpinner } from '@elastic/eui'; import { AppMountParameters, CoreStart } from '@kbn/core/public'; import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public'; import { syncGlobalQueryStateWithUrl } from '@kbn/data-plugin/public'; +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { AnalyticsNoDataPageKibanaProvider, @@ -38,6 +39,7 @@ interface NoDataComponentProps { dataViews: DataViewsContract; dataViewEditor: DataViewEditorStart; onDataViewCreated: (dataView: unknown) => void; + noDataPage?: NoDataPagePluginStart; } const NoDataComponent = ({ @@ -45,11 +47,13 @@ const NoDataComponent = ({ dataViews, dataViewEditor, onDataViewCreated, + noDataPage, }: NoDataComponentProps) => { const analyticsServices = { coreStart: core, dataViews, dataViewEditor, + noDataPage, }; return ( <AnalyticsNoDataPageKibanaProvider {...analyticsServices}> @@ -65,6 +69,7 @@ export const VisualizeApp = ({ onAppLeave }: VisualizeAppProps) => { core, kbnUrlStateStorage, dataViewEditor, + noDataPage, }, } = useKibana<VisualizeServices>(); const { pathname } = useLocation(); @@ -125,6 +130,7 @@ export const VisualizeApp = ({ onAppLeave }: VisualizeAppProps) => { dataViewEditor={dataViewEditor} dataViews={dataViews} onDataViewCreated={onDataViewCreated} + noDataPage={noDataPage} /> ); } diff --git a/src/plugins/visualizations/public/visualize_app/types.ts b/src/plugins/visualizations/public/visualize_app/types.ts index 90806f138f9b6..77f743aaeef77 100644 --- a/src/plugins/visualizations/public/visualize_app/types.ts +++ b/src/plugins/visualizations/public/visualize_app/types.ts @@ -41,6 +41,7 @@ import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public'; import type { SavedSearch, SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import type { Vis, VisualizeEmbeddableContract, @@ -117,6 +118,7 @@ export interface VisualizeServices extends CoreStart { listingViewRegistry: ListingViewRegistry; unifiedSearch: UnifiedSearchPublicPluginStart; serverless?: ServerlessPluginStart; + noDataPage?: NoDataPagePluginStart; } export interface VisInstance { diff --git a/src/plugins/visualizations/tsconfig.json b/src/plugins/visualizations/tsconfig.json index c72d4fd24d7ea..e643d9fa1fd61 100644 --- a/src/plugins/visualizations/tsconfig.json +++ b/src/plugins/visualizations/tsconfig.json @@ -62,7 +62,8 @@ "@kbn/content-management-tabbed-table-list-view", "@kbn/content-management-table-list-view", "@kbn/content-management-utils", - "@kbn/serverless" + "@kbn/serverless", + "@kbn/no-data-page-plugin" ], "exclude": [ "target/**/*", diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index 6e0c4be2faaec..03928a378f6f3 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -145,6 +145,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'newsfeed.mainInterval (duration)', 'newsfeed.service.pathTemplate (string)', 'newsfeed.service.urlRoot (string)', + 'no_data_page.analyticsNoDataPageFlavor (any)', // It's a string (any because schema.conditional) 'telemetry.allowChangingOptInStatus (boolean)', 'telemetry.appendServerlessChannelsSuffix (any)', // It's a boolean (any because schema.conditional) 'telemetry.banner (boolean)', diff --git a/tsconfig.base.json b/tsconfig.base.json index cf7d73b7a5a9c..2efdd91c53d3b 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1028,6 +1028,8 @@ "@kbn/newsfeed-plugin/*": ["src/plugins/newsfeed/*"], "@kbn/newsfeed-test-plugin": ["test/common/plugins/newsfeed"], "@kbn/newsfeed-test-plugin/*": ["test/common/plugins/newsfeed/*"], + "@kbn/no-data-page-plugin": ["src/plugins/no_data_page"], + "@kbn/no-data-page-plugin/*": ["src/plugins/no_data_page/*"], "@kbn/notifications-plugin": ["x-pack/plugins/notifications"], "@kbn/notifications-plugin/*": ["x-pack/plugins/notifications/*"], "@kbn/object-versioning": ["packages/kbn-object-versioning"], diff --git a/x-pack/test_serverless/functional/test_suites/search/empty_page.ts b/x-pack/test_serverless/functional/test_suites/search/empty_page.ts new file mode 100644 index 0000000000000..9808bb69bbeb6 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/search/empty_page.ts @@ -0,0 +1,41 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getPageObject, getService }: FtrProviderContext) { + const svlSearchNavigation = getService('svlSearchNavigation'); + const testSubjects = getService('testSubjects'); + const svlCommonNavigation = getPageObject('svlCommonNavigation'); + + describe('empty pages', function () { + before(async () => { + await svlSearchNavigation.navigateToLandingPage(); + }); + + it('should show search specific empty page in discover', async () => { + await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'discover' }); + await testSubjects.existOrFail('kbnOverviewElasticsearchGettingStarted'); + await testSubjects.click('kbnOverviewElasticsearchGettingStarted'); + await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Getting started' }); + }); + + it('should show search specific empty page in visualize', async () => { + await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'visualize' }); + await testSubjects.existOrFail('kbnOverviewElasticsearchGettingStarted'); + await testSubjects.click('kbnOverviewElasticsearchGettingStarted'); + await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Getting started' }); + }); + + it('should show search specific empty page in dashboards', async () => { + await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'dashboards' }); + await testSubjects.existOrFail('kbnOverviewElasticsearchGettingStarted'); + await testSubjects.click('kbnOverviewElasticsearchGettingStarted'); + await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Getting started' }); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/search/index.ts b/x-pack/test_serverless/functional/test_suites/search/index.ts index 9a3f5de27f16c..e4e3021ef8143 100644 --- a/x-pack/test_serverless/functional/test_suites/search/index.ts +++ b/x-pack/test_serverless/functional/test_suites/search/index.ts @@ -10,6 +10,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('serverless search UI', function () { loadTestFile(require.resolve('./landing_page')); + loadTestFile(require.resolve('./empty_page')); loadTestFile(require.resolve('./navigation')); loadTestFile(require.resolve('./cases/attachment_framework')); }); diff --git a/yarn.lock b/yarn.lock index 774ec13a90362..b3a342acb0eef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4962,6 +4962,10 @@ version "0.0.0" uid "" +"@kbn/no-data-page-plugin@link:src/plugins/no_data_page": + version "0.0.0" + uid "" + "@kbn/notifications-plugin@link:x-pack/plugins/notifications": version "0.0.0" uid "" From ba75f0ba81a4a247f6a7b55da1f1abcae6342c23 Mon Sep 17 00:00:00 2001 From: Jordan <51442161+JordanSh@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:33:33 +0300 Subject: [PATCH 14/49] [Cloud Security] Fix credential type switch (#164939) --- .../aws_credentials_form/aws_credentials_form.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx index 7fafe17113c84..dc2b46dd364fe 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx @@ -235,7 +235,9 @@ export const AwsCredentialsForm = ({ size="m" options={getSetupFormatOptions()} idSelected={setupFormat} - onChange={onSetupFormatChange} + onChange={(idSelected: SetupFormat) => + idSelected !== setupFormat && onSetupFormatChange(idSelected) + } /> <EuiSpacer size="l" /> {setupFormat === 'cloud_formation' && ( From ddaea72bca38b8b7e0fabe9cfe993a815c9d2264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= <soren.louv@elastic.co> Date: Mon, 28 Aug 2023 16:58:18 +0200 Subject: [PATCH 15/49] Add missing sourcemap config (#164779) The source map index is no longer used but should still be declared to avoid breaking existing cluster configurations --- x-pack/plugins/apm_data_access/server/index.ts | 7 ++++++- .../tests/settings/apm_indices/apm_indices.spec.ts | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/apm_data_access/server/index.ts b/x-pack/plugins/apm_data_access/server/index.ts index 4d7ae2b1eb6c3..4ef9a47937733 100644 --- a/x-pack/plugins/apm_data_access/server/index.ts +++ b/x-pack/plugins/apm_data_access/server/index.ts @@ -16,6 +16,7 @@ const configSchema = schema.object({ error: schema.string({ defaultValue: 'logs-apm*,apm-*' }), metric: schema.string({ defaultValue: 'metrics-apm*,apm-*' }), onboarding: schema.string({ defaultValue: 'apm-*' }), // Unused: to be deleted + sourcemap: schema.string({ defaultValue: 'apm-*' }), // Unused: to be deleted }), }); @@ -23,7 +24,11 @@ const configSchema = schema.object({ export const config: PluginConfigDescriptor<APMDataAccessConfig> = { deprecations: ({ renameFromRoot, unused, deprecate }) => [ // deprecations - unused('indices.sourcemap', { level: 'warning' }), + deprecate('indices.sourcemap', 'a future version', { + level: 'warning', + message: `Configuring "xpack.apm.indices.sourcemap" is deprecated and will be removed in a future version. Please remove this setting.`, + }), + deprecate('indices.onboarding', 'a future version', { level: 'warning', message: `Configuring "xpack.apm.indices.onboarding" is deprecated and will be removed in a future version. Please remove this setting.`, diff --git a/x-pack/test/apm_api_integration/tests/settings/apm_indices/apm_indices.spec.ts b/x-pack/test/apm_api_integration/tests/settings/apm_indices/apm_indices.spec.ts index 5aef295ddb324..6798d22af1999 100644 --- a/x-pack/test/apm_api_integration/tests/settings/apm_indices/apm_indices.spec.ts +++ b/x-pack/test/apm_api_integration/tests/settings/apm_indices/apm_indices.spec.ts @@ -49,6 +49,7 @@ export default function apmIndicesTests({ getService }: FtrProviderContext) { error: 'logs-apm*,apm-*', metric: 'metrics-apm*,apm-*', onboarding: 'apm-*', + sourcemap: 'apm-*', }); }); From 59845dc5b8a861b024c2fe8f2de1a455327adae2 Mon Sep 17 00:00:00 2001 From: Juan Pablo Djeredjian <jpdjeredjian@gmail.com> Date: Mon, 28 Aug 2023 17:07:18 +0200 Subject: [PATCH 16/49] [Security Solution] Fix Rule Details page unit test flakiness with business logic refactor (#164825) Fixes: https://github.com/elastic/kibana/issues/147064 ## Summary - `rule_details_ui/pages/rule_details/index.test.tsx` was too heavy and can fail by timeout - The unit test was mounting the whole rule details component to test: - redirection logic - which tabs are visible This PR: - extracts that logic into two new hooks and one component: - `useLegacyUrlRedirect` (for redirection logic) - `useRuleDetailsTabs` (to calculate which tabs should be displayed) - `LegacyUrlConflictCallOut` - adds tests for the two hooks and the component, covering all the logic that was previously covered by the `rule_details_ui/pages/rule_details/index.test.tsx` file - deletes the `rule_details_ui/pages/rule_details/index.test.tsx` file --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../__mocks__/rule_details_context.tsx | 2 +- .../execution_log_table.tsx | 4 +- .../pages/rule_details/index.test.tsx | 455 ------------------ .../pages/rule_details/index.tsx | 137 +----- .../legacy_url_conflict_callout.test.tsx | 113 +++++ .../legacy_url_conflict_callout.tsx | 46 ++ .../rule_details/rule_details_context.tsx | 2 +- .../use_redirect_legacy_url.test.ts | 115 +++++ .../rule_details/use_redirect_legacy_url.ts | 36 ++ .../use_rule_details_tabs.test.tsx | 151 ++++++ .../rule_details/use_rule_details_tabs.tsx | 110 +++++ .../components/exception_item_card/meta.tsx | 2 +- .../components/flyout_components/utils.tsx | 2 +- .../ml_rule_warning_popover.tsx | 2 +- .../rules_table/ml_rule_warning_popover.tsx | 2 +- .../components/rules_table/use_columns.tsx | 2 +- .../detection_engine/rules/breadcrumbs.ts | 8 +- .../list_details_link_anchor/index.tsx | 2 +- .../security_solution/public/rules/routes.tsx | 6 +- 19 files changed, 597 insertions(+), 600 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/legacy_url_conflict_callout.test.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/legacy_url_conflict_callout.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_redirect_legacy_url.test.ts create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_redirect_legacy_url.ts create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs.test.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs.tsx diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/__mocks__/rule_details_context.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/__mocks__/rule_details_context.tsx index f4b04627b5164..a853e8f1422c7 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/__mocks__/rule_details_context.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/__mocks__/rule_details_context.tsx @@ -7,7 +7,7 @@ import React from 'react'; import type { RuleDetailsContextType } from '../rule_details_context'; -import { RuleDetailTabs } from '..'; +import { RuleDetailTabs } from '../use_rule_details_tabs'; export const useRuleDetailsContextMock = { create: (): jest.Mocked<RuleDetailsContextType> => ({ diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx index 9c38520184eef..e30e2b6e6aa52 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx @@ -29,13 +29,13 @@ import { MAX_EXECUTION_EVENTS_DISPLAYED } from '@kbn/securitysolution-rules'; import { mountReactNode } from '@kbn/core-mount-utils-browser-internal'; import { InputsModelId } from '../../../../../common/store/inputs/constants'; -import { RuleDetailTabs } from '..'; + import { RULE_DETAILS_EXECUTION_LOG_TABLE_SHOW_METRIC_COLUMNS_STORAGE_KEY } from '../../../../../../common/constants'; import type { RuleExecutionResult, RuleExecutionStatus, } from '../../../../../../common/api/detection_engine/rule_monitoring'; - +import { RuleDetailTabs } from '../use_rule_details_tabs'; import { HeaderSection } from '../../../../../common/components/header_section'; import { UtilityBar, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.test.tsx deleted file mode 100644 index ed3f06c54e50e..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.test.tsx +++ /dev/null @@ -1,455 +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 { mount } from 'enzyme'; -import { waitFor } from '@testing-library/react'; -import '../../../../common/mock/match_media'; -import { - createSecuritySolutionStorageMock, - kibanaObservable, - mockGlobalState, - TestProviders, - SUB_PLUGINS_REDUCER, -} from '../../../../common/mock'; -import { RuleDetailsPage } from '.'; -import type { State } from '../../../../common/store'; -import { createStore } from '../../../../common/store'; -import { useUserData } from '../../../../detections/components/user_info'; -import { useRuleWithFallback } from '../../../rule_management/logic/use_rule_with_fallback'; - -import { useSourcererDataView } from '../../../../common/containers/sourcerer'; -import { useParams } from 'react-router-dom'; -import { mockHistory, Router } from '../../../../common/mock/router'; - -import { fillEmptySeverityMappings } from '../../../../detections/pages/detection_engine/rules/helpers'; - -// Test will fail because we will to need to mock some core services to make the test work -// For now let's forget about SiemSearchBar and QueryBar -jest.mock('../../../../common/components/search_bar', () => ({ - SiemSearchBar: () => null, -})); -jest.mock('../../../../detections/pages/detection_engine/rules/helpers', () => { - const original = jest.requireActual( - '../../../../detections/pages/detection_engine/rules/helpers' - ); - return { - ...original, - fillEmptySeverityMappings: jest.fn().mockReturnValue([]), - }; -}); -jest.mock('../../../../common/components/query_bar', () => ({ - QueryBar: () => null, -})); -jest.mock('../../../../detections/containers/detection_engine/lists/use_lists_config'); -jest.mock('../../../../common/components/link_to'); -jest.mock('../../../../detections/components/user_info'); -jest.mock('../../../rule_management/logic/use_rule_with_fallback', () => { - const original = jest.requireActual('../../../rule_management/logic/use_rule_with_fallback'); - return { - ...original, - useRuleWithFallback: jest.fn(), - }; -}); -jest.mock('../../../../common/containers/sourcerer', () => { - const actual = jest.requireActual('../../../../common/containers/sourcerer'); - return { - ...actual, - useSourcererDataView: jest - .fn() - .mockReturnValue({ indexPattern: ['fakeindex'], loading: false }), - }; -}); - -jest.mock('../../../../common/hooks/use_data_table_filters'); - -jest.mock('../../../../common/containers/use_global_time', () => ({ - useGlobalTime: jest.fn().mockReturnValue({ - from: '2020-07-07T08:20:18.966Z', - isInitializing: false, - to: '2020-07-08T08:20:18.966Z', - setQuery: jest.fn(), - }), -})); -jest.mock('react-router-dom', () => { - const originalModule = jest.requireActual('react-router-dom'); - - return { - ...originalModule, - useParams: jest.fn(), - useHistory: jest.fn(), - useLocation: jest.fn().mockReturnValue({ pathname: '/alerts' }), - }; -}); - -// RuleDetailsSnoozeSettings is an isolated component and not essential for existing tests -jest.mock('../../../rule_management/components/rule_snooze_badge', () => ({ - RuleSnoozeBadge: () => <></>, -})); - -const mockRedirectLegacyUrl = jest.fn(); -const mockGetLegacyUrlConflict = jest.fn(); -jest.mock('../../../../common/lib/kibana', () => { - const originalModule = jest.requireActual('../../../../common/lib/kibana'); - return { - ...originalModule, - useKibana: () => ({ - services: { - ...originalModule.useKibana().services, - storage: { - get: jest.fn().mockReturnValue(true), - }, - application: { - getUrlForApp: (appId: string, options?: { path?: string }) => - `/app/${appId}${options?.path}`, - navigateToApp: jest.fn(), - capabilities: { - actions: { - delete: true, - save: true, - show: true, - }, - siem: { - 'ai-assistant': true, - }, - }, - }, - data: { - dataViews: { - getIdsWithTitle: async () => - Promise.resolve([{ id: 'myfakeid', title: 'hello*,world*,refreshed*' }]), - create: async ({ title }: { title: string }) => - Promise.resolve({ - id: 'myfakeid', - matchedIndices: ['hello', 'world', 'refreshed'], - fields: [ - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - aggregatable: true, - searchable: true, - count: 10, - readFromDocValues: true, - scripted: false, - isMapped: true, - }, - { - name: 'ssl', - type: 'boolean', - esTypes: ['boolean'], - aggregatable: true, - searchable: true, - count: 20, - readFromDocValues: true, - scripted: false, - isMapped: true, - }, - { - name: '@timestamp', - type: 'date', - esTypes: ['date'], - aggregatable: true, - searchable: true, - count: 30, - readFromDocValues: true, - scripted: false, - isMapped: true, - }, - ], - getIndexPattern: () => title, - getRuntimeMappings: () => ({ - myfield: { - type: 'keyword', - }, - }), - }), - get: async (dataViewId: string, displayErrors?: boolean, refreshFields = false) => - Promise.resolve({ - id: dataViewId, - matchedIndices: refreshFields - ? ['hello', 'world', 'refreshed'] - : ['hello', 'world'], - fields: [ - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - aggregatable: true, - searchable: true, - count: 10, - readFromDocValues: true, - scripted: false, - isMapped: true, - }, - { - name: 'ssl', - type: 'boolean', - esTypes: ['boolean'], - aggregatable: true, - searchable: true, - count: 20, - readFromDocValues: true, - scripted: false, - isMapped: true, - }, - { - name: '@timestamp', - type: 'date', - esTypes: ['date'], - aggregatable: true, - searchable: true, - count: 30, - readFromDocValues: true, - scripted: false, - isMapped: true, - }, - ], - getIndexPattern: () => 'hello*,world*,refreshed*', - getRuntimeMappings: () => ({ - myfield: { - type: 'keyword', - }, - }), - }), - }, - search: { - search: () => ({ - subscribe: () => ({ - unsubscribe: jest.fn(), - }), - }), - }, - }, - spaces: { - ui: { - components: { getLegacyUrlConflict: mockGetLegacyUrlConflict }, - redirectLegacyUrl: mockRedirectLegacyUrl, - }, - }, - }, - }), - }; -}); - -const state: State = { - ...mockGlobalState, -}; - -const mockRule = { - id: 'myfakeruleid', - author: [], - severity_mapping: [], - risk_score_mapping: [], - rule_id: 'rule-1', - risk_score: 50, - description: 'some description', - from: 'now-5m', - to: 'now', - name: 'some-name', - severity: 'low', - type: 'query', - query: 'some query', - index: ['index-1'], - interval: '5m', - references: [], - actions: [], - enabled: false, - false_positives: [], - max_signals: 100, - tags: [], - threat: [], - throttle: null, - version: 1, - exceptions_list: [], -}; -const { storage } = createSecuritySolutionStorageMock(); -const store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); - -describe('RuleDetailsPageComponent', () => { - beforeAll(() => { - (useUserData as jest.Mock).mockReturnValue([{}]); - (useParams as jest.Mock).mockReturnValue({}); - (useSourcererDataView as jest.Mock).mockReturnValue({ - indicesExist: true, - indexPattern: {}, - }); - (useRuleWithFallback as jest.Mock).mockReturnValue({ - error: null, - loading: false, - isExistingRule: true, - refresh: jest.fn(), - rule: { ...mockRule }, - }); - (fillEmptySeverityMappings as jest.Mock).mockReturnValue([]); - }); - - beforeEach(() => { - mockRedirectLegacyUrl.mockReset(); - mockGetLegacyUrlConflict.mockReset(); - }); - - it('renders correctly with no outcome property on rule', async () => { - const wrapper = mount( - <TestProviders store={store}> - <Router history={mockHistory}> - <RuleDetailsPage /> - </Router> - </TestProviders> - ); - await waitFor(() => { - expect(wrapper.find('[data-test-subj="header-page-title"]').exists()).toBe(true); - expect(mockRedirectLegacyUrl).not.toHaveBeenCalled(); - expect(mockGetLegacyUrlConflict).not.toHaveBeenCalled(); - }); - }); - - it('renders correctly with outcome === "exactMatch"', async () => { - (useRuleWithFallback as jest.Mock).mockReturnValue({ - error: null, - loading: false, - isExistingRule: true, - refresh: jest.fn(), - rule: { ...mockRule, outcome: 'exactMatch' }, - }); - - const wrapper = mount( - <TestProviders store={store}> - <Router history={mockHistory}> - <RuleDetailsPage /> - </Router> - </TestProviders> - ); - await waitFor(() => { - expect(wrapper.find('[data-test-subj="header-page-title"]').exists()).toBe(true); - expect(mockRedirectLegacyUrl).not.toHaveBeenCalled(); - expect(mockGetLegacyUrlConflict).not.toHaveBeenCalled(); - }); - }); - - it('renders correctly with outcome === "aliasMatch"', async () => { - (useRuleWithFallback as jest.Mock).mockReturnValue({ - error: null, - loading: false, - isExistingRule: true, - refresh: jest.fn(), - rule: { ...mockRule, outcome: 'aliasMatch', alias_purpose: 'savedObjectConversion' }, - }); - const wrapper = mount( - <TestProviders store={store}> - <Router history={mockHistory}> - <RuleDetailsPage /> - </Router> - </TestProviders> - ); - await waitFor(() => { - expect(wrapper.find('[data-test-subj="header-page-title"]').exists()).toBe(true); - expect(mockRedirectLegacyUrl).toHaveBeenCalledWith({ - path: 'rules/id/myfakeruleid', - aliasPurpose: 'savedObjectConversion', - objectNoun: 'rule', - }); - expect(mockGetLegacyUrlConflict).not.toHaveBeenCalled(); - }); - }); - - it('renders correctly when outcome = conflict', async () => { - (useRuleWithFallback as jest.Mock).mockReturnValue({ - error: null, - loading: false, - isExistingRule: true, - refresh: jest.fn(), - rule: { - ...mockRule, - outcome: 'conflict', - alias_target_id: 'aliased_rule_id', - alias_purpose: 'savedObjectConversion', - }, - }); - const wrapper = mount( - <TestProviders store={store}> - <Router history={mockHistory}> - <RuleDetailsPage /> - </Router> - </TestProviders> - ); - await waitFor(() => { - expect(wrapper.find('[data-test-subj="header-page-title"]').exists()).toBe(true); - expect(mockRedirectLegacyUrl).not.toHaveBeenCalled(); - expect(mockGetLegacyUrlConflict).toHaveBeenCalledWith({ - currentObjectId: 'myfakeruleid', - objectNoun: 'rule', - otherObjectId: 'aliased_rule_id', - otherObjectPath: `rules/id/aliased_rule_id`, - }); - }); - }); - - it('renders exceptions tab', async () => { - (useRuleWithFallback as jest.Mock).mockReturnValue({ - error: null, - loading: false, - isExistingRule: true, - refresh: jest.fn(), - rule: { - ...mockRule, - outcome: 'conflict', - alias_target_id: 'aliased_rule_id', - alias_purpose: 'savedObjectConversion', - }, - }); - const wrapper = mount( - <TestProviders store={store}> - <Router history={mockHistory}> - <RuleDetailsPage /> - </Router> - </TestProviders> - ); - await waitFor(() => { - expect(wrapper.find('[data-test-subj="navigation-rule_exceptions"]').exists()).toBeTruthy(); - expect( - wrapper.find('[data-test-subj="navigation-endpoint_exceptions"]').exists() - ).toBeFalsy(); - }); - }); - - it('renders endpoint exceptions tab when rule includes endpoint list', async () => { - (useRuleWithFallback as jest.Mock).mockReturnValue({ - error: null, - loading: false, - isExistingRule: true, - refresh: jest.fn(), - rule: { - ...mockRule, - outcome: 'conflict', - alias_target_id: 'aliased_rule_id', - alias_purpose: 'savedObjectConversion', - exceptions_list: [ - { - id: 'endpoint_list', - list_id: 'endpoint_list', - type: 'endpoint', - namespace_type: 'agnostic', - }, - ], - }, - }); - const wrapper = mount( - <TestProviders store={store}> - <Router history={mockHistory}> - <RuleDetailsPage /> - </Router> - </TestProviders> - ); - await waitFor(() => { - expect(wrapper.find('[data-test-subj="navigation-rule_exceptions"]').exists()).toBeTruthy(); - expect( - wrapper.find('[data-test-subj="navigation-endpoint_exceptions"]').exists() - ).toBeTruthy(); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx index 791db19a92dcd..5f9e1f17dba18 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx @@ -19,10 +19,9 @@ import { EuiWindowEvent, } from '@elastic/eui'; import type { Filter } from '@kbn/es-query'; -import { i18n as i18nTranslate } from '@kbn/i18n'; import { Routes, Route } from '@kbn/shared-ux-router'; -import { noop, omit } from 'lodash/fp'; +import { noop } from 'lodash/fp'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useParams } from 'react-router-dom'; import type { ConnectedProps } from 'react-redux'; @@ -112,13 +111,14 @@ import { RuleStatusFailedCallOut, ruleStatusI18n, } from '../../../../detections/components/rules/rule_execution_status'; -import { ExecutionEventsTable, useRuleExecutionSettings } from '../../../rule_monitoring'; +import { ExecutionEventsTable } from '../../../rule_monitoring'; import { ExecutionLogTable } from './execution_log_table/execution_log_table'; -import * as detectionI18n from '../../../../detections/pages/detection_engine/translations'; import * as ruleI18n from '../../../../detections/pages/detection_engine/rules/translations'; import { RuleDetailsContextProvider } from './rule_details_context'; +// eslint-disable-next-line no-restricted-imports +import { LegacyUrlConflictCallOut } from './legacy_url_conflict_callout'; import { useGetSavedQuery } from '../../../../detections/pages/detection_engine/rules/use_get_saved_query'; import * as i18n from './translations'; import { NeedAdminForUpdateRulesCallOut } from '../../../../detections/components/callouts/need_admin_for_update_callout'; @@ -131,7 +131,6 @@ import { AlertsTableFilterGroup } from '../../../../detections/components/alerts import { useSignalHelpers } from '../../../../common/containers/sourcerer/use_signal_helpers'; import { HeaderPage } from '../../../../common/components/header_page'; import { ExceptionsViewer } from '../../../rule_exceptions/components/all_exception_items_table'; -import type { NavTab } from '../../../../common/components/navigation/types'; import { EditRuleSettingButtonLink } from '../../../../detections/pages/detection_engine/rules/details/components/edit_rule_settings_button_link'; import { useStartMlJobs } from '../../../rule_management/logic/use_start_ml_jobs'; import { useBulkDuplicateExceptionsConfirmation } from '../../../rule_management_ui/components/rules_table/bulk_actions/use_bulk_duplicate_confirmation'; @@ -141,6 +140,9 @@ import { RuleSnoozeBadge } from '../../../rule_management/components/rule_snooze import { useRuleIndexPattern } from '../../../rule_creation_ui/pages/form'; import { DataSourceType } from '../../../../detections/pages/detection_engine/rules/types'; import { useBoolState } from '../../../../common/hooks/use_bool_state'; +// eslint-disable-next-line no-restricted-imports +import { useLegacyUrlRedirect } from './use_redirect_legacy_url'; +import { RuleDetailTabs, useRuleDetailsTabs } from './use_rule_details_tabs'; /** * Need a 100% height here to account for the graph/analyze tool, which sets no explicit height parameters, but fills the available space. @@ -158,22 +160,6 @@ const StyledMinHeightTabContainer = styled.div` min-height: 800px; `; -export enum RuleDetailTabs { - alerts = 'alerts', - exceptions = 'rule_exceptions', - endpointExceptions = 'endpoint_exceptions', - executionResults = 'execution_results', - executionEvents = 'execution_events', -} - -export const RULE_DETAILS_TAB_NAME: Record<string, string> = { - [RuleDetailTabs.alerts]: detectionI18n.ALERT, - [RuleDetailTabs.exceptions]: i18n.EXCEPTIONS_TAB, - [RuleDetailTabs.endpointExceptions]: i18n.ENDPOINT_EXCEPTIONS_TAB, - [RuleDetailTabs.executionResults]: i18n.EXECUTION_RESULTS_TAB, - [RuleDetailTabs.executionEvents]: i18n.EXECUTION_EVENTS_TAB, -}; - type DetectionEngineComponentProps = PropsFromRedux; const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({ @@ -256,43 +242,7 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({ await startMlJobs(rule?.machine_learning_job_id); }, [rule, startMlJobs]); - const ruleDetailTabs = useMemo( - (): Record<RuleDetailTabs, NavTab> => ({ - [RuleDetailTabs.alerts]: { - id: RuleDetailTabs.alerts, - name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.alerts], - disabled: false, - href: `/rules/id/${ruleId}/${RuleDetailTabs.alerts}`, - }, - [RuleDetailTabs.exceptions]: { - id: RuleDetailTabs.exceptions, - name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.exceptions], - disabled: rule == null, - href: `/rules/id/${ruleId}/${RuleDetailTabs.exceptions}`, - }, - [RuleDetailTabs.endpointExceptions]: { - id: RuleDetailTabs.endpointExceptions, - name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.endpointExceptions], - disabled: rule == null, - href: `/rules/id/${ruleId}/${RuleDetailTabs.endpointExceptions}`, - }, - [RuleDetailTabs.executionResults]: { - id: RuleDetailTabs.executionResults, - name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.executionResults], - disabled: !isExistingRule, - href: `/rules/id/${ruleId}/${RuleDetailTabs.executionResults}`, - }, - [RuleDetailTabs.executionEvents]: { - id: RuleDetailTabs.executionEvents, - name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.executionEvents], - disabled: !isExistingRule, - href: `/rules/id/${ruleId}/${RuleDetailTabs.executionEvents}`, - }, - }), - [isExistingRule, rule, ruleId] - ); - - const [pageTabs, setTabs] = useState<Partial<Record<RuleDetailTabs, NavTab>>>(ruleDetailTabs); + const pageTabs = useRuleDetailsTabs({ rule, ruleId, isExistingRule, hasIndexRead }); const [isDeleteConfirmationVisible, showDeleteConfirmation, hideDeleteConfirmation] = useBoolState(); @@ -371,74 +321,7 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({ } }, [maybeRule]); - useEffect(() => { - if (rule) { - const outcome = rule.outcome; - if (spacesApi && outcome === 'aliasMatch') { - // This rule has been resolved from a legacy URL - redirect the user to the new URL and display a toast. - const path = `rules/id/${rule.id}${window.location.search}${window.location.hash}`; - spacesApi.ui.redirectLegacyUrl({ - path, - aliasPurpose: rule.alias_purpose, - objectNoun: i18nTranslate.translate( - 'xpack.triggersActionsUI.sections.ruleDetails.redirectObjectNoun', - { defaultMessage: 'rule' } - ), - }); - } - } - }, [rule, spacesApi]); - - const getLegacyUrlConflictCallout = useMemo(() => { - if (rule?.alias_target_id != null && spacesApi && rule.outcome === 'conflict') { - const aliasTargetId = rule.alias_target_id; - // We have resolved to one rule, but there is another one with a legacy URL associated with this page. Display a - // callout with a warning for the user, and provide a way for them to navigate to the other rule. - const otherRulePath = `rules/id/${aliasTargetId}${window.location.search}${window.location.hash}`; - return ( - <> - <EuiSpacer /> - {spacesApi.ui.components.getLegacyUrlConflict({ - objectNoun: i18nTranslate.translate( - 'xpack.triggersActionsUI.sections.ruleDetails.redirectObjectNoun', - { - defaultMessage: 'rule', - } - ), - currentObjectId: rule.id, - otherObjectId: aliasTargetId, - otherObjectPath: otherRulePath, - })} - </> - ); - } - return null; - }, [rule, spacesApi]); - - const ruleExecutionSettings = useRuleExecutionSettings(); - - useEffect(() => { - const hiddenTabs = []; - - if (!hasIndexRead) { - hiddenTabs.push(RuleDetailTabs.alerts); - } - if (!ruleExecutionSettings.extendedLogging.isEnabled) { - hiddenTabs.push(RuleDetailTabs.executionEvents); - } - if (rule != null) { - const hasEndpointList = (rule.exceptions_list ?? []).some( - (list) => list.type === ExceptionListTypeEnum.ENDPOINT - ); - if (!hasEndpointList) { - hiddenTabs.push(RuleDetailTabs.endpointExceptions); - } - } - - const tabs = omit<Record<RuleDetailTabs, NavTab>>(hiddenTabs, ruleDetailTabs); - - setTabs(tabs); - }, [hasIndexRead, rule, ruleDetailTabs, ruleExecutionSettings]); + useLegacyUrlRedirect({ rule, spacesApi }); const showUpdating = useMemo( () => isLoadingIndexPattern || isAlertsLoading || loading, @@ -769,7 +652,7 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({ </EuiFlexGroup> </HeaderPage> {ruleError} - {getLegacyUrlConflictCallout} + <LegacyUrlConflictCallOut rule={rule} spacesApi={spacesApi} /> <EuiSpacer /> <EuiFlexGroup> <EuiFlexItem data-test-subj="aboutRule" component="section" grow={1}> diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/legacy_url_conflict_callout.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/legacy_url_conflict_callout.test.tsx new file mode 100644 index 0000000000000..240bb988756f3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/legacy_url_conflict_callout.test.tsx @@ -0,0 +1,113 @@ +/* + * 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'; +// eslint-disable-next-line no-restricted-imports +import { LegacyUrlConflictCallOut } from './legacy_url_conflict_callout'; +import { render, screen } from '@testing-library/react'; +import type { Rule } from '../../../rule_management/logic'; + +const mockRedirectLegacyUrl = jest.fn(); +const mockGetLegacyUrlConflict = jest.fn(); + +const mockSpacesApi = { + getActiveSpace$: jest.fn(), + getActiveSpace: jest.fn(), + ui: { + components: { + getSpacesContextProvider: jest.fn(), + getShareToSpaceFlyout: jest.fn(), + getCopyToSpaceFlyout: jest.fn(), + getSpaceList: jest.fn(), + getEmbeddableLegacyUrlConflict: jest.fn(), + getSpaceAvatar: jest.fn(), + getLegacyUrlConflict: mockGetLegacyUrlConflict, + }, + redirectLegacyUrl: mockRedirectLegacyUrl, + useSpaces: jest.fn(), + }, +}; + +describe('<LegacyUrlConflictCallOut />', () => { + beforeEach(() => { + mockRedirectLegacyUrl.mockReset(); + mockGetLegacyUrlConflict.mockReset(); + }); + + it('renders null if no rule', () => { + render(<LegacyUrlConflictCallOut rule={null} spacesApi={mockSpacesApi} />); + expect(screen.queryByTestId('legacyUrlConflictCallOut-wrapper')).toBeNull(); + expect(mockRedirectLegacyUrl).not.toHaveBeenCalled(); + expect(mockGetLegacyUrlConflict).not.toHaveBeenCalled(); + }); + + it('renders null if spacesApi is undefined', () => { + render(<LegacyUrlConflictCallOut rule={mockRule} spacesApi={undefined} />); + expect(screen.queryByTestId('legacyUrlConflictCallOut-wrapper')).toBeNull(); + expect(mockRedirectLegacyUrl).not.toHaveBeenCalled(); + expect(mockGetLegacyUrlConflict).not.toHaveBeenCalled(); + }); + + it('renders null if rule.outcome is not "conflict"', () => { + render(<LegacyUrlConflictCallOut rule={null} spacesApi={mockSpacesApi} />); + expect(screen.queryByTestId('legacyUrlConflictCallOut-wrapper')).toBeNull(); + expect(mockRedirectLegacyUrl).not.toHaveBeenCalled(); + expect(mockGetLegacyUrlConflict).not.toHaveBeenCalled(); + }); + + it('renders LegacyUrlConfictCallout if rule.outcome is "conflict" and alias_target_id and spacesApi are defined', () => { + render( + <LegacyUrlConflictCallOut + rule={{ ...mockRule, outcome: 'conflict', alias_target_id: 'mock_alias_target_id' }} + spacesApi={mockSpacesApi} + /> + ); + expect(screen.queryByTestId('legacyUrlConflictCallOut-wrapper')).toBeInTheDocument(); + expect(mockRedirectLegacyUrl).not.toHaveBeenCalled(); + expect(mockGetLegacyUrlConflict).toHaveBeenCalledWith({ + currentObjectId: mockRule.id, + objectNoun: 'rule', + otherObjectId: 'mock_alias_target_id', + otherObjectPath: 'rules/id/mock_alias_target_id', + }); + }); +}); + +const mockRule: Rule = { + id: 'myfakeruleid', + author: [], + severity_mapping: [], + risk_score_mapping: [], + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + from: 'now-5m', + to: 'now', + name: 'some-name', + severity: 'low', + type: 'query', + query: 'some query', + index: ['index-1'], + interval: '5m', + references: [], + actions: [], + enabled: false, + false_positives: [], + max_signals: 100, + tags: [], + threat: [], + throttle: null, + version: 1, + exceptions_list: [], + created_at: '2020-04-09T09:43:51.778Z', + created_by: 'elastic', + immutable: false, + updated_at: '2020-04-09T09:43:51.778Z', + updated_by: 'elastic', + related_integrations: [], + required_fields: [], + setup: '', +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/legacy_url_conflict_callout.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/legacy_url_conflict_callout.tsx new file mode 100644 index 0000000000000..bd8589a39e392 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/legacy_url_conflict_callout.tsx @@ -0,0 +1,46 @@ +/* + * 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 { EuiSpacer } from '@elastic/eui'; +import { i18n as i18nTranslate } from '@kbn/i18n'; +import type { SpacesApi } from '@kbn/spaces-plugin/public'; +import type { Rule } from '../../../rule_management/logic'; + +interface LegacyUrlConflictCallOutProps { + rule: Rule | null; + spacesApi?: SpacesApi; +} + +export const LegacyUrlConflictCallOut = React.memo<LegacyUrlConflictCallOutProps>( + ({ rule, spacesApi }) => { + if (rule?.alias_target_id != null && spacesApi && rule.outcome === 'conflict') { + const aliasTargetId = rule.alias_target_id; + // We have resolved to one rule, but there is another one with a legacy URL associated with this page. Display a + // callout with a warning for the user, and provide a way for them to navigate to the other rule. + const otherRulePath = `rules/id/${aliasTargetId}${window.location.search}${window.location.hash}`; + return ( + <div data-test-subj="legacyUrlConflictCallOut-wrapper"> + <EuiSpacer /> + {spacesApi.ui.components.getLegacyUrlConflict({ + objectNoun: i18nTranslate.translate( + 'xpack.triggersActionsUI.sections.ruleDetails.redirectObjectNoun', + { + defaultMessage: 'rule', + } + ), + currentObjectId: rule.id, + otherObjectId: aliasTargetId, + otherObjectPath: otherRulePath, + })} + </div> + ); + } + return null; + } +); + +LegacyUrlConflictCallOut.displayName = 'LegacyUrlConflictCallOut'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/rule_details_context.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/rule_details_context.tsx index 6ef168bcd8080..e08e32662cca6 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/rule_details_context.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/rule_details_context.tsx @@ -15,7 +15,7 @@ import type { } from '../../../../../common/api/detection_engine/rule_monitoring'; import { invariant } from '../../../../../common/utils/invariant'; import { useKibana } from '../../../../common/lib/kibana'; -import { RuleDetailTabs } from '.'; +import { RuleDetailTabs } from './use_rule_details_tabs'; export interface ExecutionLogTableState { /** diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_redirect_legacy_url.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_redirect_legacy_url.test.ts new file mode 100644 index 0000000000000..454904a251bf4 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_redirect_legacy_url.test.ts @@ -0,0 +1,115 @@ +/* + * 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. + */ +/* eslint-disable no-restricted-imports */ + +import { renderHook, cleanup } from '@testing-library/react-hooks'; +import type { UseLegacyUrlRedirectParams } from './use_redirect_legacy_url'; +import { useLegacyUrlRedirect } from './use_redirect_legacy_url'; +import type { Rule } from '../../../rule_management/logic'; + +const mockRedirectLegacyUrl = jest.fn(); +const mockGetLegacyUrlConflict = jest.fn(); + +const mockSpacesApi = { + getActiveSpace$: jest.fn(), + getActiveSpace: jest.fn(), + ui: { + components: { + getSpacesContextProvider: jest.fn(), + getShareToSpaceFlyout: jest.fn(), + getCopyToSpaceFlyout: jest.fn(), + getSpaceList: jest.fn(), + getEmbeddableLegacyUrlConflict: jest.fn(), + getSpaceAvatar: jest.fn(), + getLegacyUrlConflict: mockGetLegacyUrlConflict, + }, + redirectLegacyUrl: mockRedirectLegacyUrl, + useSpaces: jest.fn(), + }, +}; + +describe('useLegacyUrlRedirect', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + afterEach(async () => { + cleanup(); + }); + + const render = (props: UseLegacyUrlRedirectParams) => + renderHook(() => useLegacyUrlRedirect({ ...props })); + + it('should not redirect if rule is null', () => { + render({ rule: null, spacesApi: mockSpacesApi }); + expect(mockRedirectLegacyUrl).not.toHaveBeenCalled(); + }); + + it('should not redirect if spacesApi is undefined', () => { + render({ + rule: { ...mockRule, id: '123', outcome: 'aliasMatch', alias_purpose: 'savedObjectImport' }, + spacesApi: undefined, + }); + expect(mockRedirectLegacyUrl).not.toHaveBeenCalled(); + }); + + it('should not redirect if outcome is not aliasMatch', () => { + render({ + rule: { ...mockRule, id: '123', outcome: 'exactMatch', alias_purpose: 'savedObjectImport' }, + spacesApi: mockSpacesApi, + }); + expect(mockRedirectLegacyUrl).not.toHaveBeenCalled(); + }); + + it('should redirect if rule is not null and outcome is aliasMatch', () => { + render({ + rule: { ...mockRule, id: '123', outcome: 'aliasMatch', alias_purpose: 'savedObjectImport' }, + spacesApi: mockSpacesApi, + }); + expect(mockRedirectLegacyUrl).toHaveBeenCalledWith({ + aliasPurpose: 'savedObjectImport', + objectNoun: 'rule', + path: 'rules/id/123', + }); + }); +}); + +const mockRule: Rule = { + id: 'myfakeruleid', + author: [], + severity_mapping: [], + risk_score_mapping: [], + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + from: 'now-5m', + to: 'now', + name: 'some-name', + severity: 'low', + type: 'query', + query: 'some query', + index: ['index-1'], + interval: '5m', + references: [], + actions: [], + enabled: false, + false_positives: [], + max_signals: 100, + tags: [], + threat: [], + throttle: null, + version: 1, + exceptions_list: [], + created_at: '2020-04-09T09:43:51.778Z', + created_by: 'elastic', + immutable: false, + updated_at: '2020-04-09T09:43:51.778Z', + updated_by: 'elastic', + related_integrations: [], + required_fields: [], + setup: '', +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_redirect_legacy_url.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_redirect_legacy_url.ts new file mode 100644 index 0000000000000..10e442c0041fc --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_redirect_legacy_url.ts @@ -0,0 +1,36 @@ +/* + * 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 { useEffect } from 'react'; +import { i18n as i18nTranslate } from '@kbn/i18n'; +import type { SpacesApi } from '@kbn/spaces-plugin/public'; +import type { Rule } from '../../../rule_management/logic'; + +export interface UseLegacyUrlRedirectParams { + rule: Rule | null; + spacesApi?: SpacesApi; +} + +export const useLegacyUrlRedirect = ({ rule, spacesApi }: UseLegacyUrlRedirectParams) => { + useEffect(() => { + if (rule) { + const outcome = rule.outcome; + if (spacesApi && outcome === 'aliasMatch') { + // This rule has been resolved from a legacy URL - redirect the user to the new URL and display a toast. + const path = `rules/id/${rule.id}${window.location.search}${window.location.hash}`; + spacesApi.ui.redirectLegacyUrl({ + path, + aliasPurpose: rule.alias_purpose, + objectNoun: i18nTranslate.translate( + 'xpack.triggersActionsUI.sections.ruleDetails.redirectObjectNoun', + { defaultMessage: 'rule' } + ), + }); + } + } + }, [rule, spacesApi]); +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs.test.tsx new file mode 100644 index 0000000000000..496fb0d94c3fc --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs.test.tsx @@ -0,0 +1,151 @@ +/* + * 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 { renderHook, cleanup } from '@testing-library/react-hooks'; +import type { UseRuleDetailsTabsProps } from './use_rule_details_tabs'; +import { RuleDetailTabs, useRuleDetailsTabs } from './use_rule_details_tabs'; +import type { Rule } from '../../../rule_management/logic'; + +import { useRuleExecutionSettings } from '../../../rule_monitoring'; +jest.mock('../../../rule_monitoring'); + +const mockRule: Rule = { + id: 'myfakeruleid', + author: [], + severity_mapping: [], + risk_score_mapping: [], + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + from: 'now-5m', + to: 'now', + name: 'some-name', + severity: 'low', + type: 'query', + query: 'some query', + index: ['index-1'], + interval: '5m', + references: [], + actions: [], + enabled: false, + false_positives: [], + max_signals: 100, + tags: [], + threat: [], + throttle: null, + version: 1, + exceptions_list: [], + created_at: '2020-04-09T09:43:51.778Z', + created_by: 'elastic', + immutable: false, + updated_at: '2020-04-09T09:43:51.778Z', + updated_by: 'elastic', + related_integrations: [], + required_fields: [], + setup: '', +}; + +describe('useRuleDetailsTabs', () => { + beforeAll(() => { + (useRuleExecutionSettings as jest.Mock).mockReturnValue({ + extendedLogging: { + isEnabled: false, + minLevel: 'debug', + }, + }); + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + afterEach(async () => { + cleanup(); + }); + + const render = (props: UseRuleDetailsTabsProps) => + renderHook(() => useRuleDetailsTabs({ ...props })); + + it('does not return the alerts tab if the user does not have read permissions', async () => { + const tabs = render({ + rule: mockRule, + ruleId: mockRule.rule_id, + isExistingRule: true, + hasIndexRead: false, + }); + const tabsNames = Object.keys(tabs.result.current); + + expect(tabsNames).not.toContain(RuleDetailTabs.alerts); + }); + + it('always returns ths rule exception tab ', async () => { + const tabs = render({ + rule: mockRule, + ruleId: mockRule.rule_id, + isExistingRule: true, + hasIndexRead: true, + }); + const tabsNames = Object.keys(tabs.result.current); + + expect(tabsNames).toContain(RuleDetailTabs.exceptions); + }); + + it('renders endpoint exceptions tab when rule includes endpoint list', async () => { + const tabs = render({ + rule: { + ...mockRule, + outcome: 'conflict', + alias_target_id: 'aliased_rule_id', + alias_purpose: 'savedObjectConversion', + exceptions_list: [ + { + id: 'endpoint_list', + list_id: 'endpoint_list', + type: 'endpoint', + namespace_type: 'agnostic', + }, + ], + }, + ruleId: mockRule.rule_id, + isExistingRule: true, + hasIndexRead: true, + }); + const tabsNames = Object.keys(tabs.result.current); + + expect(tabsNames).toContain(RuleDetailTabs.endpointExceptions); + }); + + it('does not return the execution events tab if extended logging is disabled', async () => { + const tabs = render({ + rule: mockRule, + ruleId: mockRule.rule_id, + isExistingRule: true, + hasIndexRead: true, + }); + const tabsNames = Object.keys(tabs.result.current); + + expect(tabsNames).not.toContain(RuleDetailTabs.executionEvents); + }); + + it('returns the execution events tab if extended logging is enabled', async () => { + (useRuleExecutionSettings as jest.Mock).mockReturnValue({ + extendedLogging: { + isEnabled: true, + minLevel: 'debug', + }, + }); + const tabs = render({ + rule: mockRule, + ruleId: mockRule.rule_id, + isExistingRule: true, + hasIndexRead: true, + }); + const tabsNames = Object.keys(tabs.result.current); + + expect(tabsNames).toContain(RuleDetailTabs.executionEvents); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs.tsx new file mode 100644 index 0000000000000..42a42caeb732d --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs.tsx @@ -0,0 +1,110 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEffect, useMemo, useState } from 'react'; +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import { omit } from 'lodash/fp'; +import * as detectionI18n from '../../../../detections/pages/detection_engine/translations'; +import * as i18n from './translations'; +import type { Rule } from '../../../rule_management/logic'; +import type { NavTab } from '../../../../common/components/navigation/types'; +import { useRuleExecutionSettings } from '../../../rule_monitoring'; + +export enum RuleDetailTabs { + alerts = 'alerts', + exceptions = 'rule_exceptions', + endpointExceptions = 'endpoint_exceptions', + executionResults = 'execution_results', + executionEvents = 'execution_events', +} + +export const RULE_DETAILS_TAB_NAME: Record<string, string> = { + [RuleDetailTabs.alerts]: detectionI18n.ALERT, + [RuleDetailTabs.exceptions]: i18n.EXCEPTIONS_TAB, + [RuleDetailTabs.endpointExceptions]: i18n.ENDPOINT_EXCEPTIONS_TAB, + [RuleDetailTabs.executionResults]: i18n.EXECUTION_RESULTS_TAB, + [RuleDetailTabs.executionEvents]: i18n.EXECUTION_EVENTS_TAB, +}; + +export interface UseRuleDetailsTabsProps { + rule: Rule | null; + ruleId: string; + isExistingRule: boolean; + hasIndexRead: boolean | null; +} + +export const useRuleDetailsTabs = ({ + rule, + ruleId, + isExistingRule, + hasIndexRead, +}: UseRuleDetailsTabsProps) => { + const ruleDetailTabs = useMemo( + (): Record<RuleDetailTabs, NavTab> => ({ + [RuleDetailTabs.alerts]: { + id: RuleDetailTabs.alerts, + name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.alerts], + disabled: false, + href: `/rules/id/${ruleId}/${RuleDetailTabs.alerts}`, + }, + [RuleDetailTabs.exceptions]: { + id: RuleDetailTabs.exceptions, + name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.exceptions], + disabled: rule == null, + href: `/rules/id/${ruleId}/${RuleDetailTabs.exceptions}`, + }, + [RuleDetailTabs.endpointExceptions]: { + id: RuleDetailTabs.endpointExceptions, + name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.endpointExceptions], + disabled: rule == null, + href: `/rules/id/${ruleId}/${RuleDetailTabs.endpointExceptions}`, + }, + [RuleDetailTabs.executionResults]: { + id: RuleDetailTabs.executionResults, + name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.executionResults], + disabled: !isExistingRule, + href: `/rules/id/${ruleId}/${RuleDetailTabs.executionResults}`, + }, + [RuleDetailTabs.executionEvents]: { + id: RuleDetailTabs.executionEvents, + name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.executionEvents], + disabled: !isExistingRule, + href: `/rules/id/${ruleId}/${RuleDetailTabs.executionEvents}`, + }, + }), + [isExistingRule, rule, ruleId] + ); + + const [pageTabs, setTabs] = useState<Partial<Record<RuleDetailTabs, NavTab>>>(ruleDetailTabs); + + const ruleExecutionSettings = useRuleExecutionSettings(); + + useEffect(() => { + const hiddenTabs = []; + + if (!hasIndexRead) { + hiddenTabs.push(RuleDetailTabs.alerts); + } + if (!ruleExecutionSettings.extendedLogging.isEnabled) { + hiddenTabs.push(RuleDetailTabs.executionEvents); + } + if (rule != null) { + const hasEndpointList = (rule.exceptions_list ?? []).some( + (list) => list.type === ExceptionListTypeEnum.ENDPOINT + ); + if (!hasEndpointList) { + hiddenTabs.push(RuleDetailTabs.endpointExceptions); + } + } + + const tabs = omit<Record<RuleDetailTabs, NavTab>>(hiddenTabs, ruleDetailTabs); + + setTabs(tabs); + }, [hasIndexRead, rule, ruleDetailTabs, ruleExecutionSettings]); + + return pageTabs; +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/meta.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/meta.tsx index 44109280fac9a..a324c19ff994d 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/meta.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/meta.tsx @@ -27,7 +27,7 @@ import { FormattedDate } from '../../../../common/components/formatted_date'; import { SecurityPageName } from '../../../../../common/constants'; import type { ExceptionListRuleReferencesSchema } from '../../../../../common/api/detection_engine/rule_exceptions'; import { SecuritySolutionLinkAnchor } from '../../../../common/components/links'; -import { RuleDetailTabs } from '../../../rule_details_ui/pages/rule_details'; +import { RuleDetailTabs } from '../../../rule_details_ui/pages/rule_details/use_rule_details_tabs'; import { getRuleDetailsTabUrl } from '../../../../common/components/link_to/redirect_to_detection_engine'; const StyledFlexItem = styled(EuiFlexItem)` diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/utils.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/utils.tsx index b84f8d8a8ff1c..712da253477ab 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/utils.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/utils.tsx @@ -33,7 +33,7 @@ import { } from '../../utils/helpers'; import { SecuritySolutionLinkAnchor } from '../../../../common/components/links'; import { getRuleDetailsTabUrl } from '../../../../common/components/link_to/redirect_to_detection_engine'; -import { RuleDetailTabs } from '../../../rule_details_ui/pages/rule_details'; +import { RuleDetailTabs } from '../../../rule_details_ui/pages/rule_details/use_rule_details_tabs'; import type { ExceptionListRuleReferencesInfoSchema, ExceptionListRuleReferencesSchema, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/ml_rule_warning_popover/ml_rule_warning_popover.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/ml_rule_warning_popover/ml_rule_warning_popover.tsx index 3575a030def5a..493686f9ceb19 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/ml_rule_warning_popover/ml_rule_warning_popover.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/ml_rule_warning_popover/ml_rule_warning_popover.tsx @@ -27,7 +27,7 @@ import { isMlRule } from '../../../../../common/detection_engine/utils'; import { getCapitalizedStatusText } from '../../../../detections/components/rules/rule_execution_status/utils'; import type { Rule } from '../../../rule_management/logic'; import { isJobStarted } from '../../../../../common/machine_learning/helpers'; -import { RuleDetailTabs } from '../../../rule_details_ui/pages/rule_details'; +import { RuleDetailTabs } from '../../../rule_details_ui/pages/rule_details/use_rule_details_tabs'; const POPOVER_WIDTH = '340px'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/ml_rule_warning_popover.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/ml_rule_warning_popover.tsx index 3be3cc03061b4..3d9e1f05c6e1e 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/ml_rule_warning_popover.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/ml_rule_warning_popover.tsx @@ -27,7 +27,7 @@ import { isMlRule } from '../../../../../common/detection_engine/utils'; import { getCapitalizedStatusText } from '../../../../detections/components/rules/rule_execution_status/utils'; import type { Rule } from '../../../rule_management/logic'; import { isJobStarted } from '../../../../../common/machine_learning/helpers'; -import { RuleDetailTabs } from '../../../rule_details_ui/pages/rule_details'; +import { RuleDetailTabs } from '../../../rule_details_ui/pages/rule_details/use_rule_details_tabs'; const POPOVER_WIDTH = '340px'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_columns.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_columns.tsx index 5629ed865a565..cc975a62be4a0 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_columns.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_columns.tsx @@ -37,7 +37,7 @@ import { RuleStatusBadge } from '../../../../detections/components/rules/rule_ex import { RuleSwitch } from '../../../../detections/components/rules/rule_switch'; import { SeverityBadge } from '../../../../detections/components/rules/severity_badge'; import * as i18n from '../../../../detections/pages/detection_engine/rules/translations'; -import { RuleDetailTabs } from '../../../rule_details_ui/pages/rule_details'; +import { RuleDetailTabs } from '../../../rule_details_ui/pages/rule_details/use_rule_details_tabs'; import type { Rule } from '../../../rule_management/logic'; import { PopoverTooltip } from './popover_tooltip'; import { useRulesTableContext } from './rules_table/rules_table_context'; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/breadcrumbs.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/breadcrumbs.ts index 0bd84ee4724ce..7b2cabd83f22e 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/breadcrumbs.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/breadcrumbs.ts @@ -6,6 +6,10 @@ */ import type { ChromeBreadcrumb } from '@kbn/core/public'; +import { + RuleDetailTabs, + RULE_DETAILS_TAB_NAME, +} from '../../../../detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs'; import { getRuleDetailsTabUrl, getRuleDetailsUrl, @@ -14,10 +18,6 @@ import * as i18nRules from './translations'; import { SecurityPageName } from '../../../../app/types'; import { RULES_PATH } from '../../../../../common/constants'; import type { GetTrailingBreadcrumbs } from '../../../../common/components/navigation/breadcrumbs/types'; -import { - RuleDetailTabs, - RULE_DETAILS_TAB_NAME, -} from '../../../../detection_engine/rule_details_ui/pages/rule_details'; import { DELETED_RULE } from '../../../../detection_engine/rule_details_ui/pages/rule_details/translations'; const getRuleDetailsTabName = (tabName: string): string => { diff --git a/x-pack/plugins/security_solution/public/exceptions/components/list_details_link_anchor/index.tsx b/x-pack/plugins/security_solution/public/exceptions/components/list_details_link_anchor/index.tsx index d1cb24e8d066b..4b54600fc454d 100644 --- a/x-pack/plugins/security_solution/public/exceptions/components/list_details_link_anchor/index.tsx +++ b/x-pack/plugins/security_solution/public/exceptions/components/list_details_link_anchor/index.tsx @@ -7,9 +7,9 @@ import React from 'react'; import type { FC } from 'react'; +import { RuleDetailTabs } from '../../../detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs'; import { SecurityPageName } from '../../../../common/constants'; import { getRuleDetailsTabUrl } from '../../../common/components/link_to/redirect_to_detection_engine'; -import { RuleDetailTabs } from '../../../detection_engine/rule_details_ui/pages/rule_details'; import { SecuritySolutionLinkAnchor } from '../../../common/components/links'; interface LinkAnchorProps { diff --git a/x-pack/plugins/security_solution/public/rules/routes.tsx b/x-pack/plugins/security_solution/public/rules/routes.tsx index aefdd505c95e0..7badb0c82a159 100644 --- a/x-pack/plugins/security_solution/public/rules/routes.tsx +++ b/x-pack/plugins/security_solution/public/rules/routes.tsx @@ -19,10 +19,7 @@ import { import { NotFoundPage } from '../app/404'; import { RulesPage } from '../detection_engine/rule_management_ui/pages/rule_management'; import { CreateRulePage } from '../detection_engine/rule_creation_ui/pages/rule_creation'; -import { - RuleDetailsPage, - RuleDetailTabs, -} from '../detection_engine/rule_details_ui/pages/rule_details'; +import { RuleDetailsPage } from '../detection_engine/rule_details_ui/pages/rule_details'; import { EditRulePage } from '../detection_engine/rule_creation_ui/pages/rule_editing'; import { useReadonlyHeader } from '../use_readonly_header'; import { PluginTemplateWrapper } from '../common/components/plugin_template_wrapper'; @@ -33,6 +30,7 @@ import type { SecuritySubPluginRoutes } from '../app/types'; import { RulesLandingPage } from './landing'; import { useIsExperimentalFeatureEnabled } from '../common/hooks/use_experimental_features'; import { CoverageOverviewPage } from '../detection_engine/rule_management_ui/pages/coverage_overview'; +import { RuleDetailTabs } from '../detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs'; const RulesSubRoutes = [ { From 1aa80b4e9ed44eb338bf8a9391e36088e6ffed68 Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola <michael.olorunnisola@elastic.co> Date: Mon, 28 Aug 2023 11:07:34 -0400 Subject: [PATCH 17/49] [Security Solution][Investigations] - fix expandable flyout navigation (#164918) ## Summary This PR aims at fixing a weird bug where the new expandable flyout automatically reopens when changing tabs, or clicking on the refresh button in the KQL bar. It seems that there is a conflict or a raise condition between the code that manages the url sync of the old flyout with the code that manages the url sync of the new flyout. The PR disables the old flyout navigation on initialization. _Weird thing is, while this fixed the issue, when I toggled the advanced setting off and then back on again, the issue stopped appearing all together. Still needs a bit more investigation..._ Before the fix https://github.com/elastic/kibana/assets/17276605/db3fff85-564e-480b-af26-bf4e59992560 After the fix https://github.com/elastic/kibana/assets/17276605/4bdf27bb-f9da-48bf-80d1-e2e83014c40c ### Steps to reproduce - navigate to the alerts page - open the flyout - refresh the page (browser refresh) with the flyout open - close the flyout - try to navigate to a different page (like cases) or try to click on the refresh button in the KQL bar ### Checklist - [ ] [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 --- .../hooks/flyout/use_init_flyout_url_param.ts | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/hooks/flyout/use_init_flyout_url_param.ts b/x-pack/plugins/security_solution/public/common/hooks/flyout/use_init_flyout_url_param.ts index fbbf7ea453efd..d6ab7acf0f955 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/flyout/use_init_flyout_url_param.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/flyout/use_init_flyout_url_param.ts @@ -15,12 +15,15 @@ import { tableDefaults, dataTableActions, } from '@kbn/securitysolution-data-table'; +import { ENABLE_EXPANDABLE_FLYOUT_SETTING } from '../../../../common/constants'; import { useInitializeUrlParam } from '../../utils/global_query_string'; import { URL_PARAM_KEY } from '../use_url_state'; import type { FlyoutUrlState } from './types'; import { useShallowEqualSelector } from '../use_selector'; +import { useUiSetting$ } from '../../lib/kibana'; export const useInitFlyoutFromUrlParam = () => { + const [isSecurityFlyoutEnabled] = useUiSetting$<boolean>(ENABLE_EXPANDABLE_FLYOUT_SETTING); const [urlDetails, setUrlDetails] = useState<FlyoutUrlState | null>(null); const [hasLoadedUrlDetails, updateHasLoadedUrlDetails] = useState(false); const dispatch = useDispatch(); @@ -32,16 +35,19 @@ export const useInitFlyoutFromUrlParam = () => { (state) => getDataTable(state, TableId.alertsOnAlertsPage) ?? tableDefaults ); - const onInitialize = useCallback((initialState: FlyoutUrlState | null) => { - if (initialState != null && initialState.panelView) { - setUrlDetails(initialState); - } - }, []); + const onInitialize = useCallback( + (initialState: FlyoutUrlState | null) => { + if (!isSecurityFlyoutEnabled && initialState != null && initialState.panelView) { + setUrlDetails(initialState); + } + }, + [isSecurityFlyoutEnabled] + ); const loadExpandedDetailFromUrl = useCallback(() => { const { initialized, isLoading, totalCount, additionalFilters } = dataTableCurrent; const isTableLoaded = initialized && !isLoading && totalCount > 0; - if (urlDetails) { + if (!isSecurityFlyoutEnabled && urlDetails) { if (!additionalFilters || !additionalFilters.showBuildingBlockAlerts) { // We want to show building block alerts when loading the flyout in case the alert is a building block alert dispatch( @@ -62,7 +68,7 @@ export const useInitFlyoutFromUrlParam = () => { ); } } - }, [dataTableCurrent, dispatch, urlDetails]); + }, [dataTableCurrent, dispatch, isSecurityFlyoutEnabled, urlDetails]); // The alert page creates a default dataTable slice in redux initially that is later overriden when data is retrieved // We use the below to store the urlDetails on app load, and then set it when the table is done loading and has data @@ -72,5 +78,11 @@ export const useInitFlyoutFromUrlParam = () => { } }, [hasLoadedUrlDetails, loadExpandedDetailFromUrl]); - useInitializeUrlParam(URL_PARAM_KEY.eventFlyout, onInitialize); + /** + * The URL_PARAM_KEY.eventFlyout is used for the old flyout as well as the new expandable flyout here: + * x-pack/plugins/security_solution/public/common/hooks/flyout/use_sync_flyout_url_param.ts + * We only want this to run for the old flyout. + */ + const initializeKey = isSecurityFlyoutEnabled ? '' : URL_PARAM_KEY.eventFlyout; + useInitializeUrlParam(initializeKey, onInitialize); }; From f2f7216487e77efc791a99abdc6f8ce651a23240 Mon Sep 17 00:00:00 2001 From: jennypavlova <dzheni.pavlova@elastic.co> Date: Mon, 28 Aug 2023 17:23:30 +0200 Subject: [PATCH 18/49] [Infra UI] Implement Metric charts section (#164538) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes [#162942](https://github.com/elastic/kibana/issues/162942) ## Summary This PR adds new metrics to the asset details page: - CPU usage (Broken down) - Load (Broken down) - Memory Usage (Broken down) - Disk Usage by Mount Point The hosts view flyout metrics remain the same as before. ## Testing ⚠️ I would suggest running metricbeat in Docker as some of the metrics used in `CPU usage (Broken down)` are not available in MacOs (in discussion with beats team currently) - Go to hosts page - Open the flyout for a host - Click open as page link - Check the new metrics on different screen size (the labels should be visible as shown: ![Image](https://github.com/elastic/kibana/assets/14139027/6d98996b-2eb1-414b-92a2-870932ad4284) ![Image](https://github.com/elastic/kibana/assets/14139027/e612c7b4-8d93-4c42-883b-fc5e620ab2a0) --- .../public/common/visualizations/constants.ts | 26 ++ .../asset_details/host/host_metric_charts.ts | 242 +++--------------- .../lens/dashboards/asset_details/index.ts | 4 +- .../asset_details/metric_charts/cpu.ts | 96 +++++++ .../asset_details/metric_charts/disk.ts | 150 +++++++++++ .../asset_details/metric_charts/log.ts | 24 ++ .../asset_details/metric_charts/memory.ts | 67 +++++ .../asset_details/metric_charts/network.ts | 44 ++++ .../asset_details/metric_charts/types.ts | 14 + .../lens/dashboards/constants.ts | 2 +- .../lens/formulas/host/cpu_usage_iowait.ts | 19 ++ .../lens/formulas/host/cpu_usage_irq.ts | 19 ++ .../lens/formulas/host/cpu_usage_nice.ts | 19 ++ .../lens/formulas/host/cpu_usage_softirq.ts | 19 ++ .../lens/formulas/host/cpu_usage_steal.ts | 19 ++ .../lens/formulas/host/cpu_usage_system.ts | 19 ++ .../lens/formulas/host/cpu_usage_user.ts | 19 ++ .../lens/formulas/host/index.ts | 13 + .../lens/formulas/host/load_15m.ts | 19 ++ .../lens/formulas/host/load_1m.ts | 19 ++ .../lens/formulas/host/load_5m.ts | 19 ++ .../lens/formulas/host/memory_cache.ts | 19 ++ .../host/memory_free_excluding_cache.ts | 19 ++ .../lens/formulas/host/memory_used.ts | 19 ++ .../tabs/overview/metrics/metrics_grid.tsx | 46 ++-- .../asset_details/tabs/overview/overview.tsx | 1 + .../public/components/asset_details/types.ts | 2 + .../public/components/lens/lens_wrapper.tsx | 3 - .../functional/apps/infra/node_details.ts | 4 +- 29 files changed, 747 insertions(+), 238 deletions(-) create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/cpu.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/disk.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/log.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/memory.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/network.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/types.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_iowait.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_irq.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_nice.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_softirq.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_steal.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_system.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_user.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_15m.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_1m.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_5m.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_cache.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_free_excluding_cache.ts create mode 100644 x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_used.ts diff --git a/x-pack/plugins/infra/public/common/visualizations/constants.ts b/x-pack/plugins/infra/public/common/visualizations/constants.ts index 1ef3484843507..499dc6f212850 100644 --- a/x-pack/plugins/infra/public/common/visualizations/constants.ts +++ b/x-pack/plugins/infra/public/common/visualizations/constants.ts @@ -7,6 +7,13 @@ import { cpuUsage, + cpuUsageIowait, + cpuUsageIrq, + cpuUsageNice, + cpuUsageSoftirq, + cpuUsageSteal, + cpuUsageUser, + cpuUsageSystem, diskIORead, diskIOWrite, diskReadThroughput, @@ -16,8 +23,14 @@ import { diskSpaceUsage, logRate, normalizedLoad1m, + load1m, + load5m, + load15m, memoryUsage, memoryFree, + memoryUsed, + memoryFreeExcludingCache, + memoryCache, rx, tx, hostCount, @@ -25,6 +38,13 @@ import { export const hostLensFormulas = { cpuUsage, + cpuUsageIowait, + cpuUsageIrq, + cpuUsageNice, + cpuUsageSoftirq, + cpuUsageSteal, + cpuUsageUser, + cpuUsageSystem, diskIORead, diskIOWrite, diskReadThroughput, @@ -35,8 +55,14 @@ export const hostLensFormulas = { hostCount, logRate, normalizedLoad1m, + load1m, + load5m, + load15m, memoryUsage, memoryFree, + memoryUsed, + memoryFreeExcludingCache, + memoryCache, rx, tx, }; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/host/host_metric_charts.ts b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/host/host_metric_charts.ts index e864044c928ad..0c31e1f2e6643 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/host/host_metric_charts.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/host/host_metric_charts.ts @@ -4,214 +4,40 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { cpuUsage, normalizedLoad1m, cpuUsageBreakdown, loadBreakdown } from '../metric_charts/cpu'; +import { + diskSpaceUsageAvailable, + diskThroughputReadWrite, + diskIOReadWrite, + diskSpaceUsageByMountPoint, +} from '../metric_charts/disk'; +import { logRate } from '../metric_charts/log'; +import { memoryUsage, memoryUsageBreakdown } from '../metric_charts/memory'; +import { rxTx } from '../metric_charts/network'; +import type { XYConfig } from '../metric_charts/types'; -import { i18n } from '@kbn/i18n'; -import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { hostLensFormulas } from '../../../../constants'; -import type { XYChartLayerParams } from '../../../../types'; -import { REFERENCE_LINE, XY_OVERRIDES } from '../../constants'; - -type DataViewOrigin = 'logs' | 'metrics'; - -export const hostMetricCharts: Array< - Pick<TypedLensByValueInput, 'id' | 'title' | 'overrides'> & { - dataViewOrigin: DataViewOrigin; - layers: XYChartLayerParams[]; - } -> = [ - { - id: 'cpuUsage', - title: i18n.translate('xpack.infra.assetDetails.metricsCharts.cpuUsage', { - defaultMessage: 'CPU Usage', - }), +export const hostMetricCharts: XYConfig[] = [ + cpuUsage, + memoryUsage, + normalizedLoad1m, + logRate, + diskSpaceUsageAvailable, + diskThroughputReadWrite, + diskIOReadWrite, + rxTx, +]; - layers: [ - { - data: [hostLensFormulas.cpuUsage], - type: 'visualization', - }, - ], - dataViewOrigin: 'metrics', - overrides: { - axisLeft: XY_OVERRIDES.axisLeft, - }, - }, - { - id: 'memoryUsage', - title: i18n.translate('xpack.infra.assetDetails.metricsCharts.memoryUsage', { - defaultMessage: 'Memory Usage', - }), - layers: [ - { - data: [hostLensFormulas.memoryUsage], - type: 'visualization', - }, - ], - dataViewOrigin: 'metrics', - overrides: { - axisLeft: XY_OVERRIDES.axisLeft, - }, - }, - { - id: 'normalizedLoad1m', - title: i18n.translate('xpack.infra.assetDetails.metricsCharts.normalizedLoad1m', { - defaultMessage: 'Normalized Load', - }), - layers: [ - { - data: [hostLensFormulas.normalizedLoad1m], - type: 'visualization', - }, - { - data: [REFERENCE_LINE], - type: 'referenceLines', - }, - ], - dataViewOrigin: 'metrics', - }, - { - id: 'logRate', - title: i18n.translate('xpack.infra.assetDetails.metricsCharts.logRate', { - defaultMessage: 'Log Rate', - }), - layers: [ - { - data: [hostLensFormulas.logRate], - type: 'visualization', - }, - ], - dataViewOrigin: 'logs', - }, - { - id: 'diskSpaceUsageAvailable', - title: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskSpace', { - defaultMessage: 'Disk Space', - }), - layers: [ - { - data: [ - { - ...hostLensFormulas.diskSpaceUsage, - label: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskSpace.label.used', { - defaultMessage: 'Used', - }), - }, - { - ...hostLensFormulas.diskSpaceAvailability, - label: i18n.translate( - 'xpack.infra.assetDetails.metricsCharts.diskSpace.label.available', - { - defaultMessage: 'Available', - } - ), - }, - ], - options: { - seriesType: 'area', - }, - type: 'visualization', - }, - ], - overrides: { - axisLeft: XY_OVERRIDES.axisLeft, - settings: XY_OVERRIDES.settings, - }, - dataViewOrigin: 'metrics', - }, - { - id: 'diskThroughputReadWrite', - title: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskIOPS', { - defaultMessage: 'Disk IOPS', - }), - layers: [ - { - data: [ - { - ...hostLensFormulas.diskIORead, - label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.read', { - defaultMessage: 'Read', - }), - }, - { - ...hostLensFormulas.diskIOWrite, - label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.write', { - defaultMessage: 'Write', - }), - }, - ], - options: { - seriesType: 'area', - }, - type: 'visualization', - }, - ], - overrides: { - settings: XY_OVERRIDES.settings, - }, - dataViewOrigin: 'metrics', - }, - { - id: 'diskIOReadWrite', - title: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskThroughput', { - defaultMessage: 'Disk Throughput', - }), - layers: [ - { - data: [ - { - ...hostLensFormulas.diskReadThroughput, - label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.read', { - defaultMessage: 'Read', - }), - }, - { - ...hostLensFormulas.diskWriteThroughput, - label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.write', { - defaultMessage: 'Write', - }), - }, - ], - options: { - seriesType: 'area', - }, - type: 'visualization', - }, - ], - overrides: { - settings: XY_OVERRIDES.settings, - }, - dataViewOrigin: 'metrics', - }, - { - id: 'rxTx', - title: i18n.translate('xpack.infra.assetDetails.metricsCharts.network', { - defaultMessage: 'Network', - }), - layers: [ - { - data: [ - { - ...hostLensFormulas.rx, - label: i18n.translate('xpack.infra.assetDetails.metricsCharts.network.label.rx', { - defaultMessage: 'Inbound (RX)', - }), - }, - { - ...hostLensFormulas.tx, - label: i18n.translate('xpack.infra.assetDetails.metricsCharts.network.label.tx', { - defaultMessage: 'Outbound (TX)', - }), - }, - ], - options: { - seriesType: 'area', - }, - type: 'visualization', - }, - ], - overrides: { - settings: XY_OVERRIDES.settings, - }, - dataViewOrigin: 'metrics', - }, +export const hostMetricChartsFullPage: XYConfig[] = [ + cpuUsage, + cpuUsageBreakdown, + memoryUsage, + memoryUsageBreakdown, + normalizedLoad1m, + loadBreakdown, + logRate, + diskSpaceUsageAvailable, + diskSpaceUsageByMountPoint, + diskThroughputReadWrite, + diskIOReadWrite, + rxTx, ]; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/index.ts b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/index.ts index aacc3876980e4..4222b145e2552 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/index.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/index.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { hostMetricCharts } from './host/host_metric_charts'; +import { hostMetricCharts, hostMetricChartsFullPage } from './host/host_metric_charts'; import { hostKPICharts, KPIChartProps } from './host/host_kpi_charts'; export { type KPIChartProps }; export const assetDetailsDashboards = { - host: { hostMetricCharts, hostKPICharts }, + host: { hostMetricCharts, hostMetricChartsFullPage, hostKPICharts }, }; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/cpu.ts b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/cpu.ts new file mode 100644 index 0000000000000..6e9c53cce635e --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/cpu.ts @@ -0,0 +1,96 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { hostLensFormulas } from '../../../../constants'; +import { REFERENCE_LINE, XY_OVERRIDES } from '../../constants'; +import type { XYConfig } from './types'; + +export const cpuUsage: XYConfig = { + id: 'cpuUsage', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.cpuUsage', { + defaultMessage: 'CPU Usage', + }), + + layers: [ + { + data: [hostLensFormulas.cpuUsage], + type: 'visualization', + }, + ], + dataViewOrigin: 'metrics', + overrides: { + axisLeft: XY_OVERRIDES.axisLeft, + }, +}; + +export const cpuUsageBreakdown: XYConfig = { + id: 'cpuUsageBreakdown', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.cpuUsage', { + defaultMessage: 'CPU Usage', + }), + layers: [ + { + data: [ + hostLensFormulas.cpuUsageIowait, + hostLensFormulas.cpuUsageIrq, + hostLensFormulas.cpuUsageNice, + hostLensFormulas.cpuUsageSoftirq, + hostLensFormulas.cpuUsageSteal, + hostLensFormulas.cpuUsageUser, + hostLensFormulas.cpuUsageSystem, + ], + options: { + seriesType: 'area_percentage_stacked', + }, + type: 'visualization', + }, + ], + overrides: { + axisLeft: XY_OVERRIDES.axisLeft, + settings: XY_OVERRIDES.settings, + }, + dataViewOrigin: 'metrics', +}; + +export const normalizedLoad1m: XYConfig = { + id: 'normalizedLoad1m', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.normalizedLoad1m', { + defaultMessage: 'Normalized Load', + }), + layers: [ + { + data: [hostLensFormulas.normalizedLoad1m], + type: 'visualization', + }, + { + data: [REFERENCE_LINE], + type: 'referenceLines', + }, + ], + dataViewOrigin: 'metrics', +}; + +export const loadBreakdown: XYConfig = { + id: 'loadBreakdown', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.load', { + defaultMessage: 'Load', + }), + layers: [ + { + data: [hostLensFormulas.load1m, hostLensFormulas.load5m, hostLensFormulas.load15m], + options: { + seriesType: 'area', + }, + type: 'visualization', + }, + ], + overrides: { + settings: XY_OVERRIDES.settings, + }, + dataViewOrigin: 'metrics', +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/disk.ts b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/disk.ts new file mode 100644 index 0000000000000..8d2daa435fbdc --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/disk.ts @@ -0,0 +1,150 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { hostLensFormulas } from '../../../../constants'; +import { XY_OVERRIDES } from '../../constants'; +import type { XYConfig } from './types'; + +const TOP_VALUES_SIZE = 5; + +export const diskSpaceUsageAvailable: XYConfig = { + id: 'diskSpaceUsageAvailable', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskSpace', { + defaultMessage: 'Disk Space', + }), + layers: [ + { + data: [ + { + ...hostLensFormulas.diskSpaceUsage, + label: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskSpace.label.used', { + defaultMessage: 'Used', + }), + }, + { + ...hostLensFormulas.diskSpaceAvailability, + label: i18n.translate( + 'xpack.infra.assetDetails.metricsCharts.diskSpace.label.available', + { + defaultMessage: 'Available', + } + ), + }, + ], + options: { + seriesType: 'area', + }, + type: 'visualization', + }, + ], + overrides: { + axisLeft: XY_OVERRIDES.axisLeft, + settings: XY_OVERRIDES.settings, + }, + dataViewOrigin: 'metrics', +}; + +export const diskSpaceUsageByMountPoint: XYConfig = { + id: 'DiskSpaceUsageByMountPoint', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskSpaceByMountingPoint', { + defaultMessage: 'Disk Space by Mount Point', + }), + layers: [ + { + data: [ + { + ...hostLensFormulas.diskSpaceUsage, + label: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskSpace.label.used', { + defaultMessage: 'Used', + }), + }, + ], + options: { + seriesType: 'area', + breakdown: { + type: 'top_values', + field: 'system.filesystem.mount_point', + params: { + size: TOP_VALUES_SIZE, + }, + }, + }, + type: 'visualization', + }, + ], + overrides: { + axisLeft: XY_OVERRIDES.axisLeft, + }, + dataViewOrigin: 'metrics', +}; + +export const diskThroughputReadWrite: XYConfig = { + id: 'diskThroughputReadWrite', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskIOPS', { + defaultMessage: 'Disk IOPS', + }), + layers: [ + { + data: [ + { + ...hostLensFormulas.diskIORead, + label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.read', { + defaultMessage: 'Read', + }), + }, + { + ...hostLensFormulas.diskIOWrite, + label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.write', { + defaultMessage: 'Write', + }), + }, + ], + options: { + seriesType: 'area', + }, + type: 'visualization', + }, + ], + overrides: { + settings: XY_OVERRIDES.settings, + }, + dataViewOrigin: 'metrics', +}; + +export const diskIOReadWrite: XYConfig = { + id: 'diskIOReadWrite', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskThroughput', { + defaultMessage: 'Disk Throughput', + }), + layers: [ + { + data: [ + { + ...hostLensFormulas.diskReadThroughput, + label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.read', { + defaultMessage: 'Read', + }), + }, + { + ...hostLensFormulas.diskWriteThroughput, + label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.write', { + defaultMessage: 'Write', + }), + }, + ], + options: { + seriesType: 'area', + }, + type: 'visualization', + }, + ], + overrides: { + settings: XY_OVERRIDES.settings, + }, + dataViewOrigin: 'metrics', +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/log.ts b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/log.ts new file mode 100644 index 0000000000000..811b0faa32a23 --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/log.ts @@ -0,0 +1,24 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { hostLensFormulas } from '../../../../constants'; +import type { XYConfig } from './types'; + +export const logRate: XYConfig = { + id: 'logRate', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.logRate', { + defaultMessage: 'Log Rate', + }), + layers: [ + { + data: [hostLensFormulas.logRate], + type: 'visualization', + }, + ], + dataViewOrigin: 'logs', +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/memory.ts b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/memory.ts new file mode 100644 index 0000000000000..c933a6fc424fa --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/memory.ts @@ -0,0 +1,67 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { hostLensFormulas } from '../../../../constants'; +import { XY_OVERRIDES } from '../../constants'; +import type { XYConfig } from './types'; + +export const memoryUsage: XYConfig = { + id: 'memoryUsage', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.memoryUsage', { + defaultMessage: 'Memory Usage', + }), + layers: [ + { + data: [hostLensFormulas.memoryUsage], + type: 'visualization', + }, + ], + dataViewOrigin: 'metrics', + overrides: { + axisLeft: XY_OVERRIDES.axisLeft, + }, +}; + +export const memoryUsageBreakdown: XYConfig = { + id: 'memoryUsage', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.memoryUsage', { + defaultMessage: 'Memory Usage', + }), + layers: [ + { + data: [ + { + ...hostLensFormulas.memoryCache, + label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.cache', { + defaultMessage: 'Cache', + }), + }, + { + ...hostLensFormulas.memoryUsed, + label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.used', { + defaultMessage: 'Used', + }), + }, + { + ...hostLensFormulas.memoryFreeExcludingCache, + label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.free', { + defaultMessage: 'Free', + }), + }, + ], + options: { + seriesType: 'area_stacked', + }, + type: 'visualization', + }, + ], + overrides: { + settings: XY_OVERRIDES.settings, + }, + dataViewOrigin: 'metrics', +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/network.ts b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/network.ts new file mode 100644 index 0000000000000..5baa9d6d2e489 --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/network.ts @@ -0,0 +1,44 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { hostLensFormulas } from '../../../../constants'; +import { XY_OVERRIDES } from '../../constants'; +import type { XYConfig } from './types'; + +export const rxTx: XYConfig = { + id: 'rxTx', + title: i18n.translate('xpack.infra.assetDetails.metricsCharts.network', { + defaultMessage: 'Network', + }), + layers: [ + { + data: [ + { + ...hostLensFormulas.rx, + label: i18n.translate('xpack.infra.assetDetails.metricsCharts.network.label.rx', { + defaultMessage: 'Inbound (RX)', + }), + }, + { + ...hostLensFormulas.tx, + label: i18n.translate('xpack.infra.assetDetails.metricsCharts.network.label.tx', { + defaultMessage: 'Outbound (TX)', + }), + }, + ], + options: { + seriesType: 'area', + }, + type: 'visualization', + }, + ], + overrides: { + settings: XY_OVERRIDES.settings, + }, + dataViewOrigin: 'metrics', +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/types.ts b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/types.ts new file mode 100644 index 0000000000000..0daff60793d52 --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/asset_details/metric_charts/types.ts @@ -0,0 +1,14 @@ +/* + * 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 { TypedLensByValueInput } from '@kbn/lens-plugin/public'; +import type { DataViewOrigin } from '../../../../../../components/asset_details/types'; +import type { XYChartLayerParams } from '../../../../types'; + +export type XYConfig = Pick<TypedLensByValueInput, 'id' | 'title' | 'overrides'> & { + dataViewOrigin: DataViewOrigin; + layers: XYChartLayerParams[]; +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/constants.ts b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/constants.ts index 9d37c3cc9596f..5efc100ada739 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/constants.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/constants.ts @@ -34,7 +34,7 @@ export const XY_OVERRIDES: XYOverrides = { settings: { showLegend: true, legendPosition: 'bottom', - legendSize: 35, + legendSize: 50, }, }; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_iowait.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_iowait.ts new file mode 100644 index 0000000000000..3e811a7ad517f --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_iowait.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const cpuUsageIowait: FormulaValueConfig = { + label: 'iowait', + value: 'average(system.cpu.iowait.pct) / max(system.cpu.cores)', + format: { + id: 'percent', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_irq.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_irq.ts new file mode 100644 index 0000000000000..68cdbe9b65ea5 --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_irq.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const cpuUsageIrq: FormulaValueConfig = { + label: 'irq', + value: 'average(system.cpu.irq.pct) / max(system.cpu.cores)', + format: { + id: 'percent', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_nice.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_nice.ts new file mode 100644 index 0000000000000..6ab8e01fec0c7 --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_nice.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const cpuUsageNice: FormulaValueConfig = { + label: 'nice', + value: 'average(system.cpu.nice.norm.pct) / max(system.cpu.cores)', + format: { + id: 'percent', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_softirq.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_softirq.ts new file mode 100644 index 0000000000000..bb26685b9d8bc --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_softirq.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const cpuUsageSoftirq: FormulaValueConfig = { + label: 'softirq', + value: 'average(system.cpu.softirq.pct) / max(system.cpu.cores)', + format: { + id: 'percent', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_steal.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_steal.ts new file mode 100644 index 0000000000000..ec0fa2652427c --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_steal.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const cpuUsageSteal: FormulaValueConfig = { + label: 'steal', + value: 'average(system.cpu.steal.pct) / max(system.cpu.cores)', + format: { + id: 'percent', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_system.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_system.ts new file mode 100644 index 0000000000000..303ff89aa256e --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_system.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const cpuUsageSystem: FormulaValueConfig = { + label: 'system', + value: 'average(system.cpu.system.pct) / max(system.cpu.cores)', + format: { + id: 'percent', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_user.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_user.ts new file mode 100644 index 0000000000000..d24c9b82a199a --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage_user.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const cpuUsageUser: FormulaValueConfig = { + label: 'user', + value: 'average(system.cpu.user.pct) / max(system.cpu.cores)', + format: { + id: 'percent', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/index.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/index.ts index 9cec01155ac19..1741741951e1a 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/index.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/index.ts @@ -6,6 +6,13 @@ */ export { cpuUsage } from './cpu_usage'; +export { cpuUsageIowait } from './cpu_usage_iowait'; +export { cpuUsageIrq } from './cpu_usage_irq'; +export { cpuUsageNice } from './cpu_usage_nice'; +export { cpuUsageSoftirq } from './cpu_usage_softirq'; +export { cpuUsageSteal } from './cpu_usage_steal'; +export { cpuUsageUser } from './cpu_usage_user'; +export { cpuUsageSystem } from './cpu_usage_system'; export { diskIORead } from './disk_read_iops'; export { diskIOWrite } from './disk_write_iops'; export { diskReadThroughput } from './disk_read_throughput'; @@ -16,7 +23,13 @@ export { diskSpaceUsage } from './disk_space_usage'; export { hostCount } from './host_count'; export { logRate } from './log_rate'; export { normalizedLoad1m } from './normalized_load_1m'; +export { load1m } from './load_1m'; +export { load5m } from './load_5m'; +export { load15m } from './load_15m'; export { memoryUsage } from './memory_usage'; export { memoryFree } from './memory_free'; +export { memoryUsed } from './memory_used'; +export { memoryFreeExcludingCache } from './memory_free_excluding_cache'; +export { memoryCache } from './memory_cache'; export { rx } from './rx'; export { tx } from './tx'; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_15m.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_15m.ts new file mode 100644 index 0000000000000..f34ee8aa31bdf --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_15m.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const load15m: FormulaValueConfig = { + label: 'Load (15m)', + value: 'average(system.load.15)', + format: { + id: 'number', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_1m.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_1m.ts new file mode 100644 index 0000000000000..ac11637fdab56 --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_1m.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const load1m: FormulaValueConfig = { + label: 'Load (1m)', + value: 'average(system.load.1)', + format: { + id: 'number', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_5m.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_5m.ts new file mode 100644 index 0000000000000..1fb8c15fc5888 --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/load_5m.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const load5m: FormulaValueConfig = { + label: 'Load (5m)', + value: 'average(system.load.5)', + format: { + id: 'number', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_cache.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_cache.ts new file mode 100644 index 0000000000000..6688f51fb49c5 --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_cache.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const memoryCache: FormulaValueConfig = { + label: 'cache', + value: 'average(system.memory.used.bytes) - average(system.memory.actual.used.bytes)', + format: { + id: 'bytes', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_free_excluding_cache.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_free_excluding_cache.ts new file mode 100644 index 0000000000000..96890b22a7472 --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_free_excluding_cache.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const memoryFreeExcludingCache: FormulaValueConfig = { + label: 'free', + value: 'average(system.memory.free)', + format: { + id: 'bytes', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_used.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_used.ts new file mode 100644 index 0000000000000..8df1f24353d6a --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_used.ts @@ -0,0 +1,19 @@ +/* + * 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 { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; + +export const memoryUsed: FormulaValueConfig = { + label: 'used', + value: 'average(system.memory.actual.used.bytes)', + format: { + id: 'bytes', + params: { + decimals: 1, + }, + }, +}; diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/metrics/metrics_grid.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/metrics/metrics_grid.tsx index aa07a10686e6a..9b5953f9292dd 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/metrics/metrics_grid.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/metrics/metrics_grid.tsx @@ -19,9 +19,9 @@ import { buildCombinedHostsFilter } from '../../../../../utils/filters/build'; import { LensChart, HostMetricsExplanationContent } from '../../../../lens'; import { METRIC_CHART_HEIGHT } from '../../../constants'; import { Popover } from '../../common/popover'; +import type { DataViewOrigin } from '../../../types'; import { useDateRangeProviderContext } from '../../../hooks/use_date_range'; -type DataViewOrigin = 'logs' | 'metrics'; type BrushEndArgs = Parameters<NonNullable<LensEmbeddableInput['onBrushEnd']>>[0]; interface Props { @@ -29,10 +29,11 @@ interface Props { timeRange: TimeRange; metricsDataView?: DataView; logsDataView?: DataView; + isCompactView: boolean; } export const MetricsGrid = React.memo( - ({ nodeName, metricsDataView, logsDataView, timeRange }: Props) => { + ({ nodeName, metricsDataView, logsDataView, timeRange, isCompactView }: Props) => { const { setDateRange } = useDateRangeProviderContext(); const getDataView = useCallback( (dataViewOrigin: DataViewOrigin) => { @@ -78,26 +79,27 @@ export const MetricsGrid = React.memo( gutterSize="s" data-test-subj="infraAssetDetailsMetricsChartGrid" > - {assetDetailsDashboards.host.hostMetricCharts.map( - ({ dataViewOrigin, id, layers, title, overrides }, index) => ( - <EuiFlexItem key={index} grow={false}> - <LensChart - id={`infraAssetDetailsMetricsChart${id}`} - borderRadius="m" - dataView={getDataView(dataViewOrigin)} - dateRange={timeRange} - height={METRIC_CHART_HEIGHT} - visualOptions={XY_MISSING_VALUE_DOTTED_LINE_CONFIG} - layers={layers} - filters={getFilters(dataViewOrigin)} - title={title} - overrides={overrides} - visualizationType="lnsXY" - onBrushEnd={handleBrushEnd} - /> - </EuiFlexItem> - ) - )} + {(isCompactView + ? assetDetailsDashboards.host.hostMetricCharts + : assetDetailsDashboards.host.hostMetricChartsFullPage + ).map(({ dataViewOrigin, id, layers, title, overrides }, index) => ( + <EuiFlexItem key={index} grow={false}> + <LensChart + id={`infraAssetDetailsMetricsChart${id}`} + borderRadius="m" + dataView={getDataView(dataViewOrigin)} + dateRange={timeRange} + height={METRIC_CHART_HEIGHT} + visualOptions={XY_MISSING_VALUE_DOTTED_LINE_CONFIG} + layers={layers} + filters={getFilters(dataViewOrigin)} + title={title} + overrides={overrides} + visualizationType="lnsXY" + onBrushEnd={handleBrushEnd} + /> + </EuiFlexItem> + ))} </EuiFlexGrid> </EuiFlexItem> </EuiFlexGroup> diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/overview.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/overview.tsx index 3104fdf6b5f85..27f597977b70e 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/overview.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/overview.tsx @@ -80,6 +80,7 @@ export const Overview = () => { logsDataView={logs.dataView} metricsDataView={metrics.dataView} nodeName={asset.name} + isCompactView={renderMode?.mode === 'flyout'} /> </EuiFlexItem> </EuiFlexGroup> diff --git a/x-pack/plugins/infra/public/components/asset_details/types.ts b/x-pack/plugins/infra/public/components/asset_details/types.ts index 839154a4b9d33..b2cb2bee2dfbf 100644 --- a/x-pack/plugins/infra/public/components/asset_details/types.ts +++ b/x-pack/plugins/infra/public/components/asset_details/types.ts @@ -87,3 +87,5 @@ export type TabsStateChangeFn = (state: TabState) => void; export interface ContentTemplateProps { header: Pick<AssetDetailsProps, 'tabs' | 'links'>; } + +export type DataViewOrigin = 'logs' | 'metrics'; diff --git a/x-pack/plugins/infra/public/components/lens/lens_wrapper.tsx b/x-pack/plugins/infra/public/components/lens/lens_wrapper.tsx index 043173113c5a5..8513881c22ada 100644 --- a/x-pack/plugins/infra/public/components/lens/lens_wrapper.tsx +++ b/x-pack/plugins/infra/public/components/lens/lens_wrapper.tsx @@ -107,9 +107,6 @@ export const LensWrapper = ({ border-radius: ${euiTheme.size.s}; overflow: hidden; height: 100%; - .echLegend .echLegendList { - display: flex; - } .echMetric { border-radius: ${euiTheme.border.radius.medium}; pointer-events: none; diff --git a/x-pack/test/functional/apps/infra/node_details.ts b/x-pack/test/functional/apps/infra/node_details.ts index 7e2bdba6ecf39..ba73529d76393 100644 --- a/x-pack/test/functional/apps/infra/node_details.ts +++ b/x-pack/test/functional/apps/infra/node_details.ts @@ -142,9 +142,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); }); - it('should render 8 charts in the Metrics section', async () => { + it('should render 12 charts in the Metrics section', async () => { const hosts = await pageObjects.assetDetails.getAssetDetailsMetricsCharts(); - expect(hosts.length).to.equal(8); + expect(hosts.length).to.equal(12); }); it('should show alerts', async () => { From 191bedaa5dea78ccd928f2177b17919793f01da5 Mon Sep 17 00:00:00 2001 From: Jordan <51442161+JordanSh@users.noreply.github.com> Date: Mon, 28 Aug 2023 18:33:03 +0300 Subject: [PATCH 19/49] [Cloud Security] Fix page size bug (#164428) --- .../use_cloud_posture_table.ts | 34 +++- .../pages/vulnerabilities/vulnerabilities.tsx | 158 +++++++++++------- .../resource_vulnerabilities.tsx | 71 +++++--- .../vulnerabilities_by_resource.tsx | 65 +++++-- 4 files changed, 229 insertions(+), 99 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_table/use_cloud_posture_table.ts b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_table/use_cloud_posture_table.ts index b26af81cdff43..2d42c2a8303d6 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_table/use_cloud_posture_table.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_table/use_cloud_posture_table.ts @@ -4,12 +4,39 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { useCallback } from 'react'; +import { Dispatch, SetStateAction, useCallback } from 'react'; import { type DataView } from '@kbn/data-views-plugin/common'; +import { BoolQuery } from '@kbn/es-query'; +import { CriteriaWithPagination } from '@elastic/eui'; import { useUrlQuery } from '../use_url_query'; import { usePageSize } from '../use_page_size'; import { getDefaultQuery, useBaseEsQuery, usePersistedQuery } from './utils'; +interface QuerySort { + direction: string; + id: string; +} + +export interface CloudPostureTableResult { + setUrlQuery: (query: any) => void; + // TODO: remove any, this sorting is used for both EuiGrid and EuiTable which uses different types of sorts + sort: any; + filters: any[]; + query?: { bool: BoolQuery }; + queryError?: Error; + pageIndex: number; + // TODO: remove any, urlQuery is an object with query fields but we also add custom fields to it, need to assert usages + urlQuery: any; + setTableOptions: (options: CriteriaWithPagination<object>) => void; + handleUpdateQuery: (query: any) => void; + pageSize: number; + setPageSize: Dispatch<SetStateAction<number | undefined>>; + onChangeItemsPerPage: (newPageSize: number) => void; + onChangePage: (newPageIndex: number) => void; + onSort: (sort: QuerySort[]) => void; + onResetFilters: () => void; +} + /* Hook for managing common table state and methods for Cloud Posture */ @@ -21,7 +48,7 @@ export const useCloudPostureTable = ({ defaultQuery?: (params: any) => any; dataView: DataView; paginationLocalStorageKey: string; -}) => { +}): CloudPostureTableResult => { const getPersistedDefaultQuery = usePersistedQuery(defaultQuery); const { urlQuery, setUrlQuery } = useUrlQuery(getPersistedDefaultQuery); const { pageSize, setPageSize } = usePageSize(paginationLocalStorageKey); @@ -31,9 +58,10 @@ export const useCloudPostureTable = ({ setPageSize(newPageSize); setUrlQuery({ pageIndex: 0, + pageSize: newPageSize, }); }, - [setUrlQuery, setPageSize] + [setPageSize, setUrlQuery] ); const onResetFilters = useCallback(() => { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx index 9e241364f6c01..d0b6412eaa393 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx @@ -20,7 +20,10 @@ import React, { useCallback, useMemo, useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { Routes, Route } from '@kbn/shared-ux-router'; import { LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY } from '../../common/constants'; -import { useCloudPostureTable } from '../../common/hooks/use_cloud_posture_table'; +import { + CloudPostureTableResult, + useCloudPostureTable, +} from '../../common/hooks/use_cloud_posture_table'; import { useLatestVulnerabilities } from './hooks/use_latest_vulnerabilities'; import type { VulnerabilitiesQueryData } from './types'; import { LATEST_VULNERABILITIES_INDEX_PATTERN } from '../../../common/constants'; @@ -63,67 +66,35 @@ const getDefaultQuery = ({ query, filters }: any): any => ({ pageIndex: 0, }); -export const Vulnerabilities = () => { - const { data, isLoading, error } = useFilteredDataView(LATEST_VULNERABILITIES_INDEX_PATTERN); - const getSetupStatus = useCspSetupStatusApi(); - - if (getSetupStatus?.data?.vuln_mgmt?.status !== 'indexed') return <NoVulnerabilitiesStates />; - - if (error) { - return <ErrorCallout error={error as Error} />; - } - if (isLoading) { - return defaultLoadingRenderer(); - } - - if (!data) { - return defaultNoDataRenderer(); - } - - return ( - <Routes> - <Route - exact - path={findingsNavigation.resource_vulnerabilities.path} - render={() => <ResourceVulnerabilities dataView={data} />} - /> - <Route - exact - path={findingsNavigation.vulnerabilities_by_resource.path} - render={() => <VulnerabilitiesByResource dataView={data} />} - /> - <Route - path={findingsNavigation.vulnerabilities.path} - render={() => <VulnerabilitiesContent dataView={data} />} - /> - </Routes> - ); -}; - const VulnerabilitiesDataGrid = ({ dataView, data, isFetching, + onChangeItemsPerPage, + onChangePage, + onSort, + urlQuery, + onResetFilters, + pageSize, + setUrlQuery, + pageIndex, + sort, }: { dataView: DataView; data: VulnerabilitiesQueryData | undefined; isFetching: boolean; -}) => { - const { - pageIndex, - sort, - pageSize, - onChangeItemsPerPage, - onChangePage, - onSort, - urlQuery, - setUrlQuery, - onResetFilters, - } = useCloudPostureTable({ - dataView, - defaultQuery: getDefaultQuery, - paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, - }); +} & Pick< + CloudPostureTableResult, + | 'pageIndex' + | 'sort' + | 'pageSize' + | 'onChangeItemsPerPage' + | 'onChangePage' + | 'onSort' + | 'urlQuery' + | 'setUrlQuery' + | 'onResetFilters' +>) => { const { euiTheme } = useEuiTheme(); const styles = useStyles(); const [showHighlight, setHighlight] = useState(false); @@ -131,7 +102,9 @@ const VulnerabilitiesDataGrid = ({ const invalidIndex = -1; const selectedVulnerability = useMemo(() => { - return data?.page[urlQuery.vulnerabilityIndex]; + if (urlQuery.vulnerabilityIndex !== undefined) { + return data?.page[urlQuery.vulnerabilityIndex]; + } }, [data?.page, urlQuery.vulnerabilityIndex]); const onCloseFlyout = () => { @@ -192,7 +165,9 @@ const VulnerabilitiesDataGrid = ({ const flyoutVulnerabilityIndex = urlQuery?.vulnerabilityIndex; - const selectedVulnerabilityIndex = flyoutVulnerabilityIndex + pageIndex * pageSize; + const selectedVulnerabilityIndex = flyoutVulnerabilityIndex + ? flyoutVulnerabilityIndex + pageIndex * pageSize + : undefined; const renderCellValue = useMemo(() => { const Cell: React.FC<EuiDataGridCellValueElementProps> = ({ @@ -304,7 +279,9 @@ const VulnerabilitiesDataGrid = ({ [pageSize, setUrlQuery] ); - const showVulnerabilityFlyout = flyoutVulnerabilityIndex > invalidIndex; + const showVulnerabilityFlyout = flyoutVulnerabilityIndex + ? flyoutVulnerabilityIndex > invalidIndex + : undefined; if (data?.page.length === 0) { return <EmptyState onResetFilters={onResetFilters} />; @@ -390,8 +367,21 @@ const VulnerabilitiesDataGrid = ({ </> ); }; + const VulnerabilitiesContent = ({ dataView }: { dataView: DataView }) => { - const { pageIndex, query, sort, queryError, pageSize, setUrlQuery } = useCloudPostureTable({ + const { + sort, + query, + queryError, + pageSize, + pageIndex, + onChangeItemsPerPage, + onChangePage, + onSort, + urlQuery, + setUrlQuery, + onResetFilters, + } = useCloudPostureTable({ dataView, defaultQuery: getDefaultQuery, paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, @@ -443,8 +433,58 @@ const VulnerabilitiesContent = ({ dataView }: { dataView: DataView }) => { <EuiSpacer size="m" /> {error && <ErrorCallout error={error as Error} />} {!error && ( - <VulnerabilitiesDataGrid dataView={dataView} data={data} isFetching={isFetching} /> + <VulnerabilitiesDataGrid + dataView={dataView} + data={data} + isFetching={isFetching} + pageIndex={pageIndex} + sort={sort} + pageSize={pageSize} + onChangeItemsPerPage={onChangeItemsPerPage} + onChangePage={onChangePage} + onSort={onSort} + urlQuery={urlQuery} + onResetFilters={onResetFilters} + setUrlQuery={setUrlQuery} + /> )} </> ); }; + +export const Vulnerabilities = () => { + const { data, isLoading, error } = useFilteredDataView(LATEST_VULNERABILITIES_INDEX_PATTERN); + const getSetupStatus = useCspSetupStatusApi(); + + if (getSetupStatus?.data?.vuln_mgmt?.status !== 'indexed') return <NoVulnerabilitiesStates />; + + if (error) { + return <ErrorCallout error={error as Error} />; + } + if (isLoading) { + return defaultLoadingRenderer(); + } + + if (!data) { + return defaultNoDataRenderer(); + } + + return ( + <Routes> + <Route + exact + path={findingsNavigation.resource_vulnerabilities.path} + render={() => <ResourceVulnerabilities dataView={data} />} + /> + <Route + exact + path={findingsNavigation.vulnerabilities_by_resource.path} + render={() => <VulnerabilitiesByResource dataView={data} />} + /> + <Route + path={findingsNavigation.vulnerabilities.path} + render={() => <VulnerabilitiesContent dataView={data} />} + /> + </Routes> + ); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/resource_vulnerabilities/resource_vulnerabilities.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/resource_vulnerabilities/resource_vulnerabilities.tsx index 2f1389015e907..673dd2e8130e4 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/resource_vulnerabilities/resource_vulnerabilities.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/resource_vulnerabilities/resource_vulnerabilities.tsx @@ -21,7 +21,10 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { Link, useParams, generatePath } from 'react-router-dom'; import type { BoolQuery } from '@kbn/es-query'; import { LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY } from '../../../../common/constants'; -import { useCloudPostureTable } from '../../../../common/hooks/use_cloud_posture_table'; +import { + CloudPostureTableResult, + useCloudPostureTable, +} from '../../../../common/hooks/use_cloud_posture_table'; import { useLatestVulnerabilities } from '../../hooks/use_latest_vulnerabilities'; import type { VulnerabilitiesQueryData } from '../../types'; import { ErrorCallout } from '../../../configurations/layout/error_callout'; @@ -68,26 +71,31 @@ const ResourceVulnerabilitiesDataGrid = ({ dataView, data, isFetching, + pageIndex, + sort, + pageSize, + onChangeItemsPerPage, + onChangePage, + onSort, + urlQuery, + setUrlQuery, + onResetFilters, }: { dataView: DataView; data: VulnerabilitiesQueryData; isFetching: boolean; -}) => { - const { - pageIndex, - sort, - pageSize, - onChangeItemsPerPage, - onChangePage, - onSort, - urlQuery, - setUrlQuery, - onResetFilters, - } = useCloudPostureTable({ - dataView, - defaultQuery: getDefaultQuery, - paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, - }); +} & Pick< + CloudPostureTableResult, + | 'pageIndex' + | 'sort' + | 'pageSize' + | 'onChangeItemsPerPage' + | 'onChangePage' + | 'onSort' + | 'urlQuery' + | 'setUrlQuery' + | 'onResetFilters' +>) => { const { euiTheme } = useEuiTheme(); const styles = useStyles(); @@ -355,7 +363,19 @@ export const ResourceVulnerabilities = ({ dataView }: { dataView: DataView }) => const params = useParams<{ resourceId: string }>(); const resourceId = decodeURIComponent(params.resourceId); - const { pageIndex, query, sort, queryError, pageSize, setUrlQuery } = useCloudPostureTable({ + const { + pageIndex, + pageSize, + onChangeItemsPerPage, + onChangePage, + query, + sort, + onSort, + queryError, + urlQuery, + setUrlQuery, + onResetFilters, + } = useCloudPostureTable({ dataView, defaultQuery: getDefaultQuery, paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, @@ -457,7 +477,20 @@ export const ResourceVulnerabilities = ({ dataView }: { dataView: DataView }) => <EuiSpacer size="m" /> {error && <ErrorCallout error={error as Error} />} {!error && ( - <ResourceVulnerabilitiesDataGrid dataView={dataView} data={data} isFetching={isFetching} /> + <ResourceVulnerabilitiesDataGrid + dataView={dataView} + data={data} + isFetching={isFetching} + pageIndex={pageIndex} + pageSize={pageSize} + urlQuery={urlQuery} + setUrlQuery={setUrlQuery} + onChangeItemsPerPage={onChangeItemsPerPage} + onChangePage={onChangePage} + onResetFilters={onResetFilters} + onSort={onSort} + sort={sort} + /> )} </> ); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/vulnerabilities_by_resource.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/vulnerabilities_by_resource.tsx index caa5cca3a3ac1..89488bf52046b 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/vulnerabilities_by_resource.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/vulnerabilities_by_resource.tsx @@ -19,7 +19,10 @@ import { i18n } from '@kbn/i18n'; import { Link, generatePath } from 'react-router-dom'; import { LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY } from '../../../common/constants'; import { findingsNavigation } from '../../../common/navigation/constants'; -import { useCloudPostureTable } from '../../../common/hooks/use_cloud_posture_table'; +import { + CloudPostureTableResult, + useCloudPostureTable, +} from '../../../common/hooks/use_cloud_posture_table'; import { ErrorCallout } from '../../configurations/layout/error_callout'; import { FindingsSearchBar } from '../../configurations/layout/findings_search_bar'; import { useLimitProperties } from '../../../common/utils/get_limit_properties'; @@ -54,26 +57,31 @@ const VulnerabilitiesByResourceDataGrid = ({ dataView, data, isFetching, + pageIndex, + sort, + pageSize, + onChangeItemsPerPage, + onChangePage, + onSort, + urlQuery, + setUrlQuery, + onResetFilters, }: { dataView: DataView; data: VulnerabilitiesByResourceQueryData | undefined; isFetching: boolean; -}) => { - const { - pageIndex, - sort, - pageSize, - onChangeItemsPerPage, - onChangePage, - onSort, - urlQuery, - setUrlQuery, - onResetFilters, - } = useCloudPostureTable({ - dataView, - defaultQuery: getDefaultQuery, - paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, - }); +} & Pick< + CloudPostureTableResult, + | 'pageIndex' + | 'sort' + | 'pageSize' + | 'onChangeItemsPerPage' + | 'onChangePage' + | 'onSort' + | 'urlQuery' + | 'setUrlQuery' + | 'onResetFilters' +>) => { const styles = useStyles(); const { isLastLimitedPage, limitedTotalItemCount } = useLimitProperties({ @@ -232,7 +240,19 @@ const VulnerabilitiesByResourceDataGrid = ({ }; export const VulnerabilitiesByResource = ({ dataView }: { dataView: DataView }) => { - const { pageIndex, query, sort, queryError, pageSize, setUrlQuery } = useCloudPostureTable({ + const { + pageIndex, + onChangeItemsPerPage, + onChangePage, + pageSize, + query, + sort, + onSort, + queryError, + urlQuery, + setUrlQuery, + onResetFilters, + } = useCloudPostureTable({ dataView, defaultQuery: getDefaultQuery, paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, @@ -273,6 +293,15 @@ export const VulnerabilitiesByResource = ({ dataView }: { dataView: DataView }) dataView={dataView} data={data} isFetching={isFetching} + pageIndex={pageIndex} + sort={sort} + pageSize={pageSize} + onChangeItemsPerPage={onChangeItemsPerPage} + onChangePage={onChangePage} + onSort={onSort} + urlQuery={urlQuery} + setUrlQuery={setUrlQuery} + onResetFilters={onResetFilters} /> )} </> From f9eda80352de795bab38d62dae7c1d647e8b89e6 Mon Sep 17 00:00:00 2001 From: "Joey F. Poon" <joey.poon@elastic.co> Date: Mon, 28 Aug 2023 08:40:14 -0700 Subject: [PATCH 20/49] [Security Solution] bypass usage-api cert check for serverless security (#164773) --- .../server/common/services/usage_reporting_service.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x-pack/plugins/security_solution_serverless/server/common/services/usage_reporting_service.ts b/x-pack/plugins/security_solution_serverless/server/common/services/usage_reporting_service.ts index aae47c8de9f24..4f5daeae034b9 100644 --- a/x-pack/plugins/security_solution_serverless/server/common/services/usage_reporting_service.ts +++ b/x-pack/plugins/security_solution_serverless/server/common/services/usage_reporting_service.ts @@ -7,16 +7,20 @@ import type { Response } from 'node-fetch'; import fetch from 'node-fetch'; +import https from 'https'; import { USAGE_SERVICE_USAGE_URL } from '../../constants'; import type { UsageRecord } from '../../types'; +// TODO remove once we have the CA available +const agent = new https.Agent({ rejectUnauthorized: false }); export class UsageReportingService { public async reportUsage(records: UsageRecord[]): Promise<Response> { return fetch(USAGE_SERVICE_USAGE_URL, { method: 'post', body: JSON.stringify(records), headers: { 'Content-Type': 'application/json' }, + agent, }); } } From c920180c10c69210f694015278d1a2c7cdbb3be6 Mon Sep 17 00:00:00 2001 From: Rodney Norris <rodney.norris@elastic.co> Date: Mon, 28 Aug 2023 10:59:14 -0500 Subject: [PATCH 21/49] [Enterprise Search] type clean-up (#164891) ## Summary Updated the search-api-panels docLinks types to not use `any` Fixed prop in serverless search, I _think_ this was a merge conflict between PRs --- packages/kbn-search-api-panels/components/ingest_data.tsx | 7 ++++++- .../components/integrations_panel.tsx | 2 +- .../public/application/components/overview.tsx | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/kbn-search-api-panels/components/ingest_data.tsx b/packages/kbn-search-api-panels/components/ingest_data.tsx index 5e1c8e7bc01dd..11f42fb6e7833 100644 --- a/packages/kbn-search-api-panels/components/ingest_data.tsx +++ b/packages/kbn-search-api-panels/components/ingest_data.tsx @@ -21,7 +21,12 @@ interface IngestDataProps { codeSnippet: string; selectedLanguage: LanguageDefinition; setSelectedLanguage: (language: LanguageDefinition) => void; - docLinks: any; + docLinks: { + beats: string; + connectors: string; + integrations: string; + logStash: string; + }; assetBasePath: string; application?: ApplicationStart; sharePlugin: SharePluginStart; diff --git a/packages/kbn-search-api-panels/components/integrations_panel.tsx b/packages/kbn-search-api-panels/components/integrations_panel.tsx index 4f5313dd93579..6d8e2e70526e1 100644 --- a/packages/kbn-search-api-panels/components/integrations_panel.tsx +++ b/packages/kbn-search-api-panels/components/integrations_panel.tsx @@ -24,7 +24,7 @@ import { LEARN_MORE_LABEL } from '../constants'; import { GithubLink } from './github_link'; export interface IntegrationsPanelProps { - docLinks: any; + docLinks: { beats: string; connectors: string; logStash: string }; assetBasePath: string; } diff --git a/x-pack/plugins/serverless_search/public/application/components/overview.tsx b/x-pack/plugins/serverless_search/public/application/components/overview.tsx index 3d7783ee9a50a..e8ef03a72a1f0 100644 --- a/x-pack/plugins/serverless_search/public/application/components/overview.tsx +++ b/x-pack/plugins/serverless_search/public/application/components/overview.tsx @@ -203,7 +203,7 @@ export const ElasticsearchOverview = () => { 'ingestData', codeSnippetArguments )} - showTryInConsole={getConsoleRequest('ingestData')} + consoleRequest={getConsoleRequest('ingestData')} languages={languageDefinitions} selectedLanguage={selectedLanguage} setSelectedLanguage={setSelectedLanguage} From 8ddb76274621f9d9342c27f8c2e1814e2d70b13d Mon Sep 17 00:00:00 2001 From: Alex Szabo <alex.szabo@elastic.co> Date: Mon, 28 Aug 2023 18:28:36 +0200 Subject: [PATCH 22/49] [Ops] Improve serverless_ftr.sh result output (#164966) ## Summary The FTR serverless pipeline's output can be confusing, because in case any of the configs fail, the error log is always attached to the last collapsing block (thus making devs think it was the last block that was erroneous). This PR adds an output message after the configs are ran, and separates the log from the last run's logs. - chore: Add result logging for serverless_ftr.sh with a new collapsing block to avoid confusion Was: <img width="1086" alt="Screenshot 2023-08-28 at 16 08 43" src="https://github.com/elastic/kibana/assets/4738868/46721879-8add-49a2-8448-b9ed40ac8bc0"> Would be: <img width="1079" alt="Screenshot 2023-08-28 at 16 08 20" src="https://github.com/elastic/kibana/assets/4738868/3eaf7f2b-7fc8-4777-81e3-1c21ec57faaa"> --- .buildkite/scripts/steps/functional/serverless_ftr.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.buildkite/scripts/steps/functional/serverless_ftr.sh b/.buildkite/scripts/steps/functional/serverless_ftr.sh index ba75fe6034cae..72a69897e54e3 100755 --- a/.buildkite/scripts/steps/functional/serverless_ftr.sh +++ b/.buildkite/scripts/steps/functional/serverless_ftr.sh @@ -28,6 +28,7 @@ elif [[ "$SERVERLESS_ENVIRONMENT" == "security" ]]; then fi EXIT_CODE=0 +OFFENDING_CONFIG= for CONFIG in "${SERVERLESS_CONFIGS[@]}" do @@ -42,7 +43,17 @@ do if [ $LAST_CODE -ne 0 ]; then EXIT_CODE=10 + OFFENDING_CONFIG=$CONFIG fi done +echo "--- Serverless FTR Results for $JOB" +if [ $EXIT_CODE -eq 0 ]; then + echo "✅ Success!" +elif [ $EXIT_CODE -eq 10 ]; then + echo "❌ Failed in config: $OFFENDING_CONFIG, exit code set to 10 for soft-failure" +else + echo "❌ Failed." +fi + exit $EXIT_CODE From 31e95574ae6d8cfa9e0ba4595e1068e9391b423d Mon Sep 17 00:00:00 2001 From: Yara Tercero <yctercero@users.noreply.github.com> Date: Mon, 28 Aug 2023 09:29:00 -0700 Subject: [PATCH 23/49] [Rule Details] - Update rule details data view id text (#164494) **Resolves: https://github.com/elastic/kibana/issues/164828** **Related UX writing issue: https://github.com/elastic/ux-writing/issues/46** ## Summary In rule details page, when a rule has a data view selected, two labels show up as "Data View". This appears to be a bug, as one of those labels should be "Data view ID" and another should be "Data view index pattern". Thanks to @MadameSheema @nikitaindik for finding this. ### Before ![image](https://github.com/elastic/kibana/assets/10927944/8ac8b6d4-1005-4c03-a71a-31216a1287c5) ### After <img width="808" alt="Screenshot 2023-08-26 at 19 30 54" src="https://github.com/elastic/kibana/assets/15949146/b511bf92-0e90-4455-834c-36b8e75b2a58"> ### Checklist - [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) --------- Co-authored-by: Nikita Indik <nikita.indik@elastic.co> --- .../rule_details/rule_definition_section.tsx | 50 ++++++++++++++++--- .../components/rule_details/translations.ts | 20 ++++++-- .../rules/step_define_rule/schema.tsx | 21 ++++---- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - .../cypress/screens/rule_details.ts | 2 +- 7 files changed, 72 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx index 8957ebe1ff9d5..de9e257c798bc 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx @@ -42,6 +42,7 @@ import { DataSourceType } from '../../../../detections/pages/detection_engine/ru import { convertHistoryStartToSize } from '../../../../detections/pages/detection_engine/rules/helpers'; import { MlJobLink } from '../../../../detections/components/rules/ml_job_link/ml_job_link'; import { useSecurityJobs } from '../../../../common/components/ml_popover/hooks/use_security_jobs'; +import { useKibana } from '../../../../common/lib/kibana/kibana_react'; import { BadgeList } from './badge_list'; import * as i18n from './translations'; @@ -107,11 +108,42 @@ interface IndexProps { const Index = ({ index }: IndexProps) => <BadgeList badges={index} />; -interface DataViewProps { +interface DataViewIdProps { dataViewId: string; } -const DataView = ({ dataViewId }: DataViewProps) => <EuiText size="s">{dataViewId}</EuiText>; +const DataViewId = ({ dataViewId }: DataViewIdProps) => <EuiText size="s">{dataViewId}</EuiText>; + +interface DataViewIndexPatternProps { + dataViewId: string; +} + +const DataViewIndexPattern = ({ dataViewId }: DataViewIndexPatternProps) => { + const { data } = useKibana().services; + const [indexPattern, setIndexPattern] = React.useState(''); + const [hasError, setHasError] = React.useState(false); + + React.useEffect(() => { + data.dataViews + .get(dataViewId) + .then((dataView) => { + setIndexPattern(dataView.getIndexPattern()); + }) + .catch(() => { + setHasError(true); + }); + }, [data, dataViewId]); + + if (hasError) { + return <EuiText size="s">{i18n.DATA_VIEW_INDEX_PATTERN_FETCH_ERROR_MESSAGE}</EuiText>; + } + + if (!indexPattern) { + return <EuiLoadingSpinner size="m" />; + } + + return <EuiText size="s">{indexPattern}</EuiText>; +}; interface ThresholdProps { threshold: ThresholdType; @@ -299,10 +331,16 @@ const prepareDefinitionSectionListItems = ( } if ('data_view_id' in rule && rule.data_view_id) { - definitionSectionListItems.push({ - title: i18n.DATA_VIEW_FIELD_LABEL, - description: <DataView dataViewId={rule.data_view_id} />, - }); + definitionSectionListItems.push( + { + title: i18n.DATA_VIEW_ID_FIELD_LABEL, + description: <DataViewId dataViewId={rule.data_view_id} />, + }, + { + title: i18n.DATA_VIEW_INDEX_PATTERN_FIELD_LABEL, + description: <DataViewIndexPattern dataViewId={rule.data_view_id} />, + } + ); } if (savedQuery) { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.ts index 55b0edc254d73..8e795b9477045 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.ts @@ -182,10 +182,24 @@ export const INDEX_FIELD_LABEL = i18n.translate( } ); -export const DATA_VIEW_FIELD_LABEL = i18n.translate( - 'xpack.securitySolution.detectionEngine.ruleDetails.dataViewFieldLabel', +export const DATA_VIEW_ID_FIELD_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.dataViewIdFieldLabel', { - defaultMessage: 'Data View', + defaultMessage: 'Data view', + } +); + +export const DATA_VIEW_INDEX_PATTERN_FIELD_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.dataViewIndexPatternFieldLabel', + { + defaultMessage: 'Data view index pattern', + } +); + +export const DATA_VIEW_INDEX_PATTERN_FETCH_ERROR_MESSAGE = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.dataViewIndexPatternFetchErrorMessage', + { + defaultMessage: 'Could not load data view index pattern', } ); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/schema.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/schema.tsx index d996ee4e49592..1f90b75413672 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/schema.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/schema.tsx @@ -78,21 +78,11 @@ export const schema: FormSchema<DefineStepRule> = { }, ], }, - dataViewTitle: { - label: i18n.translate( - 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.dataViewSelector', - { - defaultMessage: 'Data View', - } - ), - validations: [], - }, - // TODO: populate the dataViewTitle in a better way dataViewId: { label: i18n.translate( 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.dataViewSelector', { - defaultMessage: 'Data View', + defaultMessage: 'Data view', } ), fieldsToValidateOnChange: ['dataViewId'], @@ -128,6 +118,15 @@ export const schema: FormSchema<DefineStepRule> = { }, ], }, + dataViewTitle: { + label: i18n.translate( + 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.dataViewTitleSelector', + { + defaultMessage: 'Data view index pattern', + } + ), + validations: [], + }, eqlOptions: {}, queryBar: { validations: [ diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index bfff9d80f7f39..e044d622d0151 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -31003,7 +31003,6 @@ "xpack.securitySolution.detectionEngine.createRule.savedQueryFiltersLabel": "Filtres de requête enregistrés", "xpack.securitySolution.detectionEngine.createRule.savedQueryLabel": "Requête enregistrée", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.authorFieldEmptyError": "L'auteur doit être renseigné", - "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.dataViewSelector": "Vue de données", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.descriptionFieldRequiredError": "Une description est requise.", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fiedIndexPatternsLabel": "Modèles d'indexation", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldAssociatedToEndpointListLabel": "Ajouter des exceptions de point de terminaison existantes à la règle", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 443e6725a422a..ad0939f714278 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -31002,7 +31002,6 @@ "xpack.securitySolution.detectionEngine.createRule.savedQueryFiltersLabel": "保存されたクエリフィルター", "xpack.securitySolution.detectionEngine.createRule.savedQueryLabel": "保存されたクエリ", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.authorFieldEmptyError": "作成者は空にする必要があります", - "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.dataViewSelector": "データビュー", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.descriptionFieldRequiredError": "説明が必要です。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fiedIndexPatternsLabel": "インデックスパターン", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldAssociatedToEndpointListLabel": "既存のエンドポイント例外をルールに追加", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index f4f6bf13a8f28..228d7990cf6a0 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -30998,7 +30998,6 @@ "xpack.securitySolution.detectionEngine.createRule.savedQueryFiltersLabel": "已保存查询筛选", "xpack.securitySolution.detectionEngine.createRule.savedQueryLabel": "已保存查询", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.authorFieldEmptyError": "作者不得为空", - "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.dataViewSelector": "数据视图", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.descriptionFieldRequiredError": "描述必填。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fiedIndexPatternsLabel": "索引模式", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldAssociatedToEndpointListLabel": "将现有的终端例外添加到规则", diff --git a/x-pack/test/security_solution_cypress/cypress/screens/rule_details.ts b/x-pack/test/security_solution_cypress/cypress/screens/rule_details.ts index 97149957448b6..db13c164b3778 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/rule_details.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/rule_details.ts @@ -29,7 +29,7 @@ export const SAVED_QUERY_DETAILS = /^Saved query$/; export const SAVED_QUERY_FILTERS_DETAILS = 'Saved query filters'; -export const DATA_VIEW_DETAILS = 'Data View'; +export const DATA_VIEW_DETAILS = 'Data view'; export const DEFINITION_DETAILS = '[data-test-subj=definitionRule] [data-test-subj="listItemColumnStepRuleDescription"]'; From 3935548f36cc7853a543ca5966f2b343427e5bdf Mon Sep 17 00:00:00 2001 From: Andrew Macri <andrew.macri@elastic.co> Date: Mon, 28 Aug 2023 10:30:05 -0600 Subject: [PATCH 24/49] [Security Solution] [Elastic AI Assistant] LangChain integration (experimental) (#164908) ## [Security Solution] [Elastic AI Assistant] LangChain integration (experimental) This PR integrates [LangChain](https://www.langchain.com/) with the [Elastic AI Assistant](https://www.elastic.co/blog/introducing-elastic-ai-assistant) as an experimental, alternative execution path. ### How it works - There are virtually no client side changes to the assistant, apart from a new branch in `x-pack/packages/kbn-elastic-assistant/impl/assistant/api.tsx` that chooses a path based on the value of the `assistantLangChain` flag: ```typescript const path = assistantLangChain ? `/internal/elastic_assistant/actions/connector/${apiConfig?.connectorId}/_execute` : `/api/actions/connector/${apiConfig?.connectorId}/_execute`; ``` Execution of the LangChain chain happens server-side. The new route still executes the request via the `connectorId` in the route, but the connector won't execute the request exactly as it was sent by the client. Instead, the connector will execute one (or more) prompts that are generated by LangChain. Requests routed to `/internal/elastic_assistant/actions/connector/${apiConfig?.connectorId}/_execute` will be processed by a new Kibana plugin located in: ``` x-pack/plugins/elastic_assistant ``` - Requests are processed in the `postActionsConnectorExecuteRoute` handler in `x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.ts`. The `postActionsConnectorExecuteRoute` route handler: 1. Extracts the chat messages sent by the assistant 2. Converts the extracted messages to the format expected by LangChain 3. Passes the converted messages to `executeCustomLlmChain` - The `executeCustomLlmChain` function in `x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.ts`: 1. Splits the messages into `pastMessages` and `latestMessage`, where the latter contains only the last message sent by the user 2. Wraps the conversation history in the `BufferMemory` LangChain abstraction 3. Executes the chain, kicking it off with `latestMessage` ```typescript const llm = new ActionsClientLlm({ actions, connectorId, request }); const pastMessages = langchainMessages.slice(0, -1); // all but the last message const latestMessage = langchainMessages.slice(-1); // the last message const memory = new BufferMemory({ chatHistory: new ChatMessageHistory(pastMessages), }); const chain = new ConversationChain({ llm, memory }); await chain.call({ input: latestMessage[0].content }); // kick off the chain with the last message }; ``` - When LangChain executes the chain, it will invoke `ActionsClientLlm`'s `_call` function in `x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.ts` one or more times. The `_call` function's signature is defined by LangChain: ``` async _call(prompt: string): Promise<string> ``` - The contents of `prompt` are completely determined by LangChain. - The string returned by the promise is the "answer" from the LLM The `ActionsClientLlm` extends LangChain's LLM interface: ```typescript export class ActionsClientLlm extends LLM ``` This let's us do additional "work" in the `_call` function: 1. Create a new assistant message using the contents of the `prompt` (`string`) argument to `_call` 2. Create a request body in the format expected by the connector 3. Create an actions client from the authenticated request context 4. Execute the actions client with the request body 5. Save the raw response from the connector, because that's what the assistant expects 6. Return the result as a plain string, as per the contact of `_call` ## Desk testing This experimental LangChain integration may NOT be enabled via a feature flag (yet). Set ```typescript assistantLangChain={true} ``` in `x-pack/plugins/security_solution/public/app/app.tsx` to enable this experimental feature in development environments. --- .eslintrc.js | 5 + .github/CODEOWNERS | 1 + docs/developer/plugin-list.asciidoc | 4 + package.json | 3 + packages/kbn-test/jest-preset.js | 4 +- .../jest_integration_node/jest-preset.js | 7 + .../kbn-test/src/jest/setup/setup_test.js | 1 + tsconfig.base.json | 5 +- .../impl/assistant/api.test.tsx | 129 +++++++++ .../impl/assistant/api.tsx | 25 +- .../assistant/use_send_messages/index.tsx | 31 ++- .../impl/assistant_context/index.test.tsx | 1 + .../impl/assistant_context/index.tsx | 5 + .../mock/test_providers/test_providers.tsx | 1 + .../mock/test_providers/test_providers.tsx | 1 + x-pack/plugins/elastic_assistant/README.md | 9 + .../elastic_assistant/common/constants.ts | 13 + .../plugins/elastic_assistant/jest.config.js | 17 ++ x-pack/plugins/elastic_assistant/kibana.jsonc | 15 + .../server/__mocks__/action_result_data.ts | 36 +++ .../server/__mocks__/lang_chain_messages.ts | 20 ++ .../server/__mocks__/request.ts | 11 + .../server/__mocks__/request_context.ts | 56 ++++ .../server/__mocks__/response.ts | 12 + .../server/__mocks__/server.ts | 95 +++++++ .../server/__mocks__/test_adapters.ts | 64 +++++ .../plugins/elastic_assistant/server/index.ts | 18 ++ .../server/lib/build_response/index.ts | 68 +++++ .../execute_custom_llm_chain/index.test.ts | 105 +++++++ .../execute_custom_llm_chain/index.ts | 51 ++++ .../server/lib/langchain/helpers.test.ts | 185 +++++++++++++ .../server/lib/langchain/helpers.ts | 57 ++++ .../langchain/llm/actions_client_llm.test.ts | 172 ++++++++++++ .../lib/langchain/llm/actions_client_llm.ts | 99 +++++++ .../elastic_assistant/server/plugin.ts | 80 ++++++ .../elastic_assistant/server/routes/index.ts | 8 + .../post_actions_connector_execute.test.ts | 113 ++++++++ .../routes/post_actions_connector_execute.ts | 72 +++++ .../server/schemas/common.ts | 38 +++ .../schemas/post_actions_connector_execute.ts | 27 ++ .../plugins/elastic_assistant/server/types.ts | 40 +++ .../plugins/elastic_assistant/tsconfig.json | 27 ++ x-pack/plugins/security_solution/kibana.jsonc | 1 + .../security_solution/public/app/app.tsx | 1 + .../common/mock/mock_assistant_provider.tsx | 1 + yarn.lock | 256 +++++++++++++++++- 46 files changed, 1954 insertions(+), 36 deletions(-) create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/api.test.tsx create mode 100755 x-pack/plugins/elastic_assistant/README.md create mode 100755 x-pack/plugins/elastic_assistant/common/constants.ts create mode 100644 x-pack/plugins/elastic_assistant/jest.config.js create mode 100644 x-pack/plugins/elastic_assistant/kibana.jsonc create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/action_result_data.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/lang_chain_messages.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/request.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/request_context.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/response.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/server.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/test_adapters.ts create mode 100755 x-pack/plugins/elastic_assistant/server/index.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/build_response/index.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.ts create mode 100755 x-pack/plugins/elastic_assistant/server/plugin.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/index.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.ts create mode 100644 x-pack/plugins/elastic_assistant/server/schemas/common.ts create mode 100644 x-pack/plugins/elastic_assistant/server/schemas/post_actions_connector_execute.ts create mode 100755 x-pack/plugins/elastic_assistant/server/types.ts create mode 100644 x-pack/plugins/elastic_assistant/tsconfig.json diff --git a/.eslintrc.js b/.eslintrc.js index ddd39ed00747a..e1153546e8154 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -984,6 +984,7 @@ module.exports = { // front end and common typescript and javascript files only files: [ 'x-pack/plugins/ecs_data_quality_dashboard/common/**/*.{js,mjs,ts,tsx}', + 'x-pack/plugins/elastic_assistant/common/**/*.{js,mjs,ts,tsx}', 'x-pack/packages/kbn-elastic-assistant/**/*.{js,mjs,ts,tsx}', 'x-pack/packages/security-solution/**/*.{js,mjs,ts,tsx}', 'x-pack/plugins/security_solution/public/**/*.{js,mjs,ts,tsx}', @@ -1016,6 +1017,7 @@ module.exports = { // This should be a very small set as most linter rules are useful for tests as well. files: [ 'x-pack/plugins/ecs_data_quality_dashboard/**/*.{ts,tsx}', + 'x-pack/plugins/elastic_assistant/**/*.{ts,tsx}', 'x-pack/packages/kbn-elastic-assistant/**/*.{ts,tsx}', 'x-pack/packages/security-solution/**/*.{ts,tsx}', 'x-pack/plugins/security_solution/**/*.{ts,tsx}', @@ -1026,6 +1028,7 @@ module.exports = { ], excludedFiles: [ 'x-pack/plugins/ecs_data_quality_dashboard/**/*.{test,mock,test_helper}.{ts,tsx}', + 'x-pack/plugins/elastic_assistant/**/*.{test,mock,test_helper}.{ts,tsx}', 'x-pack/packages/kbn-elastic-assistant/**/*.{test,mock,test_helper}.{ts,tsx}', 'x-pack/packages/security-solution/**/*.{test,mock,test_helper}.{ts,tsx}', 'x-pack/plugins/security_solution/**/*.{test,mock,test_helper}.{ts,tsx}', @@ -1042,6 +1045,7 @@ module.exports = { // typescript only for front and back end files: [ 'x-pack/plugins/ecs_data_quality_dashboard/**/*.{ts,tsx}', + 'x-pack/plugins/elastic_assistant/**/*.{ts,tsx}', 'x-pack/packages/kbn-elastic-assistant/**/*.{ts,tsx}', 'x-pack/packages/security-solution/**/*.{ts,tsx}', 'x-pack/plugins/security_solution/**/*.{ts,tsx}', @@ -1077,6 +1081,7 @@ module.exports = { // typescript and javascript for front and back end files: [ 'x-pack/plugins/ecs_data_quality_dashboard/**/*.{js,mjs,ts,tsx}', + 'x-pack/plugins/elastic_assistant/**/*.{js,mjs,ts,tsx}', 'x-pack/packages/kbn-elastic-assistant/**/*.{js,mjs,ts,tsx}', 'x-pack/packages/security-solution/**/*.{js,mjs,ts,tsx}', 'x-pack/plugins/security_solution/**/*.{js,mjs,ts,tsx}', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6189270654c7b..f23d2df2fb092 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -340,6 +340,7 @@ packages/kbn-ecs @elastic/kibana-core @elastic/security-threat-hunting-investiga x-pack/packages/security-solution/ecs_data_quality_dashboard @elastic/security-threat-hunting-investigations x-pack/plugins/ecs_data_quality_dashboard @elastic/security-threat-hunting-investigations x-pack/packages/kbn-elastic-assistant @elastic/security-solution +x-pack/plugins/elastic_assistant @elastic/security-solution test/plugin_functional/plugins/elasticsearch_client_plugin @elastic/kibana-core x-pack/test/plugin_api_integration/plugins/elasticsearch_client @elastic/kibana-core x-pack/plugins/embeddable_enhanced @elastic/kibana-presentation diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 41aecaccf554c..632bce5883c28 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -528,6 +528,10 @@ Plugin server-side only. Plugin has three main functions: |This plugin implements (server) APIs used to render the content of the Data Quality dashboard. +|{kib-repo}blob/{branch}/x-pack/plugins/elastic_assistant/README.md[elasticAssistant] +|This plugin implements (only) server APIs for the Elastic AI Assistant. + + |<<enhanced-embeddables-plugin>> |Enhances Embeddables by registering a custom factory provider. The enhanced factory provider adds dynamic actions to every embeddables state, in order to support drilldowns. diff --git a/package.json b/package.json index 657329a4bb6a8..fc076f17b7407 100644 --- a/package.json +++ b/package.json @@ -383,6 +383,7 @@ "@kbn/ecs-data-quality-dashboard": "link:x-pack/packages/security-solution/ecs_data_quality_dashboard", "@kbn/ecs-data-quality-dashboard-plugin": "link:x-pack/plugins/ecs_data_quality_dashboard", "@kbn/elastic-assistant": "link:x-pack/packages/kbn-elastic-assistant", + "@kbn/elastic-assistant-plugin": "link:x-pack/plugins/elastic_assistant", "@kbn/elasticsearch-client-plugin": "link:test/plugin_functional/plugins/elasticsearch_client_plugin", "@kbn/elasticsearch-client-xpack-plugin": "link:x-pack/test/plugin_api_integration/plugins/elasticsearch_client", "@kbn/embeddable-enhanced-plugin": "link:x-pack/plugins/embeddable_enhanced", @@ -897,6 +898,7 @@ "jsonwebtoken": "^9.0.0", "jsts": "^1.6.2", "kea": "^2.4.2", + "langchain": "^0.0.132", "launchdarkly-js-client-sdk": "^2.22.1", "launchdarkly-node-server-sdk": "^6.4.2", "load-json-file": "^6.2.0", @@ -1559,6 +1561,7 @@ "val-loader": "^1.1.1", "vinyl-fs": "^4.0.0", "watchpack": "^1.6.0", + "web-streams-polyfill": "^3.2.1", "webpack": "^4.41.5", "webpack-bundle-analyzer": "^4.5.0", "webpack-cli": "^4.10.0", diff --git a/packages/kbn-test/jest-preset.js b/packages/kbn-test/jest-preset.js index f80a5e103c16f..bbe3cb2923280 100644 --- a/packages/kbn-test/jest-preset.js +++ b/packages/kbn-test/jest-preset.js @@ -105,8 +105,10 @@ module.exports = { transformIgnorePatterns: [ // ignore all node_modules except monaco-editor and react-monaco-editor which requires babel transforms to handle dynamic import() // since ESM modules are not natively supported in Jest yet (https://github.com/facebook/jest/issues/4842) - '[/\\\\]node_modules(?![\\/\\\\](byte-size|monaco-editor|monaco-yaml|vscode-languageserver-types|react-monaco-editor|d3-interpolate|d3-color))[/\\\\].+\\.js$', + '[/\\\\]node_modules(?![\\/\\\\](byte-size|monaco-editor|monaco-yaml|vscode-languageserver-types|react-monaco-editor|d3-interpolate|d3-color|langchain|langsmith))[/\\\\].+\\.js$', 'packages/kbn-pm/dist/index.js', + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))/dist/[/\\\\].+\\.js$', + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))/dist/util/[/\\\\].+\\.js$', ], // An array of regexp pattern strings that are matched against all source file paths, matched files to include/exclude for code coverage diff --git a/packages/kbn-test/jest_integration_node/jest-preset.js b/packages/kbn-test/jest_integration_node/jest-preset.js index 43373e41db5c1..92b8aedb5ee88 100644 --- a/packages/kbn-test/jest_integration_node/jest-preset.js +++ b/packages/kbn-test/jest_integration_node/jest-preset.js @@ -19,6 +19,13 @@ module.exports = { testPathIgnorePatterns: preset.testPathIgnorePatterns.filter( (pattern) => !pattern.includes('integration_tests') ), + // An array of regexp pattern strings that are matched against, matched files will skip transformation: + transformIgnorePatterns: [ + // since ESM modules are not natively supported in Jest yet (https://github.com/facebook/jest/issues/4842) + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))[/\\\\].+\\.js$', + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))/dist/[/\\\\].+\\.js$', + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))/dist/util/[/\\\\].+\\.js$', + ], setupFilesAfterEnv: [ '<rootDir>/packages/kbn-test/src/jest/setup/after_env.integration.js', '<rootDir>/packages/kbn-test/src/jest/setup/mocks.moment_timezone.js', diff --git a/packages/kbn-test/src/jest/setup/setup_test.js b/packages/kbn-test/src/jest/setup/setup_test.js index b0038daf196c9..ee386f894a71e 100644 --- a/packages/kbn-test/src/jest/setup/setup_test.js +++ b/packages/kbn-test/src/jest/setup/setup_test.js @@ -13,6 +13,7 @@ import 'jest-styled-components'; import '@testing-library/jest-dom'; +import 'web-streams-polyfill/es6'; // ReadableStream polyfill /** * Removed in Jest 27/jsdom, used in some transitive dependencies diff --git a/tsconfig.base.json b/tsconfig.base.json index 2efdd91c53d3b..a347a249b68ca 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -674,6 +674,8 @@ "@kbn/ecs-data-quality-dashboard-plugin/*": ["x-pack/plugins/ecs_data_quality_dashboard/*"], "@kbn/elastic-assistant": ["x-pack/packages/kbn-elastic-assistant"], "@kbn/elastic-assistant/*": ["x-pack/packages/kbn-elastic-assistant/*"], + "@kbn/elastic-assistant-plugin": ["x-pack/plugins/elastic_assistant"], + "@kbn/elastic-assistant-plugin/*": ["x-pack/plugins/elastic_assistant/*"], "@kbn/elasticsearch-client-plugin": ["test/plugin_functional/plugins/elasticsearch_client_plugin"], "@kbn/elasticsearch-client-plugin/*": ["test/plugin_functional/plugins/elasticsearch_client_plugin/*"], "@kbn/elasticsearch-client-xpack-plugin": ["x-pack/test/plugin_api_integration/plugins/elasticsearch_client"], @@ -1645,4 +1647,5 @@ "@kbn/ambient-storybook-types" ] } -} \ No newline at end of file +} + diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.test.tsx new file mode 100644 index 0000000000000..65b8183b60a0b --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.test.tsx @@ -0,0 +1,129 @@ +/* + * 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 { HttpSetup } from '@kbn/core-http-browser'; +import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/public/common'; + +import { fetchConnectorExecuteAction, FetchConnectorExecuteAction } from './api'; +import type { Conversation, Message } from '../assistant_context/types'; +import { API_ERROR } from './translations'; + +jest.mock('@kbn/core-http-browser'); + +const mockHttp = { + fetch: jest.fn(), +} as unknown as HttpSetup; + +const apiConfig: Conversation['apiConfig'] = { + connectorId: 'foo', + model: 'gpt-4', + provider: OpenAiProviderType.OpenAi, +}; + +const messages: Message[] = [ + { content: 'This is a test', role: 'user', timestamp: new Date().toLocaleString() }, +]; + +describe('fetchConnectorExecuteAction', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('calls the internal assistant API when assistantLangChain is true', async () => { + const testProps: FetchConnectorExecuteAction = { + assistantLangChain: true, + http: mockHttp, + messages, + apiConfig, + }; + + await fetchConnectorExecuteAction(testProps); + + expect(mockHttp.fetch).toHaveBeenCalledWith( + '/internal/elastic_assistant/actions/connector/foo/_execute', + { + body: '{"params":{"subActionParams":{"body":"{\\"model\\":\\"gpt-4\\",\\"messages\\":[{\\"role\\":\\"user\\",\\"content\\":\\"This is a test\\"}],\\"n\\":1,\\"stop\\":null,\\"temperature\\":0.2}"},"subAction":"test"}}', + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + signal: undefined, + } + ); + }); + + it('calls the actions connector api when assistantLangChain is false', async () => { + const testProps: FetchConnectorExecuteAction = { + assistantLangChain: false, + http: mockHttp, + messages, + apiConfig, + }; + + await fetchConnectorExecuteAction(testProps); + + expect(mockHttp.fetch).toHaveBeenCalledWith('/api/actions/connector/foo/_execute', { + body: '{"params":{"subActionParams":{"body":"{\\"model\\":\\"gpt-4\\",\\"messages\\":[{\\"role\\":\\"user\\",\\"content\\":\\"This is a test\\"}],\\"n\\":1,\\"stop\\":null,\\"temperature\\":0.2}"},"subAction":"test"}}', + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + signal: undefined, + }); + }); + + it('returns API_ERROR when the response status is not ok', async () => { + (mockHttp.fetch as jest.Mock).mockResolvedValue({ status: 'error' }); + + const testProps: FetchConnectorExecuteAction = { + assistantLangChain: false, + http: mockHttp, + messages, + apiConfig, + }; + + const result = await fetchConnectorExecuteAction(testProps); + + expect(result).toBe(API_ERROR); + }); + + it('returns API_ERROR when there are no choices', async () => { + (mockHttp.fetch as jest.Mock).mockResolvedValue({ status: 'ok', data: {} }); + const testProps: FetchConnectorExecuteAction = { + assistantLangChain: false, + http: mockHttp, + messages, + apiConfig, + }; + + const result = await fetchConnectorExecuteAction(testProps); + + expect(result).toBe(API_ERROR); + }); + + it('return the trimmed first `choices` `message` `content` when the API call is successful', async () => { + (mockHttp.fetch as jest.Mock).mockResolvedValue({ + status: 'ok', + data: { + choices: [ + { + message: { + content: ' Test response ', // leading and trailing whitespace + }, + }, + ], + }, + }); + + const testProps: FetchConnectorExecuteAction = { + assistantLangChain: false, + http: mockHttp, + messages, + apiConfig, + }; + + const result = await fetchConnectorExecuteAction(testProps); + + expect(result).toBe('Test response'); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.tsx index 0bb68409caf91..c8624e365419d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.tsx @@ -14,6 +14,7 @@ import { API_ERROR } from './translations'; import { MODEL_GPT_3_5_TURBO } from '../connectorland/models/model_selector/model_selector'; export interface FetchConnectorExecuteAction { + assistantLangChain: boolean; apiConfig: Conversation['apiConfig']; http: HttpSetup; messages: Message[]; @@ -21,6 +22,7 @@ export interface FetchConnectorExecuteAction { } export const fetchConnectorExecuteAction = async ({ + assistantLangChain, http, messages, apiConfig, @@ -54,19 +56,20 @@ export const fetchConnectorExecuteAction = async ({ }; try { + const path = assistantLangChain + ? `/internal/elastic_assistant/actions/connector/${apiConfig?.connectorId}/_execute` + : `/api/actions/connector/${apiConfig?.connectorId}/_execute`; + // TODO: Find return type for this API // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response = await http.fetch<any>( - `/api/actions/connector/${apiConfig?.connectorId}/_execute`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(requestBody), - signal, - } - ); + const response = await http.fetch<any>(path, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestBody), + signal, + }); const data = response.data; if (response.status !== 'ok') { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_send_messages/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_send_messages/index.tsx index 3a3b72c253862..c68d82d99b9ac 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_send_messages/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_send_messages/index.tsx @@ -8,6 +8,8 @@ import { useCallback, useState } from 'react'; import { HttpSetup } from '@kbn/core-http-browser'; + +import { useAssistantContext } from '../../assistant_context'; import { Conversation, Message } from '../../assistant_context/types'; import { fetchConnectorExecuteAction } from '../api'; @@ -23,20 +25,25 @@ interface UseSendMessages { } export const useSendMessages = (): UseSendMessages => { + const { assistantLangChain } = useAssistantContext(); const [isLoading, setIsLoading] = useState(false); - const sendMessages = useCallback(async ({ apiConfig, http, messages }: SendMessagesProps) => { - setIsLoading(true); - try { - return await fetchConnectorExecuteAction({ - http, - messages, - apiConfig, - }); - } finally { - setIsLoading(false); - } - }, []); + const sendMessages = useCallback( + async ({ apiConfig, http, messages }: SendMessagesProps) => { + setIsLoading(true); + try { + return await fetchConnectorExecuteAction({ + assistantLangChain, + http, + messages, + apiConfig, + }); + } finally { + setIsLoading(false); + } + }, + [assistantLangChain] + ); return { isLoading, sendMessages }; }; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.test.tsx index 466ccbb83cb0f..6e39da055043a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.test.tsx @@ -28,6 +28,7 @@ const ContextWrapper: React.FC = ({ children }) => ( <AssistantProvider actionTypeRegistry={actionTypeRegistry} assistantAvailability={mockAssistantAvailability} + assistantLangChain={false} augmentMessageCodeBlocks={jest.fn()} baseAllow={[]} baseAllowReplacement={[]} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx index 6779d1231e93d..bf1f72bb4beac 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.tsx @@ -49,6 +49,7 @@ type ShowAssistantOverlay = ({ export interface AssistantProviderProps { actionTypeRegistry: ActionTypeRegistryContract; assistantAvailability: AssistantAvailability; + assistantLangChain: boolean; assistantTelemetry?: AssistantTelemetry; augmentMessageCodeBlocks: (currentConversation: Conversation) => CodeBlockDetails[][]; baseAllow: string[]; @@ -85,6 +86,7 @@ export interface UseAssistantContext { augmentMessageCodeBlocks: (currentConversation: Conversation) => CodeBlockDetails[][]; allQuickPrompts: QuickPrompt[]; allSystemPrompts: Prompt[]; + assistantLangChain: boolean; baseAllow: string[]; baseAllowReplacement: string[]; docLinks: Omit<DocLinksStart, 'links'>; @@ -129,6 +131,7 @@ const AssistantContext = React.createContext<UseAssistantContext | undefined>(un export const AssistantProvider: React.FC<AssistantProviderProps> = ({ actionTypeRegistry, assistantAvailability, + assistantLangChain, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, @@ -248,6 +251,7 @@ export const AssistantProvider: React.FC<AssistantProviderProps> = ({ () => ({ actionTypeRegistry, assistantAvailability, + assistantLangChain, assistantTelemetry, augmentMessageCodeBlocks, allQuickPrompts: localStorageQuickPrompts ?? [], @@ -284,6 +288,7 @@ export const AssistantProvider: React.FC<AssistantProviderProps> = ({ [ actionTypeRegistry, assistantAvailability, + assistantLangChain, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx b/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx index aec3a6262ba4c..484dd316cc0ac 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx @@ -66,6 +66,7 @@ export const TestProvidersComponent: React.FC<Props> = ({ <AssistantProvider actionTypeRegistry={actionTypeRegistry} assistantAvailability={assistantAvailability} + assistantLangChain={false} augmentMessageCodeBlocks={jest.fn().mockReturnValue([])} baseAllow={[]} baseAllowReplacement={[]} diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx index 26eb55d49abfb..9bbdf52e606bb 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx @@ -46,6 +46,7 @@ export const TestProvidersComponent: React.FC<Props> = ({ children, isILMAvailab <AssistantProvider actionTypeRegistry={actionTypeRegistry} assistantAvailability={mockAssistantAvailability} + assistantLangChain={false} augmentMessageCodeBlocks={jest.fn()} baseAllow={[]} baseAllowReplacement={[]} diff --git a/x-pack/plugins/elastic_assistant/README.md b/x-pack/plugins/elastic_assistant/README.md new file mode 100755 index 0000000000000..e0fef329abc08 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/README.md @@ -0,0 +1,9 @@ +# Elastic AI Assistant + +This plugin implements (only) server APIs for the `Elastic AI Assistant`. + +This plugin does NOT contain UI components. See `x-pack/packages/kbn-elastic-assistant` for React components. + +## Maintainers + +Maintained by the Security Solution team diff --git a/x-pack/plugins/elastic_assistant/common/constants.ts b/x-pack/plugins/elastic_assistant/common/constants.ts new file mode 100755 index 0000000000000..c6c6f2419a182 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/common/constants.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const PLUGIN_ID = 'elasticAssistant'; +export const PLUGIN_NAME = 'elasticAssistant'; + +export const BASE_PATH = '/internal/elastic_assistant'; + +export const POST_ACTIONS_CONNECTOR_EXECUTE = `${BASE_PATH}/actions/connector/{connectorId}/_execute`; diff --git a/x-pack/plugins/elastic_assistant/jest.config.js b/x-pack/plugins/elastic_assistant/jest.config.js new file mode 100644 index 0000000000000..7bbeb3b1c89d2 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/jest.config.js @@ -0,0 +1,17 @@ +/* + * 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. + */ + +module.exports = { + collectCoverageFrom: [ + '<rootDir>/x-pack/plugins/elastic_assistant/{common,lib,server}/**/*.{ts,tsx}', + ], + coverageDirectory: '<rootDir>/target/kibana-coverage/jest/x-pack/plugins/elastic_assistant', + coverageReporters: ['text', 'html'], + rootDir: '../../..', + roots: ['<rootDir>/x-pack/plugins/elastic_assistant'], + preset: '@kbn/test', +}; diff --git a/x-pack/plugins/elastic_assistant/kibana.jsonc b/x-pack/plugins/elastic_assistant/kibana.jsonc new file mode 100644 index 0000000000000..d7518cf600983 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/kibana.jsonc @@ -0,0 +1,15 @@ +{ + "type": "plugin", + "id": "@kbn/elastic-assistant-plugin", + "owner": "@elastic/security-solution", + "description": "Server APIs for the Elastic AI Assistant", + "plugin": { + "id": "elasticAssistant", + "server": true, + "browser": false, + "requiredPlugins": [ + "actions", + "data" + ] + } +} diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/action_result_data.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/action_result_data.ts new file mode 100644 index 0000000000000..280a86d2ac326 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/action_result_data.ts @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/** + * A mock `data` property from an `actionResult` response, which is returned + * from the `execute` method of the Actions plugin. + * + * Given the following example: + * + * ```ts + * const actionResult = await actionsClient.execute(requestBody); + * ``` + * + * In the above example, `actionResult.data` would be this mock data. + */ +export const mockActionResultData = { + id: 'chatcmpl-7sFVvksgFtMUac3pY5bTypFAKaGX1', + object: 'chat.completion', + created: 1693163703, + model: 'gpt-4', + choices: [ + { + index: 0, + finish_reason: 'stop', + message: { + role: 'assistant', + content: 'Yes, your name is Andrew. How can I assist you further, Andrew?', + }, + }, + ], + usage: { completion_tokens: 16, prompt_tokens: 140, total_tokens: 156 }, +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/lang_chain_messages.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/lang_chain_messages.ts new file mode 100644 index 0000000000000..bbf32c714065f --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/lang_chain_messages.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 { AIMessage, BaseMessage, HumanMessage } from 'langchain/schema'; + +export const langChainMessages: BaseMessage[] = [ + new HumanMessage('What is my name?'), + new AIMessage( + "I'm sorry, but I am not able to answer questions unrelated to Elastic Security. If you have any questions about Elastic Security, please feel free to ask." + ), + new HumanMessage('\n\nMy name is Andrew'), + new AIMessage( + "Hello Andrew! If you have any questions about Elastic Security, feel free to ask, and I'll do my best to help you." + ), + new HumanMessage('\n\nDo you know my name?'), +]; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/request.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/request.ts new file mode 100644 index 0000000000000..827f08683e0b8 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/request.ts @@ -0,0 +1,11 @@ +/* + * 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 { httpServerMock } from '@kbn/core/server/mocks'; + +export const requestMock = { + create: httpServerMock.createKibanaRequest, +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/request_context.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/request_context.ts new file mode 100644 index 0000000000000..19fb44f7f8bac --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/request_context.ts @@ -0,0 +1,56 @@ +/* + * 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 { coreMock } from '@kbn/core/server/mocks'; +import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; + +export const createMockClients = () => { + const core = coreMock.createRequestHandlerContext(); + const license = licensingMock.createLicenseMock(); + + return { + core, + clusterClient: core.elasticsearch.client, + savedObjectsClient: core.savedObjects.client, + + licensing: { + ...licensingMock.createRequestHandlerContext({ license }), + license, + }, + + config: createMockConfig(), + appClient: createAppClientMock(), + }; +}; + +type MockClients = ReturnType<typeof createMockClients>; + +const convertRequestContextMock = <T>(context: T) => { + return coreMock.createCustomRequestHandlerContext(context); +}; + +const createMockConfig = () => ({}); + +const createAppClientMock = () => ({}); + +const createRequestContextMock = (clients: MockClients = createMockClients()) => { + return { + core: clients.core, + }; +}; + +const createTools = () => { + const clients = createMockClients(); + const context = createRequestContextMock(clients); + + return { clients, context }; +}; + +export const requestContextMock = { + create: createRequestContextMock, + convertContext: convertRequestContextMock, + createTools, +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/response.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/response.ts new file mode 100644 index 0000000000000..8efe2407f2245 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/response.ts @@ -0,0 +1,12 @@ +/* + * 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 { httpServerMock } from '@kbn/core/server/mocks'; + +export const responseMock = { + create: httpServerMock.createResponseFactory, +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/server.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/server.ts new file mode 100644 index 0000000000000..7ac44e1beedf1 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/server.ts @@ -0,0 +1,95 @@ +/* + * 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 { httpServiceMock } from '@kbn/core/server/mocks'; +import type { RequestHandler, RouteConfig, KibanaRequest } from '@kbn/core/server'; +import type { RequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; + +import { requestMock } from './request'; +import { responseMock as responseFactoryMock } from './response'; +import { requestContextMock } from './request_context'; +import { responseAdapter } from './test_adapters'; + +interface Route { + config: RouteConfig<unknown, unknown, unknown, 'get' | 'post' | 'delete' | 'patch' | 'put'>; + handler: RequestHandler; +} + +const getRoute = (routerMock: MockServer['router']): Route => { + const routeCalls = [ + ...routerMock.get.mock.calls, + ...routerMock.post.mock.calls, + ...routerMock.put.mock.calls, + ...routerMock.patch.mock.calls, + ...routerMock.delete.mock.calls, + ]; + + const [route] = routeCalls; + if (!route) { + throw new Error('No route registered!'); + } + + const [config, handler] = route; + return { config, handler }; +}; + +const buildResultMock = () => ({ ok: jest.fn((x) => x), badRequest: jest.fn((x) => x) }); + +class MockServer { + constructor( + public readonly router = httpServiceMock.createRouter(), + private responseMock = responseFactoryMock.create(), + private contextMock = requestContextMock.convertContext(requestContextMock.create()), + private resultMock = buildResultMock() + ) {} + + public validate(request: KibanaRequest) { + this.validateRequest(request); + return this.resultMock; + } + + public async inject(request: KibanaRequest, context: RequestHandlerContext = this.contextMock) { + const validatedRequest = this.validateRequest(request); + const [rejection] = this.resultMock.badRequest.mock.calls; + if (rejection) { + throw new Error(`Request was rejected with message: '${rejection}'`); + } + + await this.getRoute().handler(context, validatedRequest, this.responseMock); + return responseAdapter(this.responseMock); + } + + private getRoute(): Route { + return getRoute(this.router); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private maybeValidate(part: any, validator?: any): any { + return typeof validator === 'function' ? validator(part, this.resultMock) : part; + } + + private validateRequest(request: KibanaRequest): KibanaRequest { + const validations = this.getRoute().config.validate; + if (!validations) { + return request; + } + + const validatedRequest = requestMock.create({ + path: request.route.path, + method: request.route.method, + body: this.maybeValidate(request.body, validations.body), + query: this.maybeValidate(request.query, validations.query), + params: this.maybeValidate(request.params, validations.params), + }); + + return validatedRequest; + } +} +const createMockServer = () => new MockServer(); + +export const serverMock = { + create: createMockServer, +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/test_adapters.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/test_adapters.ts new file mode 100644 index 0000000000000..4de81ca931692 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/test_adapters.ts @@ -0,0 +1,64 @@ +/* + * 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 { responseMock } from './response'; + +type ResponseMock = ReturnType<typeof responseMock.create>; +type Method = keyof ResponseMock; + +type MockCall = any; // eslint-disable-line @typescript-eslint/no-explicit-any + +interface ResponseCall { + body: any; // eslint-disable-line @typescript-eslint/no-explicit-any + status: number; +} + +/** + * @internal + */ +export interface Response extends ResponseCall { + calls: ResponseCall[]; +} + +const buildResponses = (method: Method, calls: MockCall[]): ResponseCall[] => { + if (!calls.length) return []; + + switch (method) { + case 'ok': + return calls.map(([call]) => ({ status: 200, body: call.body })); + case 'custom': + return calls.map(([call]) => ({ + status: call.statusCode, + body: JSON.parse(call.body), + })); + case 'customError': + return calls.map(([call]) => ({ + status: call.statusCode, + body: call.body, + })); + default: + throw new Error(`Encountered unexpected call to response.${method}`); + } +}; + +export const responseAdapter = (response: ResponseMock): Response => { + const methods = Object.keys(response) as Method[]; + const calls = methods + .reduce<Response['calls']>((responses, method) => { + const methodMock = response[method]; + return [...responses, ...buildResponses(method, methodMock.mock.calls)]; + }, []) + .sort((call, other) => other.status - call.status); + + const [{ body, status }] = calls; + + return { + body, + status, + calls, + }; +}; diff --git a/x-pack/plugins/elastic_assistant/server/index.ts b/x-pack/plugins/elastic_assistant/server/index.ts new file mode 100755 index 0000000000000..a375e036d8238 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/index.ts @@ -0,0 +1,18 @@ +/* + * 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 { PluginInitializerContext } from '@kbn/core/server'; +import { ElasticAssistantPlugin } from './plugin'; + +export function plugin(initializerContext: PluginInitializerContext) { + return new ElasticAssistantPlugin(initializerContext); +} + +export type { + ElasticAssistantPluginSetup as EcsDataQualityDashboardPluginSetup, + ElasticAssistantPluginStart as EcsDataQualityDashboardPluginStart, +} from './types'; diff --git a/x-pack/plugins/elastic_assistant/server/lib/build_response/index.ts b/x-pack/plugins/elastic_assistant/server/lib/build_response/index.ts new file mode 100644 index 0000000000000..bbec702c74915 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/build_response/index.ts @@ -0,0 +1,68 @@ +/* + * 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 { CustomHttpResponseOptions, KibanaResponseFactory } from '@kbn/core-http-server'; + +const statusToErrorMessage = ( + statusCode: number +): + | 'Bad Request' + | 'Unauthorized' + | 'Forbidden' + | 'Not Found' + | 'Conflict' + | 'Internal Error' + | '(unknown error)' => { + switch (statusCode) { + case 400: + return 'Bad Request'; + case 401: + return 'Unauthorized'; + case 403: + return 'Forbidden'; + case 404: + return 'Not Found'; + case 409: + return 'Conflict'; + case 500: + return 'Internal Error'; + default: + return '(unknown error)'; + } +}; + +/** Creates responses */ +export class ResponseFactory { + /** constructor */ + constructor(private response: KibanaResponseFactory) {} + + /** error */ + error<T>({ statusCode, body, headers }: CustomHttpResponseOptions<T>) { + const contentType: CustomHttpResponseOptions<T>['headers'] = { + 'content-type': 'application/json', + }; + const defaultedHeaders: CustomHttpResponseOptions<T>['headers'] = { + ...contentType, + ...(headers ?? {}), + }; + + return this.response.custom({ + body: Buffer.from( + JSON.stringify({ + message: body ?? statusToErrorMessage(statusCode), + status_code: statusCode, + }) + ), + headers: defaultedHeaders, + statusCode, + }); + } +} + +/** builds a response */ +export const buildResponse = (response: KibanaResponseFactory): ResponseFactory => + new ResponseFactory(response); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.test.ts new file mode 100644 index 0000000000000..b6c4dd3917585 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.test.ts @@ -0,0 +1,105 @@ +/* + * 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 { KibanaRequest } from '@kbn/core/server'; +import { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; + +import { ResponseBody } from '../helpers'; +import { ActionsClientLlm } from '../llm/actions_client_llm'; +import { mockActionResultData } from '../../../__mocks__/action_result_data'; +import { langChainMessages } from '../../../__mocks__/lang_chain_messages'; +import { executeCustomLlmChain } from '.'; + +jest.mock('../llm/actions_client_llm'); + +const mockConversationChain = { + call: jest.fn(), +}; + +jest.mock('langchain/chains', () => ({ + ConversationChain: jest.fn().mockImplementation(() => mockConversationChain), +})); + +const mockConnectorId = 'mock-connector-id'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const mockRequest: KibanaRequest<unknown, unknown, any, any> = {} as KibanaRequest< + unknown, + unknown, + any, // eslint-disable-line @typescript-eslint/no-explicit-any + any // eslint-disable-line @typescript-eslint/no-explicit-any +>; + +const mockActions: ActionsPluginStart = {} as ActionsPluginStart; + +describe('executeCustomLlmChain', () => { + beforeEach(() => { + jest.clearAllMocks(); + + ActionsClientLlm.prototype.getActionResultData = jest + .fn() + .mockReturnValueOnce(mockActionResultData); + }); + + it('creates an instance of ActionsClientLlm with the expected context from the request', async () => { + await executeCustomLlmChain({ + actions: mockActions, + connectorId: mockConnectorId, + langChainMessages, + request: mockRequest, + }); + + expect(ActionsClientLlm).toHaveBeenCalledWith({ + actions: mockActions, + connectorId: mockConnectorId, + request: mockRequest, + }); + }); + + it('kicks off the chain with (only) the last message', async () => { + await executeCustomLlmChain({ + actions: mockActions, + connectorId: mockConnectorId, + langChainMessages, + request: mockRequest, + }); + + expect(mockConversationChain.call).toHaveBeenCalledWith({ + input: '\n\nDo you know my name?', + }); + }); + + it('kicks off the chain with the expected message when langChainMessages has only one entry', async () => { + const onlyOneMessage = [langChainMessages[0]]; + + await executeCustomLlmChain({ + actions: mockActions, + connectorId: mockConnectorId, + langChainMessages: onlyOneMessage, + request: mockRequest, + }); + + expect(mockConversationChain.call).toHaveBeenCalledWith({ + input: 'What is my name?', + }); + }); + + it('returns the expected response body', async () => { + const result: ResponseBody = await executeCustomLlmChain({ + actions: mockActions, + connectorId: mockConnectorId, + langChainMessages, + request: mockRequest, + }); + + expect(result).toEqual({ + connector_id: 'mock-connector-id', + data: mockActionResultData, + status: 'ok', + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.ts new file mode 100644 index 0000000000000..ee7b6820c983d --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.ts @@ -0,0 +1,51 @@ +/* + * 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 { KibanaRequest } from '@kbn/core/server'; +import type { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; +import { ConversationChain } from 'langchain/chains'; +import { BufferMemory, ChatMessageHistory } from 'langchain/memory'; +import { BaseMessage } from 'langchain/schema'; + +import { ActionsClientLlm } from '../llm/actions_client_llm'; +import { ResponseBody } from '../helpers'; + +export const executeCustomLlmChain = async ({ + actions, + connectorId, + langChainMessages, + request, +}: { + actions: ActionsPluginStart; + connectorId: string; + langChainMessages: BaseMessage[]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + request: KibanaRequest<unknown, unknown, any, any>; +}): Promise<ResponseBody> => { + const llm = new ActionsClientLlm({ actions, connectorId, request }); + + const pastMessages = langChainMessages.slice(0, -1); // all but the last message + const latestMessage = langChainMessages.slice(-1); // the last message + + const memory = new BufferMemory({ + chatHistory: new ChatMessageHistory(pastMessages), + }); + + const chain = new ConversationChain({ llm, memory }); + + await chain.call({ input: latestMessage[0].content }); // kick off the chain with the last message + + // The assistant (on the client side) expects the same response returned + // from the actions framework, so we need to return the same shape of data: + const responseBody = { + connector_id: connectorId, + data: llm.getActionResultData(), // the response from the actions framework + status: 'ok', + }; + + return responseBody; +}; diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.test.ts new file mode 100644 index 0000000000000..1c62fab9df6cc --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.test.ts @@ -0,0 +1,185 @@ +/* + * 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 { Message } from '@kbn/elastic-assistant'; +import { AIMessage, BaseMessage, HumanMessage, SystemMessage } from 'langchain/schema'; + +import { + getLangChainMessage, + getLangChainMessages, + getMessageContentAndRole, + unsafeGetAssistantMessagesFromRequest, +} from './helpers'; +import { langChainMessages } from '../../__mocks__/lang_chain_messages'; + +describe('helpers', () => { + describe('getLangChainMessage', () => { + const testCases: Array<[Pick<Message, 'content' | 'role'>, typeof BaseMessage]> = [ + [ + { + role: 'system', + content: 'System message', + }, + SystemMessage, + ], + [ + { + role: 'user', + content: 'User message', + }, + HumanMessage, + ], + [ + { + role: 'assistant', + content: 'Assistant message', + }, + AIMessage, + ], + [ + { + role: 'unknown' as Message['role'], + content: 'Unknown message', + }, + HumanMessage, + ], + ]; + + testCases.forEach(([testCase, expectedClass]) => { + it(`returns the expected content when role is ${testCase.role}`, () => { + const result = getLangChainMessage(testCase); + + expect(result.content).toEqual(testCase.content); + }); + + it(`returns the expected BaseMessage instance when role is ${testCase.role}`, () => { + const result = getLangChainMessage(testCase); + + expect(result instanceof expectedClass).toBeTruthy(); + }); + }); + }); + + describe('getLangChainMessages', () => { + const assistantMessages: Array<Pick<Message, 'content' | 'role'>> = [ + { + content: 'What is my name?', + role: 'user', + }, + { + content: + "I'm sorry, but I am not able to answer questions unrelated to Elastic Security. If you have any questions about Elastic Security, please feel free to ask.", + role: 'assistant', + }, + { + content: '\n\nMy name is Andrew', + role: 'user', + }, + { + content: + "Hello Andrew! If you have any questions about Elastic Security, feel free to ask, and I'll do my best to help you.", + role: 'assistant', + }, + { + content: '\n\nDo you know my name?', + role: 'user', + }, + ]; + + it('returns the expected BaseMessage instances', () => { + expect(getLangChainMessages(assistantMessages)).toEqual(langChainMessages); + }); + }); + + describe('getMessageContentAndRole', () => { + const testCases: Array<[string, Pick<Message, 'content' | 'role'>]> = [ + ['Prompt 1', { content: 'Prompt 1', role: 'user' }], + ['Prompt 2', { content: 'Prompt 2', role: 'user' }], + ['', { content: '', role: 'user' }], + ]; + + testCases.forEach(([prompt, expectedOutput]) => { + test(`Given the prompt "${prompt}", it returns the prompt as content with a "user" role`, () => { + const result = getMessageContentAndRole(prompt); + + expect(result).toEqual(expectedOutput); + }); + }); + }); + + describe('unsafeGetAssistantMessagesFromRequest', () => { + const rawSubActionParamsBody = { + messages: [ + { role: 'user', content: '\n\n\n\nWhat is my name?' }, + { + role: 'assistant', + content: + "Hello! Since we are communicating through text, I do not have the information about your name. Please feel free to share your name with me, if you'd like.", + }, + { role: 'user', content: '\n\nMy name is Andrew' }, + { + role: 'assistant', + content: + "Hi, Andrew! It's nice to meet you. How can I help you or what would you like to talk about today?", + }, + { role: 'user', content: '\n\nDo you know my name?' }, + ], + }; + + it('returns the expected assistant messages from a conversation', () => { + const result = unsafeGetAssistantMessagesFromRequest(JSON.stringify(rawSubActionParamsBody)); + + const expected = [ + { role: 'user', content: '\n\n\n\nWhat is my name?' }, + { + role: 'assistant', + content: + "Hello! Since we are communicating through text, I do not have the information about your name. Please feel free to share your name with me, if you'd like.", + }, + { role: 'user', content: '\n\nMy name is Andrew' }, + { + role: 'assistant', + content: + "Hi, Andrew! It's nice to meet you. How can I help you or what would you like to talk about today?", + }, + { role: 'user', content: '\n\nDo you know my name?' }, + ]; + + expect(result).toEqual(expected); + }); + + it('returns an empty array when the rawSubActionParamsBody is undefined', () => { + const result = unsafeGetAssistantMessagesFromRequest(undefined); + + expect(result).toEqual([]); + }); + + it('returns an empty array when the rawSubActionParamsBody messages[] array is empty', () => { + const hasEmptyMessages = { + messages: [], + }; + + const result = unsafeGetAssistantMessagesFromRequest(JSON.stringify(hasEmptyMessages)); + + expect(result).toEqual([]); + }); + + it('returns an empty array when the rawSubActionParamsBody shape is unexpected', () => { + const unexpected = { invalidKey: 'some_value' }; + + const result = unsafeGetAssistantMessagesFromRequest(JSON.stringify(unexpected)); + + expect(result).toEqual([]); + }); + + it('returns an empty array when the rawSubActionParamsBody is invalid JSON', () => { + const result = unsafeGetAssistantMessagesFromRequest('[]'); + + expect(result).toEqual([]); + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.ts new file mode 100644 index 0000000000000..90364dcfe75db --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.ts @@ -0,0 +1,57 @@ +/* + * 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 { Message } from '@kbn/elastic-assistant'; +import { AIMessage, BaseMessage, HumanMessage, SystemMessage } from 'langchain/schema'; + +export const getLangChainMessage = ( + assistantMessage: Pick<Message, 'content' | 'role'> +): BaseMessage => { + switch (assistantMessage.role) { + case 'system': + return new SystemMessage(assistantMessage.content); + case 'user': + return new HumanMessage(assistantMessage.content); + case 'assistant': + return new AIMessage(assistantMessage.content); + default: + return new HumanMessage(assistantMessage.content); + } +}; + +export const getLangChainMessages = ( + assistantMessages: Array<Pick<Message, 'content' | 'role'>> +): BaseMessage[] => assistantMessages.map(getLangChainMessage); + +export const getMessageContentAndRole = (prompt: string): Pick<Message, 'content' | 'role'> => ({ + content: prompt, + role: 'user', +}); + +export interface ResponseBody { + status: string; + data: Record<string, unknown>; + connector_id: string; +} + +/** An unsafe, temporary stub that parses assistant messages from the request with no validation */ +export const unsafeGetAssistantMessagesFromRequest = ( + rawSubActionParamsBody: string | undefined +): Array<Pick<Message, 'content' | 'role'>> => { + try { + if (rawSubActionParamsBody == null) { + return []; + } + + const subActionParamsBody = JSON.parse(rawSubActionParamsBody); // TODO: unsafe, no validation + const messages = subActionParamsBody?.messages; + + return Array.isArray(messages) ? messages : []; + } catch { + return []; + } +}; diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.test.ts new file mode 100644 index 0000000000000..289793de859c0 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.test.ts @@ -0,0 +1,172 @@ +/* + * 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 { KibanaRequest } from '@kbn/core/server'; +import type { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; + +import { ActionsClientLlm } from './actions_client_llm'; +import { mockActionResultData } from '../../../__mocks__/action_result_data'; + +const connectorId = 'mock-connector-id'; + +const mockExecute = jest.fn().mockImplementation(() => ({ + data: mockActionResultData, + status: 'ok', +})); + +const mockActions = { + getActionsClientWithRequest: jest.fn().mockImplementation(() => ({ + execute: mockExecute, + })), +} as unknown as ActionsPluginStart; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const mockRequest: KibanaRequest<unknown, unknown, any, any> = { + params: { connectorId }, + body: { + params: { + subActionParams: { + body: '{"messages":[{"role":"user","content":"\\n\\n\\n\\nWhat is my name?"},{"role":"assistant","content":"I\'m sorry, but I don\'t have the information about your name. You can tell me your name if you\'d like, and we can continue our conversation from there."},{"role":"user","content":"\\n\\nMy name is Andrew"},{"role":"assistant","content":"Hello, Andrew! It\'s nice to meet you. What would you like to talk about today?"},{"role":"user","content":"\\n\\nDo you know my name?"}]}', + }, + subAction: 'test', + }, + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any +} as KibanaRequest<unknown, unknown, any, any>; + +const prompt = 'Do you know my name?'; + +describe('ActionsClientLlm', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('getActionResultData', () => { + it('returns the expected data', async () => { + const actionsClientLlm = new ActionsClientLlm({ + actions: mockActions, + connectorId, + request: mockRequest, + }); + + await actionsClientLlm._call(prompt); // ignore the result + + expect(actionsClientLlm.getActionResultData()).toEqual(mockActionResultData); + }); + }); + + describe('_llmType', () => { + it('returns the expected LLM type', () => { + const actionsClientLlm = new ActionsClientLlm({ + actions: mockActions, + connectorId, + request: mockRequest, + }); + + expect(actionsClientLlm._llmType()).toEqual('ActionsClientLlm'); + }); + }); + + describe('_call', () => { + it('returns the expected content when _call is invoked', async () => { + const actionsClientLlm = new ActionsClientLlm({ + actions: mockActions, + connectorId, + request: mockRequest, + }); + + const result = await actionsClientLlm._call(prompt); + + expect(result).toEqual('Yes, your name is Andrew. How can I assist you further, Andrew?'); + }); + + it('rejects with the expected error when the action result status is error', async () => { + const hasErrorStatus = jest.fn().mockImplementation(() => ({ + message: 'action-result-message', + serviceMessage: 'action-result-service-message', + status: 'error', // <-- error status + })); + + const badActions = { + getActionsClientWithRequest: jest.fn().mockImplementation(() => ({ + execute: hasErrorStatus, + })), + } as unknown as ActionsPluginStart; + + const actionsClientLlm = new ActionsClientLlm({ + actions: badActions, + connectorId, + request: mockRequest, + }); + + expect(actionsClientLlm._call(prompt)).rejects.toThrowError( + 'ActionsClientLlm: action result status is error: action-result-message - action-result-service-message' + ); + }); + + it('rejects with the expected error the message has invalid content', async () => { + const invalidContent = { + id: 'chatcmpl-7sFVvksgFtMUac3pY5bTypFAKaGX1', + object: 'chat.completion', + created: 1693163703, + model: 'gpt-4', + choices: [ + { + index: 0, + finish_reason: 'stop', + message: { + role: 'assistant', + content: 1234, // <-- invalid content + }, + }, + ], + usage: { completion_tokens: 16, prompt_tokens: 140, total_tokens: 156 }, + }; + + mockExecute.mockImplementation(() => ({ + data: invalidContent, + status: 'ok', + })); + + const actionsClientLlm = new ActionsClientLlm({ + actions: mockActions, + connectorId, + request: mockRequest, + }); + + expect(actionsClientLlm._call(prompt)).rejects.toThrowError( + 'ActionsClientLlm: choices[0] message content should be a string, but it had an unexpected type: number' + ); + }); + + it('rejects with the expected error when choices is empty', async () => { + const invalidContent = { + id: 'chatcmpl-7sFVvksgFtMUac3pY5bTypFAKaGX1', + object: 'chat.completion', + created: 1693163703, + model: 'gpt-4', + choices: [], // <-- empty choices + usage: { completion_tokens: 16, prompt_tokens: 140, total_tokens: 156 }, + }; + + mockExecute.mockImplementation(() => ({ + data: invalidContent, + status: 'ok', + })); + + const actionsClientLlm = new ActionsClientLlm({ + actions: mockActions, + connectorId, + request: mockRequest, + }); + + expect(actionsClientLlm._call(prompt)).rejects.toThrowError( + 'ActionsClientLlm: choices is expected to be an non-empty array' + ); + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.ts new file mode 100644 index 0000000000000..00d78dc6cb309 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.ts @@ -0,0 +1,99 @@ +/* + * 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 { KibanaRequest } from '@kbn/core/server'; +import type { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; +import { LLM } from 'langchain/llms/base'; +import { get } from 'lodash/fp'; + +import { getMessageContentAndRole } from '../helpers'; + +const LLM_TYPE = 'ActionsClientLlm'; + +export class ActionsClientLlm extends LLM { + #actions: ActionsPluginStart; + #connectorId: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + #request: KibanaRequest<unknown, unknown, any, any>; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + #actionResultData: Record<string, any>; + + constructor({ + actions, + connectorId, + request, + }: { + actions: ActionsPluginStart; + connectorId: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + request: KibanaRequest<unknown, unknown, any, any>; + }) { + super({}); + + this.#actions = actions; + this.#connectorId = connectorId; + this.#request = request; + this.#actionResultData = {}; + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + getActionResultData(): Record<string, any> { + return this.#actionResultData; + } + + _llmType() { + return LLM_TYPE; + } + + async _call(prompt: string): Promise<string> { + // convert the Langchain prompt to an assistant message: + const assistantMessage = getMessageContentAndRole(prompt); + + // create a new connector request body with the assistant message: + const requestBody = { + actionId: this.#connectorId, + params: { + ...this.#request.body.params, // the original request body params + subActionParams: { + ...this.#request.body.params.subActionParams, // the original request body params.subActionParams + body: JSON.stringify({ messages: [assistantMessage] }), + }, + }, + }; + + // create an actions client from the authenticated request context: + const actionsClient = await this.#actions.getActionsClientWithRequest(this.#request); + + const actionResult = await actionsClient.execute(requestBody); + + if (actionResult.status === 'error') { + throw new Error( + `${LLM_TYPE}: action result status is error: ${actionResult?.message} - ${actionResult?.serviceMessage}` + ); + } + + const choices = get('data.choices', actionResult); + + if (Array.isArray(choices) && choices.length > 0) { + // get the raw content from the first choice, because _call must return a string + const content: string | undefined = choices[0]?.message?.content; + + if (typeof content !== 'string') { + throw new Error( + `${LLM_TYPE}: choices[0] message content should be a string, but it had an unexpected type: ${typeof content}` + ); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.#actionResultData = actionResult.data as Record<string, any>; // save the raw response from the connector, because that's what the assistant expects + + return content; // per the contact of _call, return a string + } else { + throw new Error(`${LLM_TYPE}: choices is expected to be an non-empty array`); + } + } +} diff --git a/x-pack/plugins/elastic_assistant/server/plugin.ts b/x-pack/plugins/elastic_assistant/server/plugin.ts new file mode 100755 index 0000000000000..4e277132e8da0 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/plugin.ts @@ -0,0 +1,80 @@ +/* + * 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 { + PluginInitializerContext, + CoreSetup, + CoreStart, + Plugin, + Logger, + IContextProvider, +} from '@kbn/core/server'; + +import { + ElasticAssistantPluginSetup, + ElasticAssistantPluginSetupDependencies, + ElasticAssistantPluginStart, + ElasticAssistantPluginStartDependencies, + ElasticAssistantRequestHandlerContext, +} from './types'; +import { postActionsConnectorExecuteRoute } from './routes'; + +export class ElasticAssistantPlugin + implements + Plugin< + ElasticAssistantPluginSetup, + ElasticAssistantPluginStart, + ElasticAssistantPluginSetupDependencies, + ElasticAssistantPluginStartDependencies + > +{ + private readonly logger: Logger; + + constructor(initializerContext: PluginInitializerContext) { + this.logger = initializerContext.logger.get(); + } + + private createRouteHandlerContext = ( + core: CoreSetup<ElasticAssistantPluginStart, unknown> + ): IContextProvider<ElasticAssistantRequestHandlerContext, 'elasticAssistant'> => { + return async function elasticAssistantRouteHandlerContext(context, request) { + const [_, pluginsStart] = await core.getStartServices(); + + return { + actions: pluginsStart.actions, + }; + }; + }; + + public setup(core: CoreSetup, plugins: ElasticAssistantPluginSetupDependencies) { + this.logger.debug('elasticAssistant: Setup'); + const router = core.http.createRouter<ElasticAssistantRequestHandlerContext>(); + + core.http.registerRouteHandlerContext< + ElasticAssistantRequestHandlerContext, + 'elasticAssistant' + >( + 'elasticAssistant', + this.createRouteHandlerContext(core as CoreSetup<ElasticAssistantPluginStart, unknown>) + ); + + postActionsConnectorExecuteRoute(router); + return { + actions: plugins.actions, + }; + } + + public start(core: CoreStart, plugins: ElasticAssistantPluginStartDependencies) { + this.logger.debug('elasticAssistant: Started'); + + return { + actions: plugins.actions, + }; + } + + public stop() {} +} diff --git a/x-pack/plugins/elastic_assistant/server/routes/index.ts b/x-pack/plugins/elastic_assistant/server/routes/index.ts new file mode 100644 index 0000000000000..b6a53787763a0 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { postActionsConnectorExecuteRoute } from './post_actions_connector_execute'; diff --git a/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.test.ts b/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.test.ts new file mode 100644 index 0000000000000..a5934ffb8a7a7 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.test.ts @@ -0,0 +1,113 @@ +/* + * 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 { IRouter, KibanaRequest } from '@kbn/core/server'; +import type { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; +import { BaseMessage } from 'langchain/schema'; + +import { mockActionResultData } from '../__mocks__/action_result_data'; +import { postActionsConnectorExecuteRoute } from './post_actions_connector_execute'; +import { ElasticAssistantRequestHandlerContext } from '../types'; + +jest.mock('../lib/build_response', () => ({ + buildResponse: jest.fn().mockImplementation((x) => x), +})); + +jest.mock('../lib/langchain/execute_custom_llm_chain', () => ({ + executeCustomLlmChain: jest.fn().mockImplementation( + async ({ + connectorId, + }: { + actions: ActionsPluginStart; + connectorId: string; + langChainMessages: BaseMessage[]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + request: KibanaRequest<unknown, unknown, any, any>; + }) => { + if (connectorId === 'mock-connector-id') { + return { + connector_id: 'mock-connector-id', + data: mockActionResultData, + status: 'ok', + }; + } else { + throw new Error('simulated error'); + } + } + ), +})); + +const mockContext = { + elasticAssistant: async () => ({ + actions: jest.fn(), + }), +}; + +const mockRequest = { + params: { connectorId: 'mock-connector-id' }, + body: { + params: { + subActionParams: { + body: '{"messages":[{"role":"user","content":"\\n\\n\\n\\nWhat is my name?"},{"role":"assistant","content":"I\'m sorry, but I don\'t have the information about your name. You can tell me your name if you\'d like, and we can continue our conversation from there."},{"role":"user","content":"\\n\\nMy name is Andrew"},{"role":"assistant","content":"Hello, Andrew! It\'s nice to meet you. What would you like to talk about today?"},{"role":"user","content":"\\n\\nDo you know my name?"}]}', + }, + subAction: 'test', + }, + }, +}; + +const mockResponse = { + ok: jest.fn().mockImplementation((x) => x), + error: jest.fn().mockImplementation((x) => x), +}; + +describe('postActionsConnectorExecuteRoute', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('returns the expected response', async () => { + const mockRouter = { + post: jest.fn().mockImplementation(async (_, handler) => { + const result = await handler(mockContext, mockRequest, mockResponse); + + expect(result).toEqual({ + body: { + connector_id: 'mock-connector-id', + data: mockActionResultData, + status: 'ok', + }, + }); + }), + }; + + await postActionsConnectorExecuteRoute( + mockRouter as unknown as IRouter<ElasticAssistantRequestHandlerContext> + ); + }); + + it('returns the expected error when executeCustomLlmChain fails', async () => { + const requestWithBadConnectorId = { + ...mockRequest, + params: { connectorId: 'bad-connector-id' }, + }; + + const mockRouter = { + post: jest.fn().mockImplementation(async (_, handler) => { + const result = await handler(mockContext, requestWithBadConnectorId, mockResponse); + + expect(result).toEqual({ + body: 'simulated error', + statusCode: 500, + }); + }), + }; + + await postActionsConnectorExecuteRoute( + mockRouter as unknown as IRouter<ElasticAssistantRequestHandlerContext> + ); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.ts b/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.ts new file mode 100644 index 0000000000000..be4468587bdd9 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.ts @@ -0,0 +1,72 @@ +/* + * 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 { IRouter } from '@kbn/core/server'; +import { transformError } from '@kbn/securitysolution-es-utils'; + +import { POST_ACTIONS_CONNECTOR_EXECUTE } from '../../common/constants'; +import { + getLangChainMessages, + unsafeGetAssistantMessagesFromRequest, +} from '../lib/langchain/helpers'; +import { buildResponse } from '../lib/build_response'; +import { buildRouteValidation } from '../schemas/common'; +import { + PostActionsConnectorExecuteBody, + PostActionsConnectorExecutePathParams, +} from '../schemas/post_actions_connector_execute'; +import { ElasticAssistantRequestHandlerContext } from '../types'; +import { executeCustomLlmChain } from '../lib/langchain/execute_custom_llm_chain'; + +export const postActionsConnectorExecuteRoute = ( + router: IRouter<ElasticAssistantRequestHandlerContext> +) => { + router.post( + { + path: POST_ACTIONS_CONNECTOR_EXECUTE, + validate: { + body: buildRouteValidation(PostActionsConnectorExecuteBody), + params: buildRouteValidation(PostActionsConnectorExecutePathParams), + }, + }, + async (context, request, response) => { + const resp = buildResponse(response); + + try { + const connectorId = decodeURIComponent(request.params.connectorId); + const rawSubActionParamsBody = request.body.params.subActionParams.body; + + // get the actions plugin start contract from the request context: + const actions = (await context.elasticAssistant).actions; + + // get the assistant messages from the request body: + const assistantMessages = unsafeGetAssistantMessagesFromRequest(rawSubActionParamsBody); + + // convert the assistant messages to LangChain messages: + const langChainMessages = getLangChainMessages(assistantMessages); + + const langChainResponseBody = await executeCustomLlmChain({ + actions, + connectorId, + langChainMessages, + request, + }); + + return response.ok({ + body: langChainResponseBody, + }); + } catch (err) { + const error = transformError(err); + + return resp.error({ + body: error.message, + statusCode: error.statusCode, + }); + } + } + ); +}; diff --git a/x-pack/plugins/elastic_assistant/server/schemas/common.ts b/x-pack/plugins/elastic_assistant/server/schemas/common.ts new file mode 100644 index 0000000000000..00e97a9326c5e --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/schemas/common.ts @@ -0,0 +1,38 @@ +/* + * 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 { fold } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import type * as rt from 'io-ts'; +import { exactCheck, formatErrors } from '@kbn/securitysolution-io-ts-utils'; +import type { + RouteValidationFunction, + RouteValidationResultFactory, + RouteValidationError, +} from '@kbn/core/server'; + +type RequestValidationResult<T> = + | { + value: T; + error?: undefined; + } + | { + value?: undefined; + error: RouteValidationError; + }; + +export const buildRouteValidation = + <T extends rt.Mixed, A = rt.TypeOf<T>>(schema: T): RouteValidationFunction<A> => + (inputValue: unknown, validationResult: RouteValidationResultFactory) => + pipe( + schema.decode(inputValue), + (decoded) => exactCheck(inputValue, decoded), + fold<rt.Errors, A, RequestValidationResult<A>>( + (errors: rt.Errors) => validationResult.badRequest(formatErrors(errors).join()), + (validatedInput: A) => validationResult.ok(validatedInput) + ) + ); diff --git a/x-pack/plugins/elastic_assistant/server/schemas/post_actions_connector_execute.ts b/x-pack/plugins/elastic_assistant/server/schemas/post_actions_connector_execute.ts new file mode 100644 index 0000000000000..0aae23ed7512d --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/schemas/post_actions_connector_execute.ts @@ -0,0 +1,27 @@ +/* + * 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 * as t from 'io-ts'; + +/** Validates the URL path of a POST request to the `/actions/connector/{connector_id}/_execute` endpoint */ +export const PostActionsConnectorExecutePathParams = t.type({ + connectorId: t.string, +}); + +/** Validates the body of a POST request to the `/actions/connector/{connector_id}/_execute` endpoint */ +export const PostActionsConnectorExecuteBody = t.type({ + params: t.type({ + subActionParams: t.type({ + body: t.string, + }), + subAction: t.string, + }), +}); + +export type PostActionsConnectorExecuteBodyInputs = t.TypeOf< + typeof PostActionsConnectorExecuteBody +>; diff --git a/x-pack/plugins/elastic_assistant/server/types.ts b/x-pack/plugins/elastic_assistant/server/types.ts new file mode 100755 index 0000000000000..cbe7e096b4eb3 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/types.ts @@ -0,0 +1,40 @@ +/* + * 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 { + PluginSetupContract as ActionsPluginSetup, + PluginStartContract as ActionsPluginStart, +} from '@kbn/actions-plugin/server'; +import { CustomRequestHandlerContext } from '@kbn/core/server'; + +/** The plugin setup interface */ +export interface ElasticAssistantPluginSetup { + actions: ActionsPluginSetup; +} + +/** The plugin start interface */ +export interface ElasticAssistantPluginStart { + actions: ActionsPluginStart; +} + +export interface ElasticAssistantPluginSetupDependencies { + actions: ActionsPluginSetup; +} +export interface ElasticAssistantPluginStartDependencies { + actions: ActionsPluginStart; +} + +export interface ElasticAssistantApiRequestHandlerContext { + actions: ActionsPluginStart; +} + +/** + * @internal + */ +export type ElasticAssistantRequestHandlerContext = CustomRequestHandlerContext<{ + elasticAssistant: ElasticAssistantApiRequestHandlerContext; +}>; diff --git a/x-pack/plugins/elastic_assistant/tsconfig.json b/x-pack/plugins/elastic_assistant/tsconfig.json new file mode 100644 index 0000000000000..99119202376ec --- /dev/null +++ b/x-pack/plugins/elastic_assistant/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + }, + "include": [ + "common/**/*", + "server/lib/**/*", + "server/**/*", + // must declare *.json explicitly per https://github.com/microsoft/TypeScript/issues/25636 + "server/**/*.json", + "../../../typings/**/*" + ], + "kbn_references": [ + "@kbn/core", + "@kbn/core-http-server", + "@kbn/licensing-plugin", + "@kbn/core-http-request-handler-context-server", + "@kbn/securitysolution-es-utils", + "@kbn/securitysolution-io-ts-utils", + "@kbn/actions-plugin", + "@kbn/elastic-assistant", + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/x-pack/plugins/security_solution/kibana.jsonc b/x-pack/plugins/security_solution/kibana.jsonc index f4716adfca310..91f366b5dd94f 100644 --- a/x-pack/plugins/security_solution/kibana.jsonc +++ b/x-pack/plugins/security_solution/kibana.jsonc @@ -22,6 +22,7 @@ "dataViews", "discover", "ecsDataQualityDashboard", + "elasticAssistant", "embeddable", "eventLog", "features", diff --git a/x-pack/plugins/security_solution/public/app/app.tsx b/x-pack/plugins/security_solution/public/app/app.tsx index 3e172207fb4bd..8bbf2c3a425ec 100644 --- a/x-pack/plugins/security_solution/public/app/app.tsx +++ b/x-pack/plugins/security_solution/public/app/app.tsx @@ -99,6 +99,7 @@ const StartAppComponent: FC<StartAppComponent> = ({ actionTypeRegistry={actionTypeRegistry} augmentMessageCodeBlocks={augmentMessageCodeBlocks} assistantAvailability={assistantAvailability} + assistantLangChain={false} assistantTelemetry={assistantTelemetry} defaultAllow={defaultAllow} defaultAllowReplacement={defaultAllowReplacement} diff --git a/x-pack/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx b/x-pack/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx index f36b776b72b04..90c64ec496c78 100644 --- a/x-pack/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/mock_assistant_provider.tsx @@ -34,6 +34,7 @@ export const MockAssistantProviderComponent: React.FC<Props> = ({ children }) => <AssistantProvider actionTypeRegistry={actionTypeRegistry} assistantAvailability={mockAssistantAvailability} + assistantLangChain={false} augmentMessageCodeBlocks={jest.fn(() => [])} baseAllow={[]} baseAllowReplacement={[]} diff --git a/yarn.lock b/yarn.lock index b3a342acb0eef..7264182e33b4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,6 +35,20 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" +"@anthropic-ai/sdk@^0.5.7": + version "0.5.10" + resolved "https://registry.yarnpkg.com/@anthropic-ai/sdk/-/sdk-0.5.10.tgz#8cd0b68ac32c71e579b466a89ea30338f2165a32" + integrity sha512-P8xrIuTUO/6wDzcjQRUROXp4WSqtngbXaE4GpEu0PhEmnq/1Q8vbF1s0o7W07EV3j8zzRoyJxAKovUJtNXH7ew== + dependencies: + "@types/node" "^18.11.18" + "@types/node-fetch" "^2.6.4" + abort-controller "^3.0.0" + agentkeepalive "^4.2.1" + digest-fetch "^1.3.0" + form-data-encoder "1.7.2" + formdata-node "^4.3.2" + node-fetch "^2.6.7" + "@apidevtools/json-schema-ref-parser@^9.0.6": version "9.0.9" resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b" @@ -4250,6 +4264,10 @@ version "0.0.0" uid "" +"@kbn/elastic-assistant-plugin@link:x-pack/plugins/elastic_assistant": + version "0.0.0" + uid "" + "@kbn/elastic-assistant@link:x-pack/packages/kbn-elastic-assistant": version "0.0.0" uid "" @@ -9245,7 +9263,7 @@ dependencies: "@types/node" "*" -"@types/node-fetch@2.6.4": +"@types/node-fetch@2.6.4", "@types/node-fetch@^2.6.4": version "2.6.4" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== @@ -9275,7 +9293,7 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@18.17.1", "@types/node@>= 8", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=8.9.0", "@types/node@^10.1.0", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0", "@types/node@^14.14.31": +"@types/node@*", "@types/node@18.17.1", "@types/node@>= 8", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=8.9.0", "@types/node@^10.1.0", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0", "@types/node@^14.14.31", "@types/node@^18.11.18": version "18.17.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.17.1.tgz#84c32903bf3a09f7878c391d31ff08f6fe7d8335" integrity sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw== @@ -9609,7 +9627,7 @@ dependencies: "@types/node" "*" -"@types/retry@^0.12.0": +"@types/retry@0.12.0", "@types/retry@^0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== @@ -9828,6 +9846,11 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.0.tgz#53ef263e5239728b56096b0a869595135b7952d2" integrity sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q== +"@types/uuid@^9.0.1": + version "9.0.2" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.2.tgz#ede1d1b1e451548d44919dc226253e32a6952c4b" + integrity sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ== + "@types/vfile-message@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-2.0.0.tgz#690e46af0fdfc1f9faae00cd049cc888957927d5" @@ -10409,6 +10432,13 @@ abbrev@1, abbrev@^1.0.0: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -11569,12 +11599,17 @@ balanced-match@^2.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9" integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA== +base-64@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" + integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA== + base64-js@1.3.1, base64-js@^1.0.2, base64-js@^1.2.0, base64-js@^1.3.0, base64-js@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== -base64-js@^1.1.2: +base64-js@^1.1.2, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -11667,7 +11702,12 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== -binary-search@^1.3.3: +binary-extensions@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +binary-search@^1.3.3, binary-search@^1.3.5: version "1.3.6" resolved "https://registry.yarnpkg.com/binary-search/-/binary-search-1.3.6.tgz#e32426016a0c5092f0f3598836a1c7da3560565c" integrity sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA== @@ -12291,6 +12331,11 @@ camelcase@5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== +camelcase@6: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + camelcase@^2.0.0, camelcase@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" @@ -12479,7 +12524,7 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -charenc@~0.0.1: +charenc@0.0.2, charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= @@ -13405,7 +13450,7 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -crypt@~0.0.1: +crypt@0.0.2, crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= @@ -14648,6 +14693,14 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +digest-fetch@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/digest-fetch/-/digest-fetch-1.3.0.tgz#898e69264d00012a23cf26e8a3e40320143fc661" + integrity sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA== + dependencies: + base-64 "^0.1.0" + md5 "^2.3.0" + dir-glob@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" @@ -15945,6 +15998,11 @@ event-emitter@^0.3.5, event-emitter@~0.3.5: d "1" es5-ext "~0.10.14" +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + eventemitter-asyncresource@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz#734ff2e44bf448e627f7748f905d6bdd57bdb65b" @@ -15955,7 +16013,7 @@ eventemitter2@6.4.7: resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d" integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg== -eventemitter3@^4.0.0: +eventemitter3@^4.0.0, eventemitter3@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== @@ -16123,6 +16181,11 @@ expose-loader@^0.7.5: resolved "https://registry.yarnpkg.com/expose-loader/-/expose-loader-0.7.5.tgz#e29ea2d9aeeed3254a3faa1b35f502db9f9c3f6f" integrity sha512-iPowgKUZkTPX5PznYsmifVj9Bob0w2wTHVkt/eYNPSzyebkUgIedmskf/kcfEIWpiWjg3JRjnW+a17XypySMuw== +expr-eval@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expr-eval/-/expr-eval-2.0.2.tgz#fa6f044a7b0c93fde830954eb9c5b0f7fbc7e201" + integrity sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg== + express@^4.17.1, express@^4.17.3: version "4.17.3" resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" @@ -16780,6 +16843,11 @@ fork-ts-checker-webpack-plugin@^6.0.4: semver "^7.3.2" tapable "^1.0.0" +form-data-encoder@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040" + integrity sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A== + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -16812,6 +16880,14 @@ format@^0.2.0: resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= +formdata-node@^4.3.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2" + integrity sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ== + dependencies: + node-domexception "1.0.0" + web-streams-polyfill "4.0.0-beta.3" + formdata-polyfill@^4.0.10: version "4.0.10" resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" @@ -18647,6 +18723,11 @@ is-alphanumerical@^1.0.0: is-alphabetical "^1.0.0" is-decimal "^1.0.0" +is-any-array@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-any-array/-/is-any-array-2.0.1.tgz#9233242a9c098220290aa2ec28f82ca7fa79899e" + integrity sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ== + is-arguments@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" @@ -18690,7 +18771,7 @@ is-boolean-object@^1.0.1, is-boolean-object@^1.1.0: dependencies: call-bind "^1.0.0" -is-buffer@^1.1.5, is-buffer@~1.1.1: +is-buffer@^1.1.5, is-buffer@~1.1.1, is-buffer@~1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -20091,6 +20172,13 @@ js-string-escape@^1.0.1: resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= +js-tiktoken@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/js-tiktoken/-/js-tiktoken-1.0.7.tgz#56933fcd2093e8304060dfde3071bda91812e6f5" + integrity sha512-biba8u/clw7iesNEWLOLwrNGoBP2lA+hTaBLs/D45pJdUPFXyxD6nhcDVtADChghv4GgyAiMKYMiRx7x6h7Biw== + dependencies: + base64-js "^1.5.1" + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -20287,6 +20375,11 @@ jsonparse@^1.2.0: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= +jsonpointer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" + integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== + jsonwebtoken@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz#d0faf9ba1cc3a56255fe49c0961a67e520c1926d" @@ -20456,6 +20549,44 @@ kuler@^2.0.0: resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== +langchain@^0.0.132: + version "0.0.132" + resolved "https://registry.yarnpkg.com/langchain/-/langchain-0.0.132.tgz#2cdcc5d7078c70aa403f7eaeff3556c50a485632" + integrity sha512-gXnuiAhsQQqXheKQiaSmFa9s3S/Yhkkb9OCytu04OE0ecttvVvfjjqIoNVS9vor8V7kRUgYPKHJsMz2UFDoJNw== + dependencies: + "@anthropic-ai/sdk" "^0.5.7" + ansi-styles "^5.0.0" + binary-extensions "^2.2.0" + camelcase "6" + decamelize "^1.2.0" + expr-eval "^2.0.2" + flat "^5.0.2" + js-tiktoken "^1.0.7" + js-yaml "^4.1.0" + jsonpointer "^5.0.1" + langsmith "~0.0.16" + ml-distance "^4.0.0" + object-hash "^3.0.0" + openai "^3.3.0" + openapi-types "^12.1.3" + p-queue "^6.6.2" + p-retry "4" + uuid "^9.0.0" + yaml "^2.2.1" + zod "^3.21.4" + zod-to-json-schema "^3.20.4" + +langsmith@~0.0.16: + version "0.0.26" + resolved "https://registry.yarnpkg.com/langsmith/-/langsmith-0.0.26.tgz#a63f911a3113860de5488392a46468d1b482e3ef" + integrity sha512-TecBjdgYGMxNaWp2L2X0OVgu8lge2WeQ5UpDXluwF3x+kH/WHFVSuR1RCuP+k2628GSVFvXxVIyXvzrHYxrZSw== + dependencies: + "@types/uuid" "^9.0.1" + commander "^10.0.1" + p-queue "^6.6.2" + p-retry "4" + uuid "^9.0.0" + language-subtag-registry@~0.3.2: version "0.3.21" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" @@ -21341,6 +21472,15 @@ md5@^2.1.0: crypt "~0.0.1" is-buffer "~1.1.1" +md5@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" + integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== + dependencies: + charenc "0.0.2" + crypt "0.0.2" + is-buffer "~1.1.6" + mdast-squeeze-paragraphs@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97" @@ -21991,6 +22131,42 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +ml-array-mean@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/ml-array-mean/-/ml-array-mean-1.1.6.tgz#d951a700dc8e3a17b3e0a583c2c64abd0c619c56" + integrity sha512-MIdf7Zc8HznwIisyiJGRH9tRigg3Yf4FldW8DxKxpCCv/g5CafTw0RRu51nojVEOXuCQC7DRVVu5c7XXO/5joQ== + dependencies: + ml-array-sum "^1.1.6" + +ml-array-sum@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/ml-array-sum/-/ml-array-sum-1.1.6.tgz#d1d89c20793cd29c37b09d40e85681aa4515a955" + integrity sha512-29mAh2GwH7ZmiRnup4UyibQZB9+ZLyMShvt4cH4eTK+cL2oEMIZFnSyB3SS8MlsTh6q/w/yh48KmqLxmovN4Dw== + dependencies: + is-any-array "^2.0.0" + +ml-distance-euclidean@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ml-distance-euclidean/-/ml-distance-euclidean-2.0.0.tgz#3a668d236649d1b8fec96380b9435c6f42c9a817" + integrity sha512-yC9/2o8QF0A3m/0IXqCTXCzz2pNEzvmcE/9HFKOZGnTjatvBbsn4lWYJkxENkA4Ug2fnYl7PXQxnPi21sgMy/Q== + +ml-distance@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/ml-distance/-/ml-distance-4.0.1.tgz#4741d17a1735888c5388823762271dfe604bd019" + integrity sha512-feZ5ziXs01zhyFUUUeZV5hwc0f5JW0Sh0ckU1koZe/wdVkJdGxcP06KNQuF0WBTj8FttQUzcvQcpcrOp/XrlEw== + dependencies: + ml-array-mean "^1.1.6" + ml-distance-euclidean "^2.0.0" + ml-tree-similarity "^1.0.0" + +ml-tree-similarity@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ml-tree-similarity/-/ml-tree-similarity-1.0.0.tgz#24705a107e32829e24d945e87219e892159c53f0" + integrity sha512-XJUyYqjSuUQkNQHMscr6tcjldsOoAekxADTplt40QKfwW6nd++1wHWV9AArl0Zvw/TIHgNaZZNvr8QGvE8wLRg== + dependencies: + binary-search "^1.3.5" + num-sort "^2.0.0" + mocha-junit-reporter@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-2.0.2.tgz#d521689b651dc52f52044739f8ffb368be415731" @@ -22458,7 +22634,7 @@ node-dir@^0.1.10: dependencies: minimatch "^3.0.2" -node-domexception@^1.0.0: +node-domexception@1.0.0, node-domexception@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== @@ -22764,6 +22940,11 @@ null-loader@^3.0.0: loader-utils "^1.2.3" schema-utils "^1.0.0" +num-sort@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/num-sort/-/num-sort-2.1.0.tgz#1cbb37aed071329fdf41151258bc011898577a9b" + integrity sha512-1MQz1Ed8z2yckoBeSfkQHHO9K1yDRxxtotKSJ9yvcTUUxSvfvzEq5GwBrjjHEpMlq/k5gvXdmJ1SbYxWtpNoVg== + num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" @@ -22841,6 +23022,11 @@ object-hash@^1.3.0, object-hash@^1.3.1: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + object-identity-map@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/object-identity-map/-/object-identity-map-1.0.2.tgz#2b4213a4285ca3a8cd2e696782c9964f887524e7" @@ -23047,6 +23233,11 @@ openapi-types@^10.0.0: resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-10.0.0.tgz#0debbf663b2feed0322030b5b7c9080804076934" integrity sha512-Y8xOCT2eiKGYDzMW9R4x5cmfc3vGaaI4EL2pwhDmodWw1HlK18YcZ4uJxc7Rdp7/gGzAygzH9SXr6GKYIXbRcQ== +openapi-types@^12.1.3: + version "12.1.3" + resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.3.tgz#471995eb26c4b97b7bd356aacf7b91b73e777dd3" + integrity sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw== + opener@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" @@ -23274,11 +23465,27 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" +p-queue@^6.6.2: + version "6.6.2" + resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426" + integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ== + dependencies: + eventemitter3 "^4.0.4" + p-timeout "^3.2.0" + p-reflect@2.1.0, p-reflect@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-reflect/-/p-reflect-2.1.0.tgz#5d67c7b3c577c4e780b9451fc9129675bd99fe67" integrity sha512-paHV8NUz8zDHu5lhr/ngGWQiW067DK/+IbJ+RfZ4k+s8y4EKyYCz8pGYWjxCg35eHztpJAt+NUgvN4L+GCbPlg== +p-retry@4: + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== + dependencies: + "@types/retry" "0.12.0" + retry "^0.13.1" + p-retry@^4.2.0, p-retry@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.5.0.tgz#6685336b3672f9ee8174d3769a660cb5e488521d" @@ -23302,6 +23509,13 @@ p-timeout@^2.0.1: dependencies: p-finally "^1.0.0" +p-timeout@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" + integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== + dependencies: + p-finally "^1.0.0" + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -26201,6 +26415,11 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -30062,11 +30281,21 @@ web-namespaces@^1.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== +web-streams-polyfill@4.0.0-beta.3: + version "4.0.0-beta.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38" + integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug== + web-streams-polyfill@^3.0.3, web-streams-polyfill@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA== +web-streams-polyfill@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + web-streams-polyfill@~3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz#f49e487eedeca47a207c1aee41ee5578f884b42f" @@ -30726,7 +30955,7 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yaml@^2.2.2: +yaml@^2.2.1, yaml@^2.2.2: version "2.3.1" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== @@ -30886,6 +31115,11 @@ zip-stream@^4.1.0: compress-commons "^4.1.0" readable-stream "^3.6.0" +zod-to-json-schema@^3.20.4: + version "3.21.4" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.21.4.tgz#de97c5b6d4a25e9d444618486cb55c0c7fb949fd" + integrity sha512-fjUZh4nQ1s6HMccgIeE0VP4QG/YRGPmyjO9sAh890aQKPEk3nqbfUXhMFaC+Dr5KvYBm8BCyvfpZf2jY9aGSsw== + zod@^3.21.4: version "3.21.4" resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" From 94b947e625b4fdbb2affb8e6e9d8507f639d3ac6 Mon Sep 17 00:00:00 2001 From: Philippe Oberti <philippe.oberti@elastic.co> Date: Mon, 28 Aug 2023 18:32:49 +0200 Subject: [PATCH 25/49] [Security Solution] expandable flyout - fix topN opening with Raw Events instead of Detection Alerts + add missing interaction in cell actions (#164923) --- .../left/components/entities_details.tsx | 6 ++--- .../left/components/host_details.test.tsx | 1 + .../flyout/left/components/host_details.tsx | 20 +++++++++++----- .../left/components/user_details.test.tsx | 1 + .../flyout/left/components/user_details.tsx | 20 +++++++++++----- .../components/alert_reason_preview.tsx | 6 ++--- .../components/highlighted_fields.test.tsx | 3 +++ .../right/components/highlighted_fields.tsx | 23 ++++++++++++++----- .../flyout/right/components/severity.test.tsx | 4 ++++ .../flyout/right/components/severity.tsx | 9 +++++--- .../public/flyout/right/components/status.tsx | 7 ++++-- .../utils/highlighted_fields_helpers.test.ts | 8 +++++-- .../utils/highlighted_fields_helpers.ts | 5 +++- 13 files changed, 81 insertions(+), 32 deletions(-) diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx b/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx index 40a3f1823f4d3..29e748dd70eae 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx @@ -19,7 +19,7 @@ export const ENTITIES_TAB_ID = 'entities-details'; * Entities displayed in the document details expandable flyout left section under the Insights tab */ export const EntitiesDetails: React.FC = () => { - const { getFieldsData } = useLeftPanelContext(); + const { getFieldsData, scopeId } = useLeftPanelContext(); const hostName = getField(getFieldsData('host.name')); const userName = getField(getFieldsData('user.name')); const timestamp = getField(getFieldsData('@timestamp')); @@ -28,12 +28,12 @@ export const EntitiesDetails: React.FC = () => { <EuiFlexGroup direction="column" gutterSize="m" data-test-subj={ENTITIES_DETAILS_TEST_ID}> {userName && timestamp && ( <EuiFlexItem> - <UserDetails userName={userName} timestamp={timestamp} /> + <UserDetails userName={userName} timestamp={timestamp} scopeId={scopeId} /> </EuiFlexItem> )} {hostName && timestamp && ( <EuiFlexItem> - <HostDetails hostName={hostName} timestamp={timestamp} /> + <HostDetails hostName={hostName} timestamp={timestamp} scopeId={scopeId} /> </EuiFlexItem> )} </EuiFlexGroup> diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/host_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/left/components/host_details.test.tsx index 4ee515e539442..bbec7d1d4d169 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/components/host_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/left/components/host_details.test.tsx @@ -91,6 +91,7 @@ const timestamp = '2022-07-25T08:20:18.966Z'; const defaultProps = { hostName: 'test host', timestamp, + scopeId: 'scopeId', }; const mockHostDetailsResponse = [ diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/host_details.tsx b/x-pack/plugins/security_solution/public/flyout/left/components/host_details.tsx index 8382e13e6fcc6..c2f9d263ff560 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/components/host_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/left/components/host_details.tsx @@ -20,6 +20,7 @@ import { EuiPanel, } from '@elastic/eui'; import type { EuiBasicTableColumn } from '@elastic/eui'; +import { getSourcererScopeId } from '../../../helpers'; import { ExpandablePanel } from '../../shared/components/expandable_panel'; import type { RelatedUser } from '../../../../common/search_strategy/security_solution/related_entities/related_users'; import type { RiskSeverity } from '../../../../common/search_strategy'; @@ -67,11 +68,16 @@ export interface HostDetailsProps { * timestamp of alert or event */ timestamp: string; + /** + * Maintain backwards compatibility // TODO remove when possible + */ + scopeId: string; } + /** * Host details and related users, displayed in the document details expandable flyout left section under the Insights tab, Entities tab */ -export const HostDetails: React.FC<HostDetailsProps> = ({ hostName, timestamp }) => { +export const HostDetails: React.FC<HostDetailsProps> = ({ hostName, timestamp, scopeId }) => { const { to, from, deleteQuery, setQuery, isInitializing } = useGlobalTime(); const { selectedPatterns } = useSourcererDataView(); const dispatch = useDispatch(); @@ -126,14 +132,16 @@ export const HostDetails: React.FC<HostDetailsProps> = ({ hostName, timestamp }) render: (user: string) => ( <EuiText grow={false} size="xs"> <SecurityCellActions - mode={CellActionsMode.HOVER_RIGHT} - visibleCellActions={5} - showActionTooltips - triggerId={SecurityCellActionsTrigger.DEFAULT} data={{ field: 'user.name', value: user, }} + mode={CellActionsMode.HOVER_RIGHT} + triggerId={SecurityCellActionsTrigger.DEFAULT} // TODO use SecurityCellActionsTrigger.DETAILS_FLYOUT when https://github.com/elastic/kibana/issues/155243 is fixed + visibleCellActions={5} // TODO use 6 when https://github.com/elastic/kibana/issues/155243 is fixed + sourcererScopeId={getSourcererScopeId(scopeId)} + metadata={{ scopeId }} + showActionTooltips > {user} </SecurityCellActions> @@ -180,7 +188,7 @@ export const HostDetails: React.FC<HostDetailsProps> = ({ hostName, timestamp }) ] : []), ], - [isEntityAnalyticsAuthorized] + [isEntityAnalyticsAuthorized, scopeId] ); const relatedUsersCount = useMemo( diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/user_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/left/components/user_details.test.tsx index 51eaf1bb76b74..296ae53fc779a 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/components/user_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/left/components/user_details.test.tsx @@ -88,6 +88,7 @@ const timestamp = '2022-07-25T08:20:18.966Z'; const defaultProps = { userName: 'test user', timestamp, + scopeId: 'scopeId', }; const mockUserDetailsResponse = [ diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/user_details.tsx b/x-pack/plugins/security_solution/public/flyout/left/components/user_details.tsx index 9e218c7ac94fb..9437858ca211d 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/components/user_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/left/components/user_details.tsx @@ -20,6 +20,7 @@ import { EuiPanel, } from '@elastic/eui'; import type { EuiBasicTableColumn } from '@elastic/eui'; +import { getSourcererScopeId } from '../../../helpers'; import { ExpandablePanel } from '../../shared/components/expandable_panel'; import type { RelatedHost } from '../../../../common/search_strategy/security_solution/related_entities/related_hosts'; import type { RiskSeverity } from '../../../../common/search_strategy'; @@ -67,11 +68,16 @@ export interface UserDetailsProps { * timestamp of alert or event */ timestamp: string; + /** + * Maintain backwards compatibility // TODO remove when possible + */ + scopeId: string; } + /** * User details and related users, displayed in the document details expandable flyout left section under the Insights tab, Entities tab */ -export const UserDetails: React.FC<UserDetailsProps> = ({ userName, timestamp }) => { +export const UserDetails: React.FC<UserDetailsProps> = ({ userName, timestamp, scopeId }) => { const { to, from, deleteQuery, setQuery, isInitializing } = useGlobalTime(); const { selectedPatterns } = useSourcererDataView(); const dispatch = useDispatch(); @@ -127,14 +133,16 @@ export const UserDetails: React.FC<UserDetailsProps> = ({ userName, timestamp }) render: (host: string) => ( <EuiText grow={false} size="xs"> <SecurityCellActions - mode={CellActionsMode.HOVER_RIGHT} - visibleCellActions={5} - showActionTooltips - triggerId={SecurityCellActionsTrigger.DEFAULT} data={{ value: host, field: 'host.name', }} + mode={CellActionsMode.HOVER_RIGHT} + triggerId={SecurityCellActionsTrigger.DEFAULT} // TODO use SecurityCellActionsTrigger.DETAILS_FLYOUT when https://github.com/elastic/kibana/issues/155243 is fixed + visibleCellActions={5} // TODO use 6 when https://github.com/elastic/kibana/issues/155243 is fixed + sourcererScopeId={getSourcererScopeId(scopeId)} + metadata={{ scopeId }} + showActionTooltips > {host} </SecurityCellActions> @@ -181,7 +189,7 @@ export const UserDetails: React.FC<UserDetailsProps> = ({ userName, timestamp }) ] : []), ], - [isEntityAnalyticsAuthorized] + [isEntityAnalyticsAuthorized, scopeId] ); const relatedHostsCount = useMemo( diff --git a/x-pack/plugins/security_solution/public/flyout/preview/components/alert_reason_preview.tsx b/x-pack/plugins/security_solution/public/flyout/preview/components/alert_reason_preview.tsx index d8791beb7bfd2..985c2bb288fa2 100644 --- a/x-pack/plugins/security_solution/public/flyout/preview/components/alert_reason_preview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/preview/components/alert_reason_preview.tsx @@ -26,7 +26,7 @@ const ReasonPreviewContainer = styled.div``; * Alert reason renderer on a preview panel on top of the right section of expandable flyout */ export const AlertReasonPreview: React.FC = () => { - const { dataAsNestedObject } = usePreviewPanelContext(); + const { dataAsNestedObject, scopeId } = usePreviewPanelContext(); const renderer = useMemo( () => @@ -43,10 +43,10 @@ export const AlertReasonPreview: React.FC = () => { contextId: 'event-details', data: dataAsNestedObject, isDraggable: false, - scopeId: 'global', + scopeId, }) : null, - [renderer, dataAsNestedObject] + [renderer, dataAsNestedObject, scopeId] ); if (!dataAsNestedObject || !renderer) { diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/highlighted_fields.test.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/highlighted_fields.test.tsx index 0d8ed18d83a43..5ae89154a05f2 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/highlighted_fields.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/highlighted_fields.test.tsx @@ -26,6 +26,7 @@ describe('<HighlightedFields />', () => { it('should render the component', () => { const panelContextValue = { dataFormattedForFieldBrowser: mockDataFormattedForFieldBrowser, + scopeId: 'scopeId', } as unknown as RightPanelContext; (useHighlightedFields as jest.Mock).mockReturnValue({ field: { @@ -48,6 +49,7 @@ describe('<HighlightedFields />', () => { it(`should render empty component if there aren't any highlighted fields`, () => { const panelContextValue = { dataFormattedForFieldBrowser: mockDataFormattedForFieldBrowser, + scopeId: 'scopeId', } as unknown as RightPanelContext; (useHighlightedFields as jest.Mock).mockReturnValue({}); @@ -63,6 +65,7 @@ describe('<HighlightedFields />', () => { it('should render empty component if dataFormattedForFieldBrowser is null', () => { const panelContextValue = { dataFormattedForFieldBrowser: null, + scopeId: 'scopeId', } as unknown as RightPanelContext; (useHighlightedFields as jest.Mock).mockReturnValue({ field: { diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/highlighted_fields.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/highlighted_fields.tsx index 79f75ba7ff861..908df4590aad2 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/highlighted_fields.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/highlighted_fields.tsx @@ -9,6 +9,7 @@ import type { FC } from 'react'; import React, { useMemo } from 'react'; import type { EuiBasicTableColumn } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiInMemoryTable, EuiPanel, EuiTitle } from '@elastic/eui'; +import { getSourcererScopeId } from '../../../helpers'; import { convertHighlightedFieldsToTableRow } from '../../shared/utils/highlighted_fields_helpers'; import { useRuleWithFallback } from '../../../detection_engine/rule_management/logic/use_rule_with_fallback'; import { useBasicDataFromDetailsData } from '../../../timelines/components/side_panel/event_details/helpers'; @@ -41,6 +42,10 @@ export interface HighlightedFieldsTableRow { * Highlighted field value */ values: string[] | null | undefined; + /** + * Maintain backwards compatibility // TODO remove when possible + */ + scopeId: string; }; } @@ -54,15 +59,21 @@ const columns: Array<EuiBasicTableColumn<HighlightedFieldsTableRow>> = [ field: 'description', name: HIGHLIGHTED_FIELDS_VALUE_COLUMN, 'data-test-subj': 'valueCell', - render: (description: { field: string; values: string[] | null | undefined }) => ( + render: (description: { + field: string; + values: string[] | null | undefined; + scopeId: string; + }) => ( <SecurityCellActions data={{ field: description.field, value: description.values, }} mode={CellActionsMode.HOVER_RIGHT} - triggerId={SecurityCellActionsTrigger.DEFAULT} - visibleCellActions={6} + triggerId={SecurityCellActionsTrigger.DEFAULT} // TODO use SecurityCellActionsTrigger.DETAILS_FLYOUT when https://github.com/elastic/kibana/issues/155243 is fixed + visibleCellActions={5} // TODO use 6 when https://github.com/elastic/kibana/issues/155243 is fixed + sourcererScopeId={getSourcererScopeId(description.scopeId)} + metadata={{ scopeId: description.scopeId }} > <HighlightedFieldsCell values={description.values} field={description.field} /> </SecurityCellActions> @@ -74,7 +85,7 @@ const columns: Array<EuiBasicTableColumn<HighlightedFieldsTableRow>> = [ * Component that displays the highlighted fields in the right panel under the Investigation section. */ export const HighlightedFields: FC = () => { - const { dataFormattedForFieldBrowser } = useRightPanelContext(); + const { dataFormattedForFieldBrowser, scopeId } = useRightPanelContext(); const { ruleId } = useBasicDataFromDetailsData(dataFormattedForFieldBrowser); const { rule: maybeRule } = useRuleWithFallback(ruleId); @@ -83,8 +94,8 @@ export const HighlightedFields: FC = () => { investigationFields: maybeRule?.investigation_fields ?? [], }); const items = useMemo( - () => convertHighlightedFieldsToTableRow(highlightedFields), - [highlightedFields] + () => convertHighlightedFieldsToTableRow(highlightedFields, scopeId), + [highlightedFields, scopeId] ); if (!dataFormattedForFieldBrowser || items.length === 0) { diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/severity.test.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/severity.test.tsx index ed56178531de6..d599236b4531d 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/severity.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/severity.test.tsx @@ -20,6 +20,7 @@ describe('<DocumentSeverity />', () => { it('should render severity information', () => { const contextValue = { getFieldsData: jest.fn().mockImplementation(mockGetFieldsData), + scopeId: 'scopeId', } as unknown as RightPanelContext; const { getByTestId } = render( @@ -39,6 +40,7 @@ describe('<DocumentSeverity />', () => { it('should render empty component if missing getFieldsData value', () => { const contextValue = { getFieldsData: jest.fn(), + scopeId: 'scopeId', } as unknown as RightPanelContext; const { container } = render( @@ -53,6 +55,7 @@ describe('<DocumentSeverity />', () => { it('should render empty component if getFieldsData is invalid array', () => { const contextValue = { getFieldsData: jest.fn().mockImplementation(() => ['abc']), + scopeId: 'scopeId', } as unknown as RightPanelContext; const { container } = render( @@ -67,6 +70,7 @@ describe('<DocumentSeverity />', () => { it('should render empty component if getFieldsData is invalid string', () => { const contextValue = { getFieldsData: jest.fn().mockImplementation(() => 'abc'), + scopeId: 'scopeId', } as unknown as RightPanelContext; const { container } = render( diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/severity.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/severity.tsx index 9059b24a6fd2b..c5f49400f088c 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/severity.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/severity.tsx @@ -11,6 +11,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import { ALERT_SEVERITY } from '@kbn/rule-data-utils'; import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; import { CellActionsMode } from '@kbn/cell-actions'; +import { getSourcererScopeId } from '../../../helpers'; import { SecurityCellActions } from '../../../common/components/cell_actions'; import { SecurityCellActionsTrigger } from '../../../actions/constants'; import { SEVERITY_TITLE } from './translations'; @@ -25,7 +26,7 @@ const isSeverity = (x: unknown): x is Severity => * Document details severity displayed in flyout right section header */ export const DocumentSeverity: FC = memo(() => { - const { getFieldsData } = useRightPanelContext(); + const { getFieldsData, scopeId } = useRightPanelContext(); const fieldsData = getFieldsData(ALERT_SEVERITY); if (!fieldsData) { @@ -55,8 +56,10 @@ export const DocumentSeverity: FC = memo(() => { value: alertSeverity, }} mode={CellActionsMode.HOVER_RIGHT} - triggerId={SecurityCellActionsTrigger.DEFAULT} - visibleCellActions={6} + triggerId={SecurityCellActionsTrigger.DEFAULT} // TODO use SecurityCellActionsTrigger.DETAILS_FLYOUT when https://github.com/elastic/kibana/issues/155243 is fixed + visibleCellActions={5} // TODO use 6 when https://github.com/elastic/kibana/issues/155243 is fixed + sourcererScopeId={getSourcererScopeId(scopeId)} + metadata={{ scopeId }} > <SeverityBadge value={alertSeverity} /> </SecurityCellActions> diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/status.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/status.tsx index dacb68435fcb1..fa3a0c6f2ab14 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/status.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/status.tsx @@ -10,6 +10,7 @@ import React, { useMemo } from 'react'; import { find } from 'lodash/fp'; import { useExpandableFlyoutContext } from '@kbn/expandable-flyout'; import { CellActionsMode } from '@kbn/cell-actions'; +import { getSourcererScopeId } from '../../../helpers'; import { SecurityCellActions } from '../../../common/components/cell_actions'; import type { EnrichedFieldInfo, @@ -61,8 +62,10 @@ export const DocumentStatus: FC = () => { value: statusData.values[0], }} mode={CellActionsMode.HOVER_RIGHT} - triggerId={SecurityCellActionsTrigger.DEFAULT} - visibleCellActions={6} + triggerId={SecurityCellActionsTrigger.DEFAULT} // TODO use SecurityCellActionsTrigger.DETAILS_FLYOUT when https://github.com/elastic/kibana/issues/155243 is fixed + visibleCellActions={5} // TODO use 6 when https://github.com/elastic/kibana/issues/155243 is fixed + sourcererScopeId={getSourcererScopeId(scopeId)} + metadata={{ scopeId }} > <StatusPopoverButton eventId={eventId} diff --git a/x-pack/plugins/security_solution/public/flyout/shared/utils/highlighted_fields_helpers.test.ts b/x-pack/plugins/security_solution/public/flyout/shared/utils/highlighted_fields_helpers.test.ts index f79a7a300eb3e..ec92745455e21 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/utils/highlighted_fields_helpers.test.ts +++ b/x-pack/plugins/security_solution/public/flyout/shared/utils/highlighted_fields_helpers.test.ts @@ -10,6 +10,8 @@ import { convertHighlightedFieldsToTableRow, } from './highlighted_fields_helpers'; +const scopeId = 'scopeId'; + describe('convertHighlightedFieldsToTableRow', () => { it('should convert highlighted fields to a table row', () => { const highlightedFields = { @@ -17,12 +19,13 @@ describe('convertHighlightedFieldsToTableRow', () => { values: ['host-1'], }, }; - expect(convertHighlightedFieldsToTableRow(highlightedFields)).toEqual([ + expect(convertHighlightedFieldsToTableRow(highlightedFields, scopeId)).toEqual([ { field: 'host.name', description: { field: 'host.name', values: ['host-1'], + scopeId: 'scopeId', }, }, ]); @@ -35,12 +38,13 @@ describe('convertHighlightedFieldsToTableRow', () => { values: ['host-1'], }, }; - expect(convertHighlightedFieldsToTableRow(highlightedFields)).toEqual([ + expect(convertHighlightedFieldsToTableRow(highlightedFields, scopeId)).toEqual([ { field: 'host.name-override', description: { field: 'host.name-override', values: ['host-1'], + scopeId: 'scopeId', }, }, ]); diff --git a/x-pack/plugins/security_solution/public/flyout/shared/utils/highlighted_fields_helpers.ts b/x-pack/plugins/security_solution/public/flyout/shared/utils/highlighted_fields_helpers.ts index d44ec666a27bc..094187b570251 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/utils/highlighted_fields_helpers.ts +++ b/x-pack/plugins/security_solution/public/flyout/shared/utils/highlighted_fields_helpers.ts @@ -12,9 +12,11 @@ import type { HighlightedFieldsTableRow } from '../../right/components/highlight /** * Converts the highlighted fields to a format that can be consumed by the HighlightedFields component * @param highlightedFields + * @param scopeId */ export const convertHighlightedFieldsToTableRow = ( - highlightedFields: UseHighlightedFieldsResult + highlightedFields: UseHighlightedFieldsResult, + scopeId: string ): HighlightedFieldsTableRow[] => { const fieldNames = Object.keys(highlightedFields); return fieldNames.map((fieldName) => { @@ -27,6 +29,7 @@ export const convertHighlightedFieldsToTableRow = ( description: { field, values, + scopeId, }, }; }); From 4f81a3750247444ac129bf8f02a924c1bf30fe0b Mon Sep 17 00:00:00 2001 From: Philippe Oberti <philippe.oberti@elastic.co> Date: Mon, 28 Aug 2023 18:35:44 +0200 Subject: [PATCH 26/49] [Security Solution] expandable flyout - fix incorrect logic to show/hide the share alert button (#164990) --- .../right/components/header_title.test.tsx | 95 ++++--------------- .../flyout/right/components/header_title.tsx | 16 +++- 2 files changed, 31 insertions(+), 80 deletions(-) diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/header_title.test.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/header_title.test.tsx index 6d132ce54501e..3256d3c3895cd 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/header_title.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/header_title.test.tsx @@ -23,16 +23,23 @@ import { useDateFormat, useTimeZone } from '../../../common/lib/kibana'; import { mockDataFormattedForFieldBrowser, mockGetFieldsData } from '../mocks/mock_context'; import { useAssistant } from '../hooks/use_assistant'; import { TestProvidersComponent } from '../../../common/mock'; +import { useGetAlertDetailsFlyoutLink } from '../../../timelines/components/side_panel/event_details/use_get_alert_details_flyout_link'; jest.mock('../../../common/lib/kibana'); jest.mock('../hooks/use_assistant'); +jest.mock( + '../../../timelines/components/side_panel/event_details/use_get_alert_details_flyout_link' +); moment.suppressDeprecationWarnings = true; moment.tz.setDefault('UTC'); const dateFormat = 'MMM D, YYYY @ HH:mm:ss.SSS'; - const flyoutContextValue = {} as unknown as ExpandableFlyoutContext; +const mockContextValue = { + dataFormattedForFieldBrowser: mockDataFormattedForFieldBrowser, + getFieldsData: jest.fn().mockImplementation(mockGetFieldsData), +} as unknown as RightPanelContext; const renderHeader = (contextValue: RightPanelContext) => render( @@ -50,15 +57,11 @@ describe('<HeaderTitle />', () => { jest.mocked(useDateFormat).mockImplementation(() => dateFormat); jest.mocked(useTimeZone).mockImplementation(() => 'UTC'); jest.mocked(useAssistant).mockReturnValue({ showAssistant: true, promptContextId: '' }); + jest.mocked(useGetAlertDetailsFlyoutLink).mockReturnValue('url'); }); it('should render component', () => { - const contextValue = { - dataFormattedForFieldBrowser: mockDataFormattedForFieldBrowser, - getFieldsData: jest.fn().mockImplementation(mockGetFieldsData), - } as unknown as RightPanelContext; - - const { getByTestId } = renderHeader(contextValue); + const { getByTestId } = renderHeader(mockContextValue); expect(getByTestId(FLYOUT_HEADER_TITLE_TEST_ID)).toBeInTheDocument(); expect(getByTestId(FLYOUT_HEADER_RISK_SCORE_VALUE_TEST_ID)).toBeInTheDocument(); @@ -66,101 +69,42 @@ describe('<HeaderTitle />', () => { }); it('should render rule name in the title if document is an alert', () => { - const contextValue = { - dataFormattedForFieldBrowser: [ - { - category: 'kibana', - field: 'kibana.alert.rule.uuid', - values: ['123'], - originalValue: ['123'], - isObjectArray: false, - }, - { - category: 'kibana', - field: 'kibana.alert.rule.name', - values: ['test'], - originalValue: ['test'], - isObjectArray: false, - }, - ], - getFieldsData: () => [], - } as unknown as RightPanelContext; + const { getByTestId } = renderHeader(mockContextValue); - const { getByTestId } = renderHeader(contextValue); - - expect(getByTestId(FLYOUT_HEADER_TITLE_TEST_ID)).toHaveTextContent('test'); + expect(getByTestId(FLYOUT_HEADER_TITLE_TEST_ID)).toHaveTextContent('rule-name'); }); - it('should render share button in the title if document is an alert with url info', () => { - const contextValue = { - dataFormattedForFieldBrowser: [ - { - category: 'kibana', - field: 'kibana.alert.rule.uuid', - values: ['123'], - originalValue: ['123'], - isObjectArray: false, - }, - { - category: 'kibana', - field: 'kibana.alert.url', - values: ['http://kibana.url/alert/id'], - originalValue: ['http://kibana.url/alert/id'], - isObjectArray: false, - }, - ], - getFieldsData: () => [], - } as unknown as RightPanelContext; - - const { getByTestId } = renderHeader(contextValue); + it('should render share button in the title', () => { + const { getByTestId } = renderHeader(mockContextValue); expect(getByTestId(FLYOUT_HEADER_SHARE_BUTTON_TEST_ID)).toBeInTheDocument(); }); it('should not render share button in the title if alert is missing url info', () => { - const contextValue = { - dataFormattedForFieldBrowser: [ - { - category: 'kibana', - field: 'kibana.alert.rule.uuid', - values: ['123'], - originalValue: ['123'], - isObjectArray: false, - }, - ], - getFieldsData: () => [], - } as unknown as RightPanelContext; + jest.mocked(useGetAlertDetailsFlyoutLink).mockReturnValue(null); - const { queryByTestId } = renderHeader(contextValue); + const { queryByTestId } = renderHeader(mockContextValue); expect(queryByTestId(FLYOUT_HEADER_SHARE_BUTTON_TEST_ID)).not.toBeInTheDocument(); }); it('should render chat button in the title', () => { - const contextValue = { - dataFormattedForFieldBrowser: [], - getFieldsData: () => [], - } as unknown as RightPanelContext; - - const { getByTestId } = renderHeader(contextValue); + const { getByTestId } = renderHeader(mockContextValue); expect(getByTestId(FLYOUT_HEADER_CHAT_BUTTON_TEST_ID)).toBeInTheDocument(); }); it('should not render chat button in the title if should not be shown', () => { jest.mocked(useAssistant).mockReturnValue({ showAssistant: false, promptContextId: '' }); - const contextValue = { - dataFormattedForFieldBrowser: [], - getFieldsData: () => [], - } as unknown as RightPanelContext; - const { queryByTestId } = renderHeader(contextValue); + const { queryByTestId } = renderHeader(mockContextValue); expect(queryByTestId(FLYOUT_HEADER_CHAT_BUTTON_TEST_ID)).not.toBeInTheDocument(); }); it('should render default document detail title if document is not an alert', () => { const contextValue = { + ...mockContextValue, dataFormattedForFieldBrowser: [ { category: 'kibana', @@ -170,7 +114,6 @@ describe('<HeaderTitle />', () => { isObjectArray: false, }, ], - getFieldsData: () => [], } as unknown as RightPanelContext; const { getByTestId } = renderHeader(contextValue); diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/header_title.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/header_title.tsx index bac1b3d9f1bd1..716db70b60947 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/header_title.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/header_title.tsx @@ -11,6 +11,7 @@ import { NewChatById } from '@kbn/elastic-assistant'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui'; import { isEmpty } from 'lodash'; import { css } from '@emotion/react'; +import { useGetAlertDetailsFlyoutLink } from '../../../timelines/components/side_panel/event_details/use_get_alert_details_flyout_link'; import { DocumentStatus } from './status'; import { useAssistant } from '../hooks/use_assistant'; import { @@ -37,15 +38,22 @@ export interface HeaderTitleProps { * Document details flyout right section header */ export const HeaderTitle: VFC<HeaderTitleProps> = memo(({ flyoutIsExpandable }) => { - const { dataFormattedForFieldBrowser } = useRightPanelContext(); - const { isAlert, ruleName, timestamp, alertUrl } = useBasicDataFromDetailsData( + const { dataFormattedForFieldBrowser, eventId, indexName } = useRightPanelContext(); + const { isAlert, ruleName, timestamp } = useBasicDataFromDetailsData( dataFormattedForFieldBrowser ); + const alertDetailsLink = useGetAlertDetailsFlyoutLink({ + _id: eventId, + _index: indexName, + timestamp, + }); + + const showShareAlertButton = isAlert && alertDetailsLink; + const { showAssistant, promptContextId } = useAssistant({ dataFormattedForFieldBrowser, isAlert, }); - const showShareAlertButton = isAlert && alertUrl; return ( <> @@ -71,7 +79,7 @@ export const HeaderTitle: VFC<HeaderTitleProps> = memo(({ flyoutIsExpandable }) )} {showShareAlertButton && ( <EuiFlexItem grow={false}> - <ShareButton alertUrl={alertUrl} /> + <ShareButton alertUrl={alertDetailsLink} /> </EuiFlexItem> )} </EuiFlexGroup> From d94bd8de0df116a7529453f945a1deaa1a7c011b Mon Sep 17 00:00:00 2001 From: Philippe Oberti <philippe.oberti@elastic.co> Date: Mon, 28 Aug 2023 18:37:15 +0200 Subject: [PATCH 27/49] [Security Solution] expandable flyout - show deleted rule badge in rule preview (#164965) --- .../preview/components/rule_preview.tsx | 8 ++++++-- .../components/rule_preview_title.test.tsx | 20 ++++++++++++++++++- .../preview/components/rule_preview_title.tsx | 19 ++++++++++++++++-- .../flyout/preview/components/test_ids.ts | 2 ++ 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx b/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx index 023c214630dd4..d1595f7419aa0 100644 --- a/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx @@ -34,7 +34,11 @@ import * as i18n from './translations'; export const RulePreview: React.FC = memo(() => { const { ruleId, indexPattern } = usePreviewPanelContext(); const [rule, setRule] = useState<Rule | null>(null); - const { rule: maybeRule, loading: ruleLoading } = useRuleWithFallback(ruleId ?? ''); + const { + rule: maybeRule, + loading: ruleLoading, + isExistingRule, + } = useRuleWithFallback(ruleId ?? ''); const { data } = useKibana().services; // persist rule until refresh is complete @@ -77,7 +81,7 @@ export const RulePreview: React.FC = memo(() => { return rule ? ( <EuiPanel hasShadow={false} data-test-subj={RULE_PREVIEW_BODY_TEST_ID} className="eui-yScroll"> - <RulePreviewTitle rule={rule} /> + <RulePreviewTitle rule={rule} isSuppressed={!isExistingRule} /> <EuiHorizontalRule margin="s" /> <ExpandableSection title={i18n.RULE_PREVIEW_ABOUT_TEXT} diff --git a/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview_title.test.tsx b/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview_title.test.tsx index 589d0d4e3b456..719433051ef0c 100644 --- a/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview_title.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview_title.test.tsx @@ -16,15 +16,17 @@ import { RULE_PREVIEW_TITLE_TEST_ID, RULE_PREVIEW_RULE_CREATED_BY_TEST_ID, RULE_PREVIEW_RULE_UPDATED_BY_TEST_ID, + RULE_PREVIEW_RULE_TITLE_SUPPRESSED_TEST_ID, } from './test_ids'; const defaultProps = { rule: { id: 'id' } as Rule, + isSuppressed: false, }; describe('<RulePreviewTitle />', () => { it('should render title and its components', () => { - const { getByTestId } = render( + const { getByTestId, queryByTestId } = render( <TestProviders> <ExpandableFlyoutContext.Provider value={mockFlyoutContextValue}> <RulePreviewTitle {...defaultProps} /> @@ -34,5 +36,21 @@ describe('<RulePreviewTitle />', () => { expect(getByTestId(RULE_PREVIEW_TITLE_TEST_ID)).toBeInTheDocument(); expect(getByTestId(RULE_PREVIEW_RULE_CREATED_BY_TEST_ID)).toBeInTheDocument(); expect(getByTestId(RULE_PREVIEW_RULE_UPDATED_BY_TEST_ID)).toBeInTheDocument(); + expect(queryByTestId(RULE_PREVIEW_RULE_TITLE_SUPPRESSED_TEST_ID)).not.toBeInTheDocument(); + }); + + it('should render deleted rule badge', () => { + const props = { + ...defaultProps, + isSuppressed: true, + }; + const { getByTestId } = render( + <TestProviders> + <ExpandableFlyoutContext.Provider value={mockFlyoutContextValue}> + <RulePreviewTitle {...props} /> + </ExpandableFlyoutContext.Provider> + </TestProviders> + ); + expect(getByTestId(RULE_PREVIEW_RULE_TITLE_SUPPRESSED_TEST_ID)).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview_title.tsx b/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview_title.tsx index 8a937b5a727af..ab15265d7dc21 100644 --- a/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview_title.tsx +++ b/x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview_title.tsx @@ -4,14 +4,17 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import React from 'react'; -import { EuiTitle, EuiText, EuiSpacer, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiTitle, EuiText, EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiBadge } from '@elastic/eui'; +import { DELETED_RULE } from '../../../detection_engine/rule_details_ui/pages/rule_details/translations'; import type { Rule } from '../../../detection_engine/rule_management/logic'; import { CreatedBy, UpdatedBy } from '../../../detections/components/rules/rule_info'; import { RULE_PREVIEW_TITLE_TEST_ID, RULE_PREVIEW_RULE_CREATED_BY_TEST_ID, RULE_PREVIEW_RULE_UPDATED_BY_TEST_ID, + RULE_PREVIEW_RULE_TITLE_SUPPRESSED_TEST_ID, } from './test_ids'; interface RulePreviewTitleProps { @@ -19,17 +22,29 @@ interface RulePreviewTitleProps { * Rule object that represents relevant information about a rule */ rule: Rule; + /** + * Flag to indicate if rule is suppressed + */ + isSuppressed: boolean; } /** * Title component that shows basic information of a rule. This is displayed above rule preview body in rule preview panel */ -export const RulePreviewTitle: React.FC<RulePreviewTitleProps> = ({ rule }) => { +export const RulePreviewTitle: React.FC<RulePreviewTitleProps> = ({ rule, isSuppressed }) => { return ( <div data-test-subj={RULE_PREVIEW_TITLE_TEST_ID}> <EuiTitle> <h6>{rule.name}</h6> </EuiTitle> + {isSuppressed && ( + <> + <EuiSpacer size="s" /> + <EuiBadge data-test-subj={RULE_PREVIEW_RULE_TITLE_SUPPRESSED_TEST_ID} title=""> + {DELETED_RULE} + </EuiBadge> + </> + )} <EuiSpacer size="s" /> <EuiFlexGroup gutterSize="xs" direction="column"> <EuiFlexItem data-test-subj={RULE_PREVIEW_RULE_CREATED_BY_TEST_ID}> diff --git a/x-pack/plugins/security_solution/public/flyout/preview/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/preview/components/test_ids.ts index 764ec90fd9bdf..c9894efe905b5 100644 --- a/x-pack/plugins/security_solution/public/flyout/preview/components/test_ids.ts +++ b/x-pack/plugins/security_solution/public/flyout/preview/components/test_ids.ts @@ -10,6 +10,8 @@ import { CONTENT_TEST_ID, HEADER_TEST_ID } from '../../right/components/expandab /* Rule preview */ export const RULE_PREVIEW_TITLE_TEST_ID = 'securitySolutionDocumentDetailsFlyoutRulePreviewTitle'; +export const RULE_PREVIEW_RULE_TITLE_SUPPRESSED_TEST_ID = + 'securitySolutionDocumentDetailsFlyoutRulePreviewTitleSuppressed'; export const RULE_PREVIEW_RULE_CREATED_BY_TEST_ID = 'securitySolutionDocumentDetailsFlyoutRulePreviewCreatedByText'; export const RULE_PREVIEW_RULE_UPDATED_BY_TEST_ID = From 68a6a56eb2c482f7c2ceb30db0201b6e3d27ecd2 Mon Sep 17 00:00:00 2001 From: "Quynh Nguyen (Quinn)" <43350163+qn895@users.noreply.github.com> Date: Mon, 28 Aug 2023 12:11:44 -0500 Subject: [PATCH 28/49] [ML] Fix flaky continuous transform tests (#164940) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Initially, the failed tests occurred for `products.base_price` field in the latest transform, however, the error could happen to all other numeric fields that could appear as an integer or a float. This PR adds explicit mappings for all numeric fields. [Flaky test suite runner for functional/apps/transform/creation/index_pattern](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/2994)... sucessful after 100 runs ✅ [Flaky test suite runner for functional_basic/apps/transform/creation/index_pattern](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/3000)... ### Checklist Delete any items that are not applicable to this PR. - [ ] 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) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [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 - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] 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) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../index_pattern/continuous_transform.ts | 79 ++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/transform/creation/index_pattern/continuous_transform.ts b/x-pack/test/functional/apps/transform/creation/index_pattern/continuous_transform.ts index 0fed167afb835..a284070fa7b6b 100644 --- a/x-pack/test/functional/apps/transform/creation/index_pattern/continuous_transform.ts +++ b/x-pack/test/functional/apps/transform/creation/index_pattern/continuous_transform.ts @@ -7,7 +7,6 @@ import { TRANSFORM_STATE } from '@kbn/transform-plugin/common/constants'; -import type { MappingTypeMapping } from '@elastic/elasticsearch/lib/api/types'; import type { FtrProviderContext } from '../../../../ftr_provider_context'; import { GroupByEntry, @@ -231,13 +230,91 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { if (testData.type === 'latest') { const destIndexMappings: MappingTypeMapping = { properties: { + customer_id: { + type: 'long', + }, + day_of_week_i: { + type: 'long', + }, + order_date: { + type: 'date', + }, + order_id: { + type: 'long', + }, products: { properties: { + _id: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + ignore_above: 256, + }, + }, + }, base_price: { type: 'float', }, + base_unit_price: { + type: 'float', + }, + created_on: { + type: 'date', + }, + discount_amount: { + type: 'float', + }, + discount_percentage: { + type: 'float', + }, + min_price: { + type: 'float', + }, + price: { + type: 'float', + }, + product_id: { + type: 'long', + }, + product_name: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + ignore_above: 256, + }, + }, + }, + quantity: { + type: 'long', + }, + tax_amount: { + type: 'float', + }, + taxful_price: { + type: 'float', + }, + taxless_price: { + type: 'float', + }, + unit_discount_amount: { + type: 'float', + }, }, }, + taxful_total_price: { + type: 'float', + }, + taxless_total_price: { + type: 'float', + }, + total_quantity: { + type: 'long', + }, + total_unique_products: { + type: 'long', + }, }, }; From cb9797500a1753f9376267802e398fc9e81e2813 Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <xavier.mouligneau@elastic.co> Date: Mon, 28 Aug 2023 13:25:48 -0400 Subject: [PATCH 29/49] [RAM] update api key to become public (#164883) ## Summary [Summarize your PR. If it involves visual changes include a screenshot or gif.](https://github.com/elastic/enhancements/issues/17998) ### Checklist - [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 --------- Co-authored-by: lcawl <lcawley@elastic.co> --- .../rules/rule-apis-passthru.asciidoc | 63 +++++++++++ x-pack/plugins/alerting/README.md | 26 ++--- .../alerting/docs/openapi/bundled.json | 102 +++++++++++++++--- .../alerting/docs/openapi/bundled.yaml | 54 ++++++++-- .../components/schemas/400_response.yaml | 17 +++ .../alerting/docs/openapi/entrypoint.yaml | 2 + ...lerting@rule@{ruleid}@_update_api_key.yaml | 23 ++++ .../server/routes/update_rule_api_key.test.ts | 2 +- .../server/routes/update_rule_api_key.ts | 4 +- .../lib/rule_api/update_api_key.test.ts | 2 +- .../lib/rule_api/update_api_key.ts | 4 +- .../common/lib/alert_utils.ts | 2 +- .../tests/alerting/user_managed_api_key.ts | 4 +- 13 files changed, 262 insertions(+), 43 deletions(-) create mode 100644 x-pack/plugins/alerting/docs/openapi/components/schemas/400_response.yaml create mode 100644 x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_update_api_key.yaml diff --git a/docs/api-generated/rules/rule-apis-passthru.asciidoc b/docs/api-generated/rules/rule-apis-passthru.asciidoc index 63aad889c865c..843f073f95e04 100644 --- a/docs/api-generated/rules/rule-apis-passthru.asciidoc +++ b/docs/api-generated/rules/rule-apis-passthru.asciidoc @@ -45,6 +45,7 @@ Any modifications made to this file will be overwritten. <li><a href="#unmuteAlert"><code><span class="http-method">post</span> /s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_unmute</code></a></li> <li><a href="#unmuteAllAlerts"><code><span class="http-method">post</span> /s/{spaceId}/api/alerting/rule/{ruleId}/_unmute_all</code></a></li> <li><a href="#updateRule"><code><span class="http-method">put</span> /s/{spaceId}/api/alerting/rule/{ruleId}</code></a></li> + <li><a href="#updateRuleAPIKey"><code><span class="http-method">post</span> /s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key</code></a></li> </ul> <h1><a name="Alerting">Alerting</a></h1> @@ -2827,12 +2828,61 @@ Any modifications made to this file will be overwritten. <a href="#404_response">404_response</a> </div> <!-- method --> <hr/> + <div class="method"><a name="updateRuleAPIKey"/> + <div class="method-path"> + <a class="up" href="#__Methods">Up</a> + <pre class="post"><code class="huge"><span class="http-method">post</span> /s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key</code></pre></div> + <div class="method-summary">Updates the API key for a rule. (<span class="nickname">updateRuleAPIKey</span>)</div> + <div class="method-notes">The new API key has the credentials of the user that submits the request.</div> + + <h3 class="field-label">Path parameters</h3> + <div class="field-items"> + <div class="param">ruleId (required)</div> + + <div class="param-desc"><span class="param-type">Path Parameter</span> — An identifier for the rule. default: null </div><div class="param">spaceId (required)</div> + + <div class="param-desc"><span class="param-type">Path Parameter</span> — An identifier for the space. If <code>/s/</code> and the identifier are omitted from the path, the default space is used. default: null </div> + </div> <!-- field-items --> + + + + <h3 class="field-label">Request headers</h3> + <div class="field-items"> + <div class="param">kbn-xsrf (required)</div> + + <div class="param-desc"><span class="param-type">Header Parameter</span> — Cross-site request forgery protection default: null </div> + + </div> <!-- field-items --> + + + + + <!--Todo: process Response Object and its headers, schema, examples --> + + + <h3 class="field-label">Produces</h3> + This API call produces the following media types according to the <span class="header">Accept</span> request header; + the media type will be conveyed by the <span class="header">Content-Type</span> response header. + <ul> + <li><code>application/json</code></li> + </ul> + + <h3 class="field-label">Responses</h3> + <h4 class="field-label">200</h4> + Indicates a successful call. + <a href="#"></a> + <h4 class="field-label">400</h4> + Bad request + <a href="#400_response">400_response</a> + </div> <!-- method --> + <hr/> <h2><a name="__Models">Models</a></h2> [ Jump to <a href="#__Methods">Methods</a> ] <h3>Table of Contents</h3> <ol> + <li><a href="#400_response"><code>400_response</code> - Bad request</a></li> <li><a href="#401_response"><code>401_response</code> - Unsuccessful rule API response</a></li> <li><a href="#404_response"><code>404_response</code> - </a></li> <li><a href="#Count"><code>Count</code> - Count</a></li> @@ -2969,6 +3019,19 @@ Any modifications made to this file will be overwritten. <li><a href="#update_rule_request"><code>update_rule_request</code> - Update rule request</a></li> </ol> + <div class="model"> + <h3><a name="400_response"><code>400_response</code> - Bad request</a> <a class="up" href="#__Models">Up</a></h3> + <div class='model-description'></div> + <div class="field-items"> + <div class="param">error </div><div class="param-desc"><span class="param-type"><a href="#string">String</a></span> </div> + <div class="param-enum-header">Enum:</div> + <div class="param-enum">Bad Request</div> +<div class="param">message </div><div class="param-desc"><span class="param-type"><a href="#string">String</a></span> </div> +<div class="param">statusCode </div><div class="param-desc"><span class="param-type"><a href="#integer">Integer</a></span> </div> + <div class="param-enum-header">Enum:</div> + <div class="param-enum">400</div> + </div> <!-- field-items --> + </div> <div class="model"> <h3><a name="401_response"><code>401_response</code> - Unsuccessful rule API response</a> <a class="up" href="#__Models">Up</a></h3> <div class='model-description'></div> diff --git a/x-pack/plugins/alerting/README.md b/x-pack/plugins/alerting/README.md index ba8a7ea8f763f..508a70874e37e 100644 --- a/x-pack/plugins/alerting/README.md +++ b/x-pack/plugins/alerting/README.md @@ -30,7 +30,7 @@ Table of Contents - [Internal HTTP APIs](#internal-http-apis) - [`GET /internal/alerting/rule/{id}/state`: Get rule state](#get-internalalertingruleidstate-get-rule-state) - [`GET /internal/alerting/rule/{id}/_alert_summary`: Get rule alert summary](#get-internalalertingruleidalertsummary-get-rule-alert-summary) - - [`POST /internal/alerting/rule/{id}/_update_api_key`: Update rule API key](#post-internalalertingruleidupdateapikey-update-rule-api-key) + - [`POST /api/alerting/rule/{id}/_update_api_key`: Update rule API key](#post-internalalertingruleidupdateapikey-update-rule-api-key) - [Alert Factory](#alert-factory) - [Templating Actions](#templating-actions) - [Examples](#examples) @@ -306,7 +306,7 @@ interface MyRuleTypeAlertContext extends AlertInstanceContext { } type MyRuleTypeActionGroups = 'default' | 'warning'; - + const myRuleType: RuleType< MyRuleTypeParams, MyRuleTypeExtractedParams, @@ -380,9 +380,9 @@ const myRuleType: RuleType< // Only execute if CPU usage is greater than threshold if (currentCpuUsage > threshold) { - // The first argument is a unique identifier for the alert. In this - // scenario the provided server will be used. Also, this ID will be - // used to make `getState()` return previous state, if any, on + // The first argument is a unique identifier for the alert. In this + // scenario the provided server will be used. Also, this ID will be + // used to make `getState()` return previous state, if any, on // matching identifiers. const alert = services.alertFactory.create(server); @@ -395,7 +395,7 @@ const myRuleType: RuleType< cpuUsage: currentCpuUsage, }); - // 'default' refers to the id of a group of actions to be scheduled + // 'default' refers to the id of a group of actions to be scheduled // for execution, see 'actions' in create rule section alert.scheduleActions('default', { server, @@ -406,8 +406,8 @@ const myRuleType: RuleType< // Returning updated rule type level state, this will become available // within the `state` function parameter at the next execution return { - // This is an example attribute you could set, it makes more sense - // to use this state when the rule type executes multiple + // This is an example attribute you could set, it makes more sense + // to use this state when the rule type executes multiple // alerts but wants a single place to track certain values. lastChecked: new Date(), }; @@ -497,7 +497,7 @@ features.registerKibanaFeature({ // grant `read` over our own type 'my-application-id.my-alert-type', // grant `read` over the built-in IndexThreshold - '.index-threshold', + '.index-threshold', // grant `read` over Uptime's TLS RuleType 'xpack.uptime.alerts.actionGroups.tls' ], @@ -507,7 +507,7 @@ features.registerKibanaFeature({ // grant `read` over our own type 'my-application-id.my-alert-type', // grant `read` over the built-in IndexThreshold - '.index-threshold', + '.index-threshold', // grant `read` over Uptime's TLS RuleType 'xpack.uptime.alerts.actionGroups.tls' ], @@ -555,7 +555,7 @@ features.registerKibanaFeature({ read: [ 'my-application-id.my-restricted-rule-type' ], - }, + }, alert: { all: [ 'my-application-id.my-rule-type' @@ -563,7 +563,7 @@ features.registerKibanaFeature({ read: [ 'my-application-id.my-restricted-rule-type' ], - }, + }, }, savedObject: { all: [], @@ -798,7 +798,7 @@ Query: |---|---|---| |dateStart|The date to start looking for alert events in the event log. Either an ISO date string, or a duration string indicating time since now.|string| -### `POST /internal/alerting/rule/{id}/_update_api_key`: Update rule API key +### `POST /api/alerting/rule/{id}/_update_api_key`: Update rule API key |Property|Description|Type| |---|---|---| diff --git a/x-pack/plugins/alerting/docs/openapi/bundled.json b/x-pack/plugins/alerting/docs/openapi/bundled.json index 31b043f812d47..ad42d43569b82 100644 --- a/x-pack/plugins/alerting/docs/openapi/bundled.json +++ b/x-pack/plugins/alerting/docs/openapi/bundled.json @@ -12,18 +12,26 @@ "url": "https://www.elastic.co/licensing/elastic-license" } }, - "tags": [ - { - "name": "alerting", - "description": "Alerting APIs enable you to create and manage rules and alerts." - } - ], "servers": [ { "url": "http://localhost:5601", "description": "local" } ], + "security": [ + { + "basicAuth": [] + }, + { + "apiKeyAuth": [] + } + ], + "tags": [ + { + "name": "alerting", + "description": "Alerting APIs enable you to create and manage rules and alerts." + } + ], "paths": { "/s/{spaceId}/api/alerting/rule": { "post": { @@ -1188,6 +1196,52 @@ } ] }, + "/s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key": { + "post": { + "summary": "Updates the API key for a rule.", + "operationId": "updateRuleAPIKey", + "description": "The new API key has the credentials of the user that submits the request.", + "tags": [ + "alerting" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/rule_id" + }, + { + "$ref": "#/components/parameters/space_id" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call." + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, "/s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_mute": { "post": { "summary": "Mutes an alert.", @@ -6595,6 +6649,32 @@ } } }, + "400_response": { + "title": "Bad request", + "type": "object", + "required": [ + "error", + "message", + "statusCode" + ], + "properties": { + "error": { + "type": "string", + "enum": [ + "Bad Request" + ] + }, + "message": { + "type": "string" + }, + "statusCode": { + "type": "integer", + "enum": [ + 400 + ] + } + } + }, "alert_response_properties": { "title": "Legacy alert response properties", "type": "object", @@ -7504,13 +7584,5 @@ ] } } - }, - "security": [ - { - "basicAuth": [] - }, - { - "apiKeyAuth": [] - } - ] + } } \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/bundled.yaml b/x-pack/plugins/alerting/docs/openapi/bundled.yaml index 72c8cf2da3828..6f328ca879b43 100644 --- a/x-pack/plugins/alerting/docs/openapi/bundled.yaml +++ b/x-pack/plugins/alerting/docs/openapi/bundled.yaml @@ -8,12 +8,15 @@ info: license: name: Elastic License 2.0 url: https://www.elastic.co/licensing/elastic-license -tags: - - name: alerting - description: Alerting APIs enable you to create and manage rules and alerts. servers: - url: http://localhost:5601 description: local +security: + - basicAuth: [] + - apiKeyAuth: [] +tags: + - name: alerting + description: Alerting APIs enable you to create and manage rules and alerts. paths: /s/{spaceId}/api/alerting/rule: post: @@ -732,6 +735,30 @@ paths: - url: https://localhost:5601 servers: - url: https://localhost:5601 + /s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key: + post: + summary: Updates the API key for a rule. + operationId: updateRuleAPIKey + description: The new API key has the credentials of the user that submits the request. + tags: + - alerting + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/rule_id' + - $ref: '#/components/parameters/space_id' + responses: + '200': + description: Indicates a successful call. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 /s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_mute: post: summary: Mutes an alert. @@ -4503,6 +4530,24 @@ components: $ref: '#/components/schemas/tags' throttle: $ref: '#/components/schemas/throttle' + 400_response: + title: Bad request + type: object + required: + - error + - message + - statusCode + properties: + error: + type: string + enum: + - Bad Request + message: + type: string + statusCode: + type: integer + enum: + - 400 alert_response_properties: title: Legacy alert response properties type: object @@ -5217,6 +5262,3 @@ components: id: recovered name: Recovered rule_task_timeout: 5m -security: - - basicAuth: [] - - apiKeyAuth: [] diff --git a/x-pack/plugins/alerting/docs/openapi/components/schemas/400_response.yaml b/x-pack/plugins/alerting/docs/openapi/components/schemas/400_response.yaml new file mode 100644 index 0000000000000..ab0887586c0eb --- /dev/null +++ b/x-pack/plugins/alerting/docs/openapi/components/schemas/400_response.yaml @@ -0,0 +1,17 @@ +title: Bad request +type: object +required: + - error + - message + - statusCode +properties: + error: + type: string + enum: + - Bad Request + message: + type: string + statusCode: + type: integer + enum: + - 400 \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml b/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml index 5e73a74c058a0..f6beba7fdb82c 100644 --- a/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml +++ b/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml @@ -33,6 +33,8 @@ paths: $ref: 'paths/s@{spaceid}@api@alerting@rule@{ruleid}@_mute_all.yaml' '/s/{spaceId}/api/alerting/rule/{ruleId}/_unmute_all': $ref: 'paths/s@{spaceid}@api@alerting@rule@{ruleid}@_unmute_all.yaml' + '/s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key': + $ref: 'paths/s@{spaceid}@api@alerting@rule@{ruleid}@_update_api_key.yaml' '/s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_mute': $ref: 'paths/s@{spaceid}@api@alerting@rule@{ruleid}@alert@{alertid}@_mute.yaml' '/s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_unmute': diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_update_api_key.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_update_api_key.yaml new file mode 100644 index 0000000000000..a4d79f12943cc --- /dev/null +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_update_api_key.yaml @@ -0,0 +1,23 @@ +post: + summary: Updates the API key for a rule. + operationId: updateRuleAPIKey + description: The new API key has the credentials of the user that submits the request. + tags: + - alerting + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - $ref: '../components/parameters/rule_id.yaml' + - $ref: '../components/parameters/space_id.yaml' + responses: + '200': + description: Indicates a successful call. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts b/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts index 4b2847eb16f73..ea88e2eba19bd 100644 --- a/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts +++ b/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts @@ -30,7 +30,7 @@ describe('updateRuleApiKeyRoute', () => { const [config, handler] = router.post.mock.calls[0]; - expect(config.path).toMatchInlineSnapshot(`"/internal/alerting/rule/{id}/_update_api_key"`); + expect(config.path).toMatchInlineSnapshot(`"/api/alerting/rule/{id}/_update_api_key"`); rulesClient.updateApiKey.mockResolvedValueOnce(); diff --git a/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts b/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts index 4e99b54e76af4..6ba598fe621e0 100644 --- a/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts +++ b/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts @@ -9,7 +9,7 @@ import { IRouter } from '@kbn/core/server'; import { schema } from '@kbn/config-schema'; import { ILicenseState, RuleTypeDisabledError } from '../lib'; import { verifyAccessAndContext } from './lib'; -import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../types'; +import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../types'; const paramSchema = schema.object({ id: schema.string(), @@ -21,7 +21,7 @@ export const updateRuleApiKeyRoute = ( ) => { router.post( { - path: `${INTERNAL_BASE_ALERTING_API_PATH}/rule/{id}/_update_api_key`, + path: `${BASE_ALERTING_API_PATH}/rule/{id}/_update_api_key`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_api_key.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_api_key.test.ts index 15d1e6a58596e..2b643cfc07cc7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_api_key.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_api_key.test.ts @@ -18,7 +18,7 @@ describe('updateAPIKey', () => { expect(http.post.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "/internal/alerting/rule/1%2F/_update_api_key", + "/api/alerting/rule/1%2F/_update_api_key", ], ] `); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_api_key.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_api_key.ts index f9a6912c1d43f..1b83238559d1e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_api_key.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_api_key.ts @@ -6,12 +6,12 @@ */ import { HttpSetup } from '@kbn/core/public'; import { KueryNode } from '@kbn/es-query'; -import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants'; +import { BASE_ALERTING_API_PATH, INTERNAL_BASE_ALERTING_API_PATH } from '../../constants'; import { BulkEditResponse } from '../../../types'; export async function updateAPIKey({ id, http }: { id: string; http: HttpSetup }): Promise<string> { return http.post<string>( - `${INTERNAL_BASE_ALERTING_API_PATH}/rule/${encodeURIComponent(id)}/_update_api_key` + `${BASE_ALERTING_API_PATH}/rule/${encodeURIComponent(id)}/_update_api_key` ); } diff --git a/x-pack/test/alerting_api_integration/common/lib/alert_utils.ts b/x-pack/test/alerting_api_integration/common/lib/alert_utils.ts index 74354c15af0ce..cff3ed710bf6d 100644 --- a/x-pack/test/alerting_api_integration/common/lib/alert_utils.ts +++ b/x-pack/test/alerting_api_integration/common/lib/alert_utils.ts @@ -167,7 +167,7 @@ export class AlertUtils { public getUpdateApiKeyRequest(alertId: string) { const request = this.supertestWithoutAuth - .post(`${getUrlPrefix(this.space.id)}/internal/alerting/rule/${alertId}/_update_api_key`) + .post(`${getUrlPrefix(this.space.id)}/api/alerting/rule/${alertId}/_update_api_key`) .set('kbn-xsrf', 'foo'); if (this.user) { return request.auth(this.user.username, this.user.password); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/user_managed_api_key.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/user_managed_api_key.ts index 7a92b9e11d859..905fe05e110e1 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/user_managed_api_key.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/user_managed_api_key.ts @@ -397,7 +397,7 @@ export default function userManagedApiKeyTest({ getService }: FtrProviderContext .post( `${getUrlPrefix( SuperuserAtSpace1.space.id - )}/internal/alerting/rule/${ruleId}/_update_api_key` + )}/api/alerting/rule/${ruleId}/_update_api_key` ) .set('kbn-xsrf', 'foo') .set('Authorization', `ApiKey ${apiKey}`); @@ -422,7 +422,7 @@ export default function userManagedApiKeyTest({ getService }: FtrProviderContext .post( `${getUrlPrefix( SuperuserAtSpace1.space.id - )}/internal/alerting/rule/${ruleId}/_update_api_key` + )}/api/alerting/rule/${ruleId}/_update_api_key` ) .set('kbn-xsrf', 'foo'); expect(response.status).to.eql(204); From 5724d015363d001a73aaa0c0f78b87b0e59d4849 Mon Sep 17 00:00:00 2001 From: Navarone Feekery <13634519+navarone-feekery@users.noreply.github.com> Date: Mon, 28 Aug 2023 19:33:31 +0200 Subject: [PATCH 30/49] [Enterprise Search] Make network drive connector platinum (#165007) ## Summary Change the Network Drive connector to require a platinum license. --- .../components/search_index/connector/constants.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/constants.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/constants.ts index 950e47882af0a..94630fc054b26 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/constants.ts @@ -98,6 +98,7 @@ export const CONNECTORS_DICT: Record<string, ConnectorClientSideDefinition> = { externalAuthDocsUrl: '', externalDocsUrl: '', icon: CONNECTOR_ICONS.network_drive, + platinumOnly: true, }, onedrive: { docsUrl: docLinks.connectorsOneDrive, From 0113eb74c86f39f0c1d9af8373dfebb6085b4087 Mon Sep 17 00:00:00 2001 From: Nathan Reese <reese.nathan@elastic.co> Date: Mon, 28 Aug 2023 11:40:26 -0600 Subject: [PATCH 31/49] remove unneeded usages of isErrorResponse (#164609) `data.search` uses [poll_search](https://github.com/elastic/kibana/blob/main/src/plugins/data/common/search/poll_search.ts) to fetch data. `poll_search` checks for `isErrorResponse` and throws when`isErrorResponse` is true. **Note** `searchSource.search` uses `data.search` to perform searches. ```javascript return from(search()).pipe( expand(() => { const elapsedTime = Date.now() - startTime; return timer(getPollInterval(elapsedTime)).pipe(switchMap(search)); }), tap((response) => { if (isErrorResponse(response)) { throw response ? new Error('Received partial response') : new AbortError(); } }), takeWhile<Response>(isPartialResponse, true), takeUntil<Response>(aborted$) ); ``` Subscribers to `data.search` and `searchSource.search` do not need to check for `isErrorResponse` in `next`. `poll_search` has already thrown then the response is `isErrorResponse` so these checks are dead code blocks that are never executed. This PR removes these dead code blocks. Breaking this change out of https://github.com/elastic/kibana/pull/164506 so that it can be reviewed in isolated. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../search_examples/public/search/app.tsx | 8 --- .../public/search_sessions/app.tsx | 3 -- .../search_examples/public/sql_search/app.tsx | 5 -- .../search_source/search_source.test.ts | 26 ---------- .../search/search_source/search_source.ts | 5 +- .../use_categorize_request.ts | 4 +- .../public/hooks/use_cancellable_search.ts | 8 +-- .../events_viewer/use_timelines_events.tsx | 14 ++--- .../containers/cti/event_enrichment/api.ts | 6 +-- .../events/last_event_time/index.ts | 9 ++-- .../events/last_event_time/translations.ts | 7 --- .../containers/matrix_histogram/index.test.ts | 13 ----- .../containers/matrix_histogram/index.ts | 11 ++-- .../use_search_strategy/index.test.ts | 19 +++---- .../containers/use_search_strategy/index.tsx | 12 ++--- .../containers/kpi_network/dns/index.tsx | 10 ++-- .../kpi_network/network_events/index.tsx | 10 ++-- .../kpi_network/tls_handshakes/index.tsx | 10 ++-- .../kpi_network/unique_flows/index.tsx | 10 ++-- .../kpi_network/unique_private_ips/index.tsx | 10 ++-- .../overview_cti_links/use_ti_data_sources.ts | 4 +- .../timelines/containers/details/index.tsx | 10 ++-- .../public/timelines/containers/index.tsx | 23 +------- .../timelines/containers/kpis/index.tsx | 10 ++-- .../public/utils/search.ts | 4 -- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - .../hooks/use_fetch_alerts.test.tsx | 52 +++---------------- .../alerts_table/hooks/use_fetch_alerts.tsx | 7 +-- 30 files changed, 56 insertions(+), 257 deletions(-) diff --git a/examples/search_examples/public/search/app.tsx b/examples/search_examples/public/search/app.tsx index e6aeeaae648bd..0fa13df35a4e9 100644 --- a/examples/search_examples/public/search/app.tsx +++ b/examples/search_examples/public/search/app.tsx @@ -30,7 +30,6 @@ import { DataPublicPluginStart, IKibanaSearchResponse, isCompleteResponse, - isErrorResponse, } from '@kbn/data-plugin/public'; import { SearchResponseWarning } from '@kbn/data-plugin/public/search/types'; import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; @@ -247,9 +246,6 @@ export const SearchExamplesApp = ({ text: toMountPoint(res.warning), }); } - } else if (isErrorResponse(res)) { - // TODO: Make response error status clearer - notifications.toasts.addDanger('An error has occurred'); } }, error: (e) => { @@ -401,10 +397,6 @@ export const SearchExamplesApp = ({ title: 'Query result', text: 'Query finished', }); - } else if (isErrorResponse(res)) { - setIsLoading(false); - // TODO: Make response error status clearer - notifications.toasts.addWarning('An error has occurred'); } }, error: (e) => { diff --git a/examples/search_examples/public/search_sessions/app.tsx b/examples/search_examples/public/search_sessions/app.tsx index 701665fd52075..8b7c7bbcaa144 100644 --- a/examples/search_examples/public/search_sessions/app.tsx +++ b/examples/search_examples/public/search_sessions/app.tsx @@ -40,7 +40,6 @@ import { IEsSearchRequest, IEsSearchResponse, isCompleteResponse, - isErrorResponse, QueryState, SearchSessionState, } from '@kbn/data-plugin/public'; @@ -724,8 +723,6 @@ function doSearch( title: 'Query result', text: mountReactNode(message), }); - } else if (isErrorResponse(res)) { - notifications.toasts.addWarning('An error has occurred'); } }), map((res) => ({ response: res, request: req, tookMs: performance.now() - startTs })), diff --git a/examples/search_examples/public/sql_search/app.tsx b/examples/search_examples/public/sql_search/app.tsx index f8278736e4a70..33406a53f9674 100644 --- a/examples/search_examples/public/sql_search/app.tsx +++ b/examples/search_examples/public/sql_search/app.tsx @@ -27,7 +27,6 @@ import { DataPublicPluginStart, IKibanaSearchResponse, isCompleteResponse, - isErrorResponse, } from '@kbn/data-plugin/public'; import { SQL_SEARCH_STRATEGY, @@ -70,10 +69,6 @@ export const SqlSearchExampleApp = ({ notifications, data }: SearchExamplesAppDe if (isCompleteResponse(res)) { setIsLoading(false); setResponse(res); - } else if (isErrorResponse(res)) { - setIsLoading(false); - setResponse(res); - notifications.toasts.addDanger('An error has occurred'); } }, error: (e) => { diff --git a/src/plugins/data/common/search/search_source/search_source.test.ts b/src/plugins/data/common/search/search_source/search_source.test.ts index eeb4c5a972e3a..8ceaab7e12a18 100644 --- a/src/plugins/data/common/search/search_source/search_source.test.ts +++ b/src/plugins/data/common/search/search_source/search_source.test.ts @@ -1105,32 +1105,6 @@ describe('SearchSource', () => { expect(complete2).toBeCalledTimes(1); expect(searchSourceDependencies.search).toHaveBeenCalledTimes(1); }); - - test('should emit error on empty response', async () => { - searchSourceDependencies.search = mockSearchMethod = jest - .fn() - .mockReturnValue( - of({ rawResponse: { test: 1 }, isPartial: true, isRunning: true }, undefined) - ); - - searchSource = new SearchSource({ index: indexPattern }, searchSourceDependencies); - const options = {}; - - const next = jest.fn(); - const error = jest.fn(); - const complete = jest.fn(); - const res$ = searchSource.fetch$(options); - res$.subscribe({ next, error, complete }); - await firstValueFrom(res$).catch((_) => {}); - - expect(next).toBeCalledTimes(1); - expect(error).toBeCalledTimes(1); - expect(complete).toBeCalledTimes(0); - expect(next.mock.calls[0][0].rawResponse).toStrictEqual({ - test: 1, - }); - expect(error.mock.calls[0][0]).toBe(undefined); - }); }); describe('inspector', () => { diff --git a/src/plugins/data/common/search/search_source/search_source.ts b/src/plugins/data/common/search/search_source/search_source.ts index c11289439885b..91eea3e50f881 100644 --- a/src/plugins/data/common/search/search_source/search_source.ts +++ b/src/plugins/data/common/search/search_source/search_source.ts @@ -106,7 +106,6 @@ import { getRequestInspectorStats, getResponseInspectorStats } from './inspect'; import { getEsQueryConfig, IKibanaSearchResponse, - isErrorResponse, isPartialResponse, isCompleteResponse, UI_SETTINGS, @@ -547,9 +546,7 @@ export class SearchSource { // For testing timeout messages in UI, uncomment the next line // response.rawResponse.timed_out = true; return new Observable<IKibanaSearchResponse<unknown>>((obs) => { - if (isErrorResponse(response)) { - obs.error(response); - } else if (isPartialResponse(response)) { + if (isPartialResponse(response)) { obs.next(this.postFlightTransform(response)); } else { if (!this.hasPostFlightRequests()) { diff --git a/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts b/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts index a4ad155092f25..3108ec9391cef 100644 --- a/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts +++ b/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts @@ -7,7 +7,7 @@ import { cloneDeep, get } from 'lodash'; import { useRef, useCallback, useMemo } from 'react'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/public'; +import { isCompleteResponse } from '@kbn/data-plugin/public'; import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { createRandomSamplerWrapper } from '@kbn/ml-random-sampler-utils'; @@ -110,8 +110,6 @@ export function useCategorizeRequest() { next: (result) => { if (isCompleteResponse(result)) { resolve(processCategoryResults(result, field, unwrap)); - } else if (isErrorResponse(result)) { - reject(result); } else { // partial results // Ignore partial results for now. diff --git a/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts b/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts index 0450905bde912..a44e176c1c073 100644 --- a/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts +++ b/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts @@ -6,11 +6,7 @@ */ import { useCallback, useRef, useState } from 'react'; -import { - type IKibanaSearchResponse, - isCompleteResponse, - isErrorResponse, -} from '@kbn/data-plugin/common'; +import { type IKibanaSearchResponse, isCompleteResponse } from '@kbn/data-plugin/common'; import { tap } from 'rxjs/operators'; import { useAiopsAppContext } from './use_aiops_app_context'; @@ -38,8 +34,6 @@ export function useCancellableSearch() { if (isCompleteResponse(result)) { setIsFetching(false); resolve(result); - } else if (isErrorResponse(result)) { - reject(result); } else { // partial results // Ignore partial results for now. diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/use_timelines_events.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/use_timelines_events.tsx index 3a70ccebb9ca6..2b234879ccc50 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/use_timelines_events.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/use_timelines_events.tsx @@ -12,7 +12,7 @@ import { useDispatch } from 'react-redux'; import { Subscription } from 'rxjs'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import type { Inspect, PaginationInputPaginated, @@ -32,8 +32,6 @@ import type { RunTimeMappings } from '../../store/sourcerer/model'; import { TimelineEventsQueries } from '../../../../common/search_strategy'; import type { KueryFilterQueryKind } from '../../../../common/types'; import type { ESQuery } from '../../../../common/typed_json'; -import { useAppToasts } from '../../hooks/use_app_toasts'; -import { ERROR_TIMELINE_EVENTS } from './translations'; import type { AlertWorkflowStatus } from '../../types'; import { getSearchTransactionName, useStartTransaction } from '../../lib/apm/use_start_transaction'; export type InspectResponse = Inspect & { response: string[] }; @@ -220,7 +218,6 @@ export const useTimelineEventsHandler = ({ loadPage: wrappedLoadPage, updatedAt: 0, }); - const { addWarning } = useAppToasts(); const timelineSearch = useCallback( (request: TimelineRequest<typeof language> | null, onNextHandler?: OnNextResponseHandler) => { @@ -233,7 +230,7 @@ export const useTimelineEventsHandler = ({ abortCtrl.current = new AbortController(); setLoading(true); if (data && data.search) { - const { endTracking } = startTracking(); + startTracking(); const abortSignal = abortCtrl.current.signal; searchSubscription$.current = data.search .search<TimelineRequest<typeof language>, TimelineResponse<typeof language>>( @@ -270,11 +267,6 @@ export const useTimelineEventsHandler = ({ setFilterStatus(request.filterStatus); setLoading(false); - searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - setLoading(false); - endTracking('invalid'); - addWarning(ERROR_TIMELINE_EVENTS); searchSubscription$.current.unsubscribe(); } }, @@ -292,7 +284,7 @@ export const useTimelineEventsHandler = ({ asyncSearch(); refetch.current = asyncSearch; }, - [skip, data, entityType, dataViewId, addWarning, startTracking, dispatch, id, prevFilterStatus] + [skip, data, entityType, dataViewId, startTracking, dispatch, id, prevFilterStatus] ); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/common/containers/cti/event_enrichment/api.ts b/x-pack/plugins/security_solution/public/common/containers/cti/event_enrichment/api.ts index bf595de39ee5e..0d08b9a93a5c4 100644 --- a/x-pack/plugins/security_solution/public/common/containers/cti/event_enrichment/api.ts +++ b/x-pack/plugins/security_solution/public/common/containers/cti/event_enrichment/api.ts @@ -9,7 +9,7 @@ import type { Observable } from 'rxjs'; import { filter } from 'rxjs/operators'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { isErrorResponse, isCompleteResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import type { CtiEventEnrichmentRequestOptions, CtiEventEnrichmentStrategyResponse, @@ -46,6 +46,4 @@ export const getEventEnrichment = ({ export const getEventEnrichmentComplete = ( props: GetEventEnrichmentProps ): Observable<CtiEventEnrichmentStrategyResponse> => - getEventEnrichment(props).pipe( - filter((response) => isErrorResponse(response) || isCompleteResponse(response)) - ); + getEventEnrichment(props).pipe(filter((response) => isCompleteResponse(response))); diff --git a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts index b55c566084528..8904ccd5ad8bb 100644 --- a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts +++ b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import type { inputsModel } from '../../../store'; import { useKibana } from '../../../lib/kibana'; import type { @@ -59,7 +59,7 @@ export const useTimelineLastEventTime = ({ refetch: refetch.current, errorMessage: undefined, }); - const { addError, addWarning } = useAppToasts(); + const { addError } = useAppToasts(); const timelineLastEventTimeSearch = useCallback( (request: TimelineEventsLastEventTimeRequestOptions) => { @@ -85,9 +85,6 @@ export const useTimelineLastEventTime = ({ lastSeen: response.lastSeen, refetch: refetch.current, })); - } else if (isErrorResponse(response)) { - setLoading(false); - addWarning(i18n.ERROR_LAST_EVENT_TIME); } }, error: (msg) => { @@ -107,7 +104,7 @@ export const useTimelineLastEventTime = ({ asyncSearch(); refetch.current = asyncSearch; }, - [data.search, addError, addWarning] + [data.search, addError] ); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/translations.ts b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/translations.ts index c882029958934..840567d5c1f14 100644 --- a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/translations.ts +++ b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/translations.ts @@ -7,13 +7,6 @@ import { i18n } from '@kbn/i18n'; -export const ERROR_LAST_EVENT_TIME = i18n.translate( - 'xpack.securitySolution.lastEventTime.errorSearchDescription', - { - defaultMessage: `An error has occurred on last event time search`, - } -); - export const FAIL_LAST_EVENT_TIME = i18n.translate( 'xpack.securitySolution.lastEventTime.failSearchDescription', { diff --git a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.test.ts b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.test.ts index dba14afd0ff2e..fab3766d2c5d0 100644 --- a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.test.ts @@ -190,19 +190,6 @@ describe('useMatrixHistogram', () => { expect(mockEndTracking).toHaveBeenCalledWith('success'); }); - it('should end tracking error when the partial request is invalid', () => { - (useKibana().services.data.search.search as jest.Mock).mockReturnValueOnce({ - subscribe: ({ next }: { next: Function }) => next(null), - }); - - renderHook(useMatrixHistogram, { - initialProps: props, - wrapper: TestProviders, - }); - - expect(mockEndTracking).toHaveBeenCalledWith('invalid'); - }); - it('should end tracking error when the request fails', () => { (useKibana().services.data.search.search as jest.Mock).mockReturnValueOnce({ subscribe: ({ error }: { error: Function }) => error('some error'), diff --git a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts index f75385fdd4955..137acc4f1c9e7 100644 --- a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts +++ b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts @@ -10,7 +10,7 @@ import { getOr, noop } from 'lodash/fp'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isErrorResponse, isCompleteResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import type { MatrixHistogramQueryProps } from '../../components/matrix_histogram/types'; import type { inputsModel } from '../../store'; import { createFilter } from '../helpers'; @@ -92,7 +92,7 @@ export const useMatrixHistogram = ({ ...(isPtrIncluded != null ? { isPtrIncluded } : {}), ...(includeMissingData != null ? { includeMissingData } : {}), }); - const { addError, addWarning } = useAppToasts(); + const { addError } = useAppToasts(); const [matrixHistogramResponse, setMatrixHistogramResponse] = useState<UseMatrixHistogramArgs>({ data: [], @@ -138,11 +138,6 @@ export const useMatrixHistogram = ({ })); endTracking('success'); searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - setLoading(false); - addWarning(i18n.ERROR_MATRIX_HISTOGRAM); - endTracking('invalid'); - searchSubscription$.current.unsubscribe(); } }, error: (msg) => { @@ -160,7 +155,7 @@ export const useMatrixHistogram = ({ asyncSearch(); refetch.current = asyncSearch; }, - [data.search, histogramType, addWarning, addError, errorMessage, startTracking] + [data.search, histogramType, addError, errorMessage, startTracking] ); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts index 00dd75222cafb..6a3b48dce6615 100644 --- a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts @@ -273,14 +273,18 @@ describe('useSearchStrategy', () => { expect(mockEndTracking).toBeCalledWith('success'); }); - it('should track invalid search result', () => { - mockResponse.mockReturnValueOnce({}); // mock invalid empty response + it('should handle search error', () => { + mockResponse.mockImplementation(() => { + throw new Error( + 'simulated search response error, which could be 1) undefined response, 2) response without rawResponse, or 3) partial response' + ); + }); const { result } = renderHook(() => useSearch<FactoryQueryTypes>(factoryQueryType)); result.current({ request, abortSignal: new AbortController().signal }); expect(mockStartTracking).toBeCalledTimes(1); - expect(mockEndTracking).toBeCalledWith('invalid'); + expect(mockEndTracking).toBeCalledWith('error'); }); it('should track error search result', () => { @@ -310,14 +314,5 @@ describe('useSearchStrategy', () => { expect(mockEndTracking).toBeCalledTimes(1); expect(mockEndTracking).toBeCalledWith('aborted'); }); - - it('should show toast warning when the API returns partial invalid response', () => { - mockResponse.mockReturnValueOnce({}); // mock invalid empty response - - const { result } = renderHook(() => useSearch<FactoryQueryTypes>(factoryQueryType)); - result.current({ request, abortSignal: new AbortController().signal }); - - expect(mockAddToastWarning).toBeCalled(); - }); }); }); diff --git a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx index 65175f00074c8..b9cd06e77e27e 100644 --- a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx @@ -47,7 +47,6 @@ export const useSearch = <QueryType extends FactoryQueryTypes>( factoryQueryType: QueryType ): UseSearchFunction<QueryType> => { const { data } = useKibana().services; - const { addWarning } = useAppToasts(); const { startTracking } = useTrackHttpRequest(); const search = useCallback<UseSearchFunction<QueryType>>( @@ -65,16 +64,11 @@ export const useSearch = <QueryType extends FactoryQueryTypes>( abortSignal, } ) - .pipe(filter((response) => isErrorResponse(response) || isCompleteResponse(response))); + .pipe(filter((response) => isCompleteResponse(response))); observable.subscribe({ next: (response) => { - if (isErrorResponse(response)) { - addWarning(i18n.INVALID_RESPONSE_WARNING_SEARCH_STRATEGY(factoryQueryType)); - endTracking('invalid'); - } else { - endTracking('success'); - } + endTracking('success'); }, error: () => { endTracking(abortSignal.aborted ? 'aborted' : 'error'); @@ -83,7 +77,7 @@ export const useSearch = <QueryType extends FactoryQueryTypes>( return observable; }, - [addWarning, data.search, factoryQueryType, startTracking] + [data.search, factoryQueryType, startTracking] ); return search; diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx index 806c8d67e0c8e..cf52d2b4ee0eb 100644 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; import type { inputsModel } from '../../../../../common/store'; import { createFilter } from '../../../../../common/containers/helpers'; @@ -69,7 +69,7 @@ export const useNetworkKpiDns = ({ isInspected: false, refetch: refetch.current, }); - const { addError, addWarning } = useAppToasts(); + const { addError } = useAppToasts(); const networkKpiDnsSearch = useCallback( (request: NetworkKpiDnsRequestOptions | null) => { @@ -97,10 +97,6 @@ export const useNetworkKpiDns = ({ refetch: refetch.current, })); searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - setLoading(false); - addWarning(i18n.ERROR_NETWORK_KPI_DNS); - searchSubscription$.current.unsubscribe(); } }, error: (msg) => { @@ -117,7 +113,7 @@ export const useNetworkKpiDns = ({ asyncSearch(); refetch.current = asyncSearch; }, - [data.search, addError, addWarning, skip] + [data.search, addError, skip] ); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx index fe631b6b7e975..378120d155e16 100644 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; import type { inputsModel } from '../../../../../common/store'; import { createFilter } from '../../../../../common/containers/helpers'; @@ -70,7 +70,7 @@ export const useNetworkKpiNetworkEvents = ({ isInspected: false, refetch: refetch.current, }); - const { addError, addWarning } = useAppToasts(); + const { addError } = useAppToasts(); const networkKpiNetworkEventsSearch = useCallback( (request: NetworkKpiNetworkEventsRequestOptions | null) => { @@ -101,10 +101,6 @@ export const useNetworkKpiNetworkEvents = ({ refetch: refetch.current, })); searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - setLoading(false); - addWarning(i18n.ERROR_NETWORK_KPI_NETWORK_EVENTS); - searchSubscription$.current.unsubscribe(); } }, error: (msg) => { @@ -121,7 +117,7 @@ export const useNetworkKpiNetworkEvents = ({ asyncSearch(); refetch.current = asyncSearch; }, - [data.search, addError, addWarning, skip] + [data.search, addError, skip] ); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx index 63beacc2d297d..b53c07640220e 100644 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; import type { inputsModel } from '../../../../../common/store'; import { createFilter } from '../../../../../common/containers/helpers'; @@ -70,7 +70,7 @@ export const useNetworkKpiTlsHandshakes = ({ isInspected: false, refetch: refetch.current, }); - const { addError, addWarning } = useAppToasts(); + const { addError } = useAppToasts(); const networkKpiTlsHandshakesSearch = useCallback( (request: NetworkKpiTlsHandshakesRequestOptions | null) => { @@ -100,10 +100,6 @@ export const useNetworkKpiTlsHandshakes = ({ refetch: refetch.current, })); searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - setLoading(false); - addWarning(i18n.ERROR_NETWORK_KPI_TLS_HANDSHAKES); - searchSubscription$.current.unsubscribe(); } }, error: (msg) => { @@ -120,7 +116,7 @@ export const useNetworkKpiTlsHandshakes = ({ asyncSearch(); refetch.current = asyncSearch; }, - [data.search, addError, addWarning, skip] + [data.search, addError, skip] ); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx index 0d62d4e286201..6ff0eb5372a19 100644 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; import type { inputsModel } from '../../../../../common/store'; import { createFilter } from '../../../../../common/containers/helpers'; @@ -70,7 +70,7 @@ export const useNetworkKpiUniqueFlows = ({ isInspected: false, refetch: refetch.current, }); - const { addError, addWarning } = useAppToasts(); + const { addError } = useAppToasts(); const networkKpiUniqueFlowsSearch = useCallback( (request: NetworkKpiUniqueFlowsRequestOptions | null) => { @@ -100,10 +100,6 @@ export const useNetworkKpiUniqueFlows = ({ refetch: refetch.current, })); searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - setLoading(false); - addWarning(i18n.ERROR_NETWORK_KPI_UNIQUE_FLOWS); - searchSubscription$.current.unsubscribe(); } }, error: (msg) => { @@ -120,7 +116,7 @@ export const useNetworkKpiUniqueFlows = ({ asyncSearch(); refetch.current = asyncSearch; }, - [data.search, addError, addWarning, skip] + [data.search, addError, skip] ); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx index 2e73cb18ef52d..45435665dba41 100644 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; import type { inputsModel } from '../../../../../common/store'; import { createFilter } from '../../../../../common/containers/helpers'; @@ -77,7 +77,7 @@ export const useNetworkKpiUniquePrivateIps = ({ isInspected: false, refetch: refetch.current, }); - const { addError, addWarning } = useAppToasts(); + const { addError } = useAppToasts(); const networkKpiUniquePrivateIpsSearch = useCallback( (request: NetworkKpiUniquePrivateIpsRequestOptions | null) => { @@ -112,10 +112,6 @@ export const useNetworkKpiUniquePrivateIps = ({ refetch: refetch.current, })); searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - setLoading(false); - addWarning(i18n.ERROR_NETWORK_KPI_UNIQUE_PRIVATE_IPS); - searchSubscription$.current.unsubscribe(); } }, error: (msg) => { @@ -132,7 +128,7 @@ export const useNetworkKpiUniquePrivateIps = ({ asyncSearch(); refetch.current = asyncSearch; }, - [data.search, addError, addWarning, skip] + [data.search, addError, skip] ); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/use_ti_data_sources.ts b/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/use_ti_data_sources.ts index 43aff52970348..96a0c44327909 100644 --- a/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/use_ti_data_sources.ts +++ b/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/use_ti_data_sources.ts @@ -9,7 +9,7 @@ import { filter } from 'rxjs/operators'; import { useEffect, useState } from 'react'; import { useObservable, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/public'; +import { isCompleteResponse } from '@kbn/data-plugin/public'; import { useKibana } from '../../../common/lib/kibana'; import type { Bucket, @@ -51,7 +51,7 @@ export const getTiDataSourcesComplete = ( ): Observable<CtiDataSourceStrategyResponse> => { return getTiDataSources(props).pipe( filter((response) => { - return isErrorResponse(response) || isCompleteResponse(response); + return isCompleteResponse(response); }) ); }; diff --git a/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx index c07e52b09874f..3b326e492d132 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx @@ -11,7 +11,7 @@ import ReactDOM from 'react-dom'; import deepEqual from 'fast-deep-equal'; import { Subscription } from 'rxjs'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import { EntityType } from '@kbn/timelines-plugin/common'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; import { useKibana } from '../../../common/lib/kibana'; @@ -62,7 +62,7 @@ export const useTimelineEventsDetails = ({ const [loading, setLoading] = useState(true); const [timelineDetailsRequest, setTimelineDetailsRequest] = useState<TimelineEventsDetailsRequestOptions | null>(null); - const { addError, addWarning } = useAppToasts(); + const { addError } = useAppToasts(); const [timelineDetailsResponse, setTimelineDetailsResponse] = useState<EventsArgs['detailsData']>(null); @@ -99,10 +99,6 @@ export const useTimelineEventsDetails = ({ searchSubscription$.current.unsubscribe(); }); }); - } else if (isErrorResponse(response)) { - setLoading(false); - addWarning(i18n.FAIL_TIMELINE_DETAILS); - searchSubscription$.current.unsubscribe(); } }, error: (msg) => { @@ -117,7 +113,7 @@ export const useTimelineEventsDetails = ({ asyncSearch(); refetch.current = asyncSearch; }, - [data.search, addError, addWarning, skip] + [data.search, addError, skip] ); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx index 6d2837db0eddc..b65c7c7c51498 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx @@ -12,7 +12,7 @@ import { useDispatch } from 'react-redux'; import { Subscription } from 'rxjs'; import type { DataView } from '@kbn/data-plugin/common'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import type { ESQuery } from '../../../common/typed_json'; import type { inputsModel } from '../../common/store'; @@ -32,7 +32,6 @@ import type { } from '../../../common/search_strategy'; import { Direction, TimelineEventsQueries } from '../../../common/search_strategy'; import type { InspectResponse } from '../../types'; -import * as i18n from './translations'; import type { KueryFilterQueryKind } from '../../../common/types/timeline'; import { TimelineId } from '../../../common/types/timeline'; import { useRouteSpy } from '../../common/utils/route/use_route_spy'; @@ -42,7 +41,6 @@ import type { TimelineEqlRequestOptions, TimelineEqlResponse, } from '../../../common/search_strategy/timeline/events/eql'; -import { useAppToasts } from '../../common/hooks/use_app_toasts'; import { useTrackHttpRequest } from '../../common/lib/apm/use_track_http_request'; import { APP_UI_ID } from '../../../common/constants'; @@ -221,8 +219,6 @@ export const useTimelineEventsHandler = ({ } }, [setUpdated, timelineResponse.updatedAt]); - const { addWarning } = useAppToasts(); - const timelineSearch = useCallback( async ( request: TimelineRequest<typeof language> | null, @@ -275,11 +271,6 @@ export const useTimelineEventsHandler = ({ return newTimelineResponse; }); - searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - endTracking('invalid'); - setLoading(false); - addWarning(i18n.ERROR_TIMELINE_EVENTS); searchSubscription$.current.unsubscribe(); } }, @@ -335,17 +326,7 @@ export const useTimelineEventsHandler = ({ await asyncSearch(); refetch.current = asyncSearch; }, - [ - pageName, - skip, - id, - startTracking, - data.search, - dataViewId, - addWarning, - refetchGrid, - wrappedLoadPage, - ] + [pageName, skip, id, startTracking, data.search, dataViewId, refetchGrid, wrappedLoadPage] ); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/timelines/containers/kpis/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/kpis/index.tsx index 5bd71f4f7be94..f2a1d81ec0294 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/kpis/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/kpis/index.tsx @@ -10,7 +10,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import deepEqual from 'fast-deep-equal'; import { Subscription } from 'rxjs'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/public'; +import { isCompleteResponse } from '@kbn/data-plugin/public'; import type { inputsModel } from '../../../common/store'; import { useKibana } from '../../../common/lib/kibana'; import type { @@ -46,7 +46,7 @@ export const useTimelineKpis = ({ ); const [timelineKpiResponse, setTimelineKpiResponse] = useState<TimelineKpiStrategyResponse | null>(null); - const { addError, addWarning } = useAppToasts(); + const { addError } = useAppToasts(); const timelineKpiSearch = useCallback( (request: TimelineKpiStrategyRequest | null) => { @@ -68,10 +68,6 @@ export const useTimelineKpis = ({ setLoading(false); setTimelineKpiResponse(response); searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - setLoading(false); - addWarning(i18n.FAIL_TIMELINE_KPI_DETAILS); - searchSubscription$.current.unsubscribe(); } }, error: (msg) => { @@ -86,7 +82,7 @@ export const useTimelineKpis = ({ asyncSearch(); refetch.current = asyncSearch; }, - [data.search, addError, addWarning] + [data.search, addError] ); useEffect(() => { diff --git a/x-pack/plugins/threat_intelligence/public/utils/search.ts b/x-pack/plugins/threat_intelligence/public/utils/search.ts index e54bd6ecef885..1dac39f74b230 100644 --- a/x-pack/plugins/threat_intelligence/public/utils/search.ts +++ b/x-pack/plugins/threat_intelligence/public/utils/search.ts @@ -9,7 +9,6 @@ import { IEsSearchRequest, IKibanaSearchResponse, isCompleteResponse, - isErrorResponse, } from '@kbn/data-plugin/common'; import { ISearchStart } from '@kbn/data-plugin/public'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; @@ -97,9 +96,6 @@ export const search = async <TResponse, T = {}>( if (isCompleteResponse(response)) { inspect.recordRequestCompletion(searchRequest, response); resolve(response.rawResponse); - } else if (isErrorResponse(response)) { - inspect.recordRequestError(response); - reject(response); } }, error: (requestError) => { diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index e044d622d0151..e1f61483a6b20 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -33569,7 +33569,6 @@ "xpack.securitySolution.kubernetes.columnPod": "Pod", "xpack.securitySolution.kubernetes.columnSessionStart": "Date de démarrage", "xpack.securitySolution.landing.threatHunting.hostsDescription": "Aperçu complet de tous les hôtes et événements de sécurité des hôtes.", - "xpack.securitySolution.lastEventTime.errorSearchDescription": "Une erreur s'est produite sur la recherche de dernière heure de l'événement", "xpack.securitySolution.lastEventTime.failSearchDescription": "Impossible de lancer une recherche sur la dernière heure de l'événement", "xpack.securitySolution.lensEmbeddable.NoDataToDisplay.title": "Aucune donnée à afficher", "xpack.securitySolution.licensing.unsupportedMachineLearningMessage": "Votre licence ne prend pas en charge le Machine Learning. Veuillez mettre votre licence à niveau.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index ad0939f714278..0afa87b22236a 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -33568,7 +33568,6 @@ "xpack.securitySolution.kubernetes.columnPod": "ポッド", "xpack.securitySolution.kubernetes.columnSessionStart": "開始日", "xpack.securitySolution.landing.threatHunting.hostsDescription": "すべてのホストとホスト関連のセキュリティイベントに関する包括的な概要。", - "xpack.securitySolution.lastEventTime.errorSearchDescription": "前回のイベント時刻検索でエラーが発生しました。", "xpack.securitySolution.lastEventTime.failSearchDescription": "前回のイベント時刻で検索を実行できませんでした", "xpack.securitySolution.lensEmbeddable.NoDataToDisplay.title": "表示するデータがありません", "xpack.securitySolution.licensing.unsupportedMachineLearningMessage": "ご使用のライセンスは機械翻訳をサポートしていません。ライセンスをアップグレードしてください。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 228d7990cf6a0..57172509567f9 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -33564,7 +33564,6 @@ "xpack.securitySolution.kubernetes.columnPod": "Pod", "xpack.securitySolution.kubernetes.columnSessionStart": "开始日期", "xpack.securitySolution.landing.threatHunting.hostsDescription": "所有主机和主机相关安全事件的全面概览。", - "xpack.securitySolution.lastEventTime.errorSearchDescription": "搜索上次事件时间时发生错误", "xpack.securitySolution.lastEventTime.failSearchDescription": "无法对上次事件时间执行搜索", "xpack.securitySolution.lensEmbeddable.NoDataToDisplay.title": "没有可显示的数据", "xpack.securitySolution.licensing.unsupportedMachineLearningMessage": "您的许可证不支持 Machine Learning。请升级您的许可证。", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.test.tsx index 06c712ef87e2b..ef515cf8ffdca 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.test.tsx @@ -6,7 +6,7 @@ */ import sinon from 'sinon'; -import { of } from 'rxjs'; +import { of, throwError } from 'rxjs'; import { act, renderHook } from '@testing-library/react-hooks'; import { useFetchAlerts, FetchAlertsArgs, FetchAlertResp } from './use_fetch_alerts'; import { useKibana } from '../../../../common/lib/kibana'; @@ -286,9 +286,10 @@ describe('useFetchAlerts', () => { ]); }); - it('returns the correct response if the request is undefined', () => { - // @ts-expect-error - const obs$ = of<IKibanaSearchResponse>(undefined); + it('handles search error', () => { + const obs$ = throwError( + 'simulated search response error, which could be 1) undefined response, 2) response without rawResponse, or 3) partial response' + ); dataSearchMock.mockReturnValue(obs$); const { result } = renderHook(() => useFetchAlerts(args)); @@ -308,7 +309,7 @@ describe('useFetchAlerts', () => { expect(showErrorMock).toHaveBeenCalled(); }); - it('returns the correct response if the request is running', () => { + it('returns the correct response if the search response is running', () => { const obs$ = of<IKibanaSearchResponse>({ ...searchResponse, isRunning: true }); dataSearchMock.mockReturnValue(obs$); const { result } = renderHook(() => useFetchAlerts(args)); @@ -327,47 +328,6 @@ describe('useFetchAlerts', () => { ]); }); - it('returns the correct response if the request is partial', () => { - const obs$ = of<IKibanaSearchResponse>({ ...searchResponse, isPartial: true }); - dataSearchMock.mockReturnValue(obs$); - const { result } = renderHook(() => useFetchAlerts(args)); - - expect(result.current).toEqual([ - false, - { - ...expectedResponse, - alerts: [], - getInspectQuery: expect.anything(), - refetch: expect.anything(), - isInitializing: true, - totalAlerts: -1, - updatedAt: 0, - }, - ]); - expect(showErrorMock).toHaveBeenCalled(); - }); - - it('returns the correct response if there is no rawResponse', () => { - // @ts-expect-error - const obs$ = of<IKibanaSearchResponse>({ id: '1', isRunning: true, isPartial: false }); - dataSearchMock.mockReturnValue(obs$); - const { result } = renderHook(() => useFetchAlerts(args)); - - expect(result.current).toEqual([ - false, - { - ...expectedResponse, - alerts: [], - getInspectQuery: expect.anything(), - refetch: expect.anything(), - isInitializing: true, - totalAlerts: -1, - updatedAt: 0, - }, - ]); - expect(showErrorMock).toHaveBeenCalled(); - }); - it('returns the correct total alerts if the total alerts in the response is an object', () => { const obs$ = of<IKibanaSearchResponse>({ ...searchResponse, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.tsx index d509c2dcf98f7..374e2883cc089 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.tsx @@ -12,7 +12,7 @@ import { noop } from 'lodash'; import { useCallback, useEffect, useReducer, useRef, useMemo } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; +import { isCompleteResponse } from '@kbn/data-plugin/common'; import type { RuleRegistrySearchRequest, RuleRegistrySearchRequestPagination, @@ -27,7 +27,6 @@ import type { import type { Alert, Alerts, GetInspectQuery, InspectQuery } from '../../../../types'; import { useKibana } from '../../../../common/lib/kibana'; import { DefaultSort } from './constants'; -import * as i18n from './translations'; export interface FetchAlertsArgs { featureIds: ValidFeatureId[]; @@ -260,10 +259,6 @@ const useFetchAlerts = ({ totalAlerts, }); searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - dispatch({ type: 'loading', loading: false }); - data.search.showError(new Error(i18n.ERROR_FETCH_ALERTS)); - searchSubscription$.current.unsubscribe(); } }, error: (msg) => { From 35b7b08595d02964c1931beb2f9d52634268b82c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= <mikecote@users.noreply.github.com> Date: Mon, 28 Aug 2023 13:42:21 -0400 Subject: [PATCH 32/49] [Event Log] Skip setting assets to hidden in serverless (#164767) Resolves https://github.com/elastic/kibana/issues/163891. In this PR, I'm making the event log skip converting existing assets to hidden if it is in a serverless deployment. Given assets that need to be converted to hidden would exist prior to 8.0, there isn't such a case in serverless and we do not have the necessary legacy APIs to retrieve them. ## To verify on Serverless - Ensure on serverless there are no more warnings as indicated in https://github.com/elastic/kibana/issues/163891. ## To verify on non-Serverless 1. Create a 7.15 deployment (and persisting the ES data so you can upgrade later) 2. Create an alerting rule (with short interval, say 10s) 3. Let the alerting rule run a few times so it generates event logs 4. Upgrade ES to 7.17 (it will fail otherwise) 5. Upgrade your deployment to this PR 6. Check the event log index template, indices and alias for 7.15 to ensure they got converted to hidden - `curl -XGET http://elastic:changeme@localhost:9200/_template/.kibana-event-log-7.15.3-template` - `curl -XGET http://elastic:changeme@localhost:9200/.kibana-event-log-7.15.3-000001` - `curl -XGET http://elastic:changeme@localhost:9200/_alias/.kibana-event-log-7.15.3` --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/event_log/kibana.jsonc | 3 ++- .../event_log/server/es/context.mock.ts | 1 + .../event_log/server/es/context.test.ts | 6 ++++++ x-pack/plugins/event_log/server/es/context.ts | 4 ++++ .../plugins/event_log/server/es/init.test.ts | 18 ++++++++++++++++++ x-pack/plugins/event_log/server/es/init.ts | 7 +++++-- x-pack/plugins/event_log/server/plugin.test.ts | 6 ++++-- x-pack/plugins/event_log/server/plugin.ts | 9 ++++++++- x-pack/plugins/event_log/tsconfig.json | 1 + 9 files changed, 49 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/event_log/kibana.jsonc b/x-pack/plugins/event_log/kibana.jsonc index 1f05da271664f..ae1da1389b1eb 100644 --- a/x-pack/plugins/event_log/kibana.jsonc +++ b/x-pack/plugins/event_log/kibana.jsonc @@ -11,7 +11,8 @@ "eventLog" ], "optionalPlugins": [ - "spaces" + "spaces", + "serverless" ] } } diff --git a/x-pack/plugins/event_log/server/es/context.mock.ts b/x-pack/plugins/event_log/server/es/context.mock.ts index c974a63a6407f..90514d8f53727 100644 --- a/x-pack/plugins/event_log/server/es/context.mock.ts +++ b/x-pack/plugins/event_log/server/es/context.mock.ts @@ -20,6 +20,7 @@ const createContextMock = () => { } = { logger: loggingSystemMock.createLogger(), esNames: namesMock.create(), + shouldSetExistingAssetsToHidden: true, initialize: jest.fn(), shutdown: jest.fn(), waitTillReady: jest.fn(async () => true), diff --git a/x-pack/plugins/event_log/server/es/context.test.ts b/x-pack/plugins/event_log/server/es/context.test.ts index 681b927478d81..5cb6887af3c9b 100644 --- a/x-pack/plugins/event_log/server/es/context.test.ts +++ b/x-pack/plugins/event_log/server/es/context.test.ts @@ -34,6 +34,7 @@ describe('createEsContext', () => { test('should return is ready state as falsy if not initialized', () => { const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test0', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), @@ -48,6 +49,7 @@ describe('createEsContext', () => { test('should return esNames', () => { const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test-index', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), @@ -65,6 +67,7 @@ describe('createEsContext', () => { test('should return exist false for esAdapter index template and data stream before initialize', async () => { const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test1', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), @@ -86,6 +89,7 @@ describe('createEsContext', () => { test('should return exist true for esAdapter index template and data stream after initialize', async () => { const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test2', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), @@ -117,6 +121,7 @@ describe('createEsContext', () => { const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test2', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), @@ -134,6 +139,7 @@ describe('createEsContext', () => { jest.requireMock('./init').initializeEs.mockResolvedValue(false); const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test2', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), diff --git a/x-pack/plugins/event_log/server/es/context.ts b/x-pack/plugins/event_log/server/es/context.ts index c3301e321256e..25d978416e354 100644 --- a/x-pack/plugins/event_log/server/es/context.ts +++ b/x-pack/plugins/event_log/server/es/context.ts @@ -23,6 +23,7 @@ export interface EsContext { waitTillReady(): Promise<boolean>; readonly initialized: boolean; readonly retryDelay: number; + shouldSetExistingAssetsToHidden: boolean; } export interface EsError { @@ -38,6 +39,7 @@ export interface EsContextCtorParams { logger: Logger; indexNameRoot: string; kibanaVersion: string; + shouldSetExistingAssetsToHidden: boolean; elasticsearchClientPromise: Promise<ElasticsearchClient>; } @@ -48,6 +50,7 @@ class EsContextImpl implements EsContext { private readonly readySignal: ReadySignal<boolean>; public initialized: boolean; public readonly retryDelay: number; + public readonly shouldSetExistingAssetsToHidden: boolean; constructor(params: EsContextCtorParams) { this.logger = params.logger; @@ -55,6 +58,7 @@ class EsContextImpl implements EsContext { this.readySignal = createReadySignal(); this.initialized = false; this.retryDelay = RETRY_DELAY; + this.shouldSetExistingAssetsToHidden = params.shouldSetExistingAssetsToHidden; this.esAdapter = new ClusterClientAdapter({ logger: params.logger, elasticsearchClientPromise: params.elasticsearchClientPromise, diff --git a/x-pack/plugins/event_log/server/es/init.test.ts b/x-pack/plugins/event_log/server/es/init.test.ts index 7c81ae80b8823..8cf2b808b8939 100644 --- a/x-pack/plugins/event_log/server/es/init.test.ts +++ b/x-pack/plugins/event_log/server/es/init.test.ts @@ -74,6 +74,12 @@ describe('initializeEs', () => { expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).not.toHaveBeenCalled(); }); + test(`should not read or update existing index templates when specifying shouldSetExistingAssetsToHidden=false`, async () => { + await initializeEs({ ...esContext, shouldSetExistingAssetsToHidden: false }); + expect(esContext.esAdapter.getExistingLegacyIndexTemplates).not.toHaveBeenCalled(); + expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).not.toHaveBeenCalled(); + }); + test(`should continue initialization if getting existing index templates throws an error`, async () => { esContext.esAdapter.getExistingLegacyIndexTemplates.mockRejectedValue(new Error('Fail')); @@ -198,6 +204,12 @@ describe('initializeEs', () => { expect(esContext.esAdapter.setIndexToHidden).not.toHaveBeenCalled(); }); + test(`should not read or update existing index settings when specifying shouldSetExistingAssetsToHidden=false`, async () => { + await initializeEs({ ...esContext, shouldSetExistingAssetsToHidden: false }); + expect(esContext.esAdapter.getExistingIndices).not.toHaveBeenCalled(); + expect(esContext.esAdapter.setIndexToHidden).not.toHaveBeenCalled(); + }); + test(`should continue initialization if getting existing index settings throws an error`, async () => { esContext.esAdapter.getExistingIndices.mockRejectedValue(new Error('Fail')); @@ -287,6 +299,12 @@ describe('initializeEs', () => { expect(esContext.esAdapter.setIndexAliasToHidden).not.toHaveBeenCalled(); }); + test(`should not read or update existing index aliases when specifying shouldSetExistingAssetsToHidden=false`, async () => { + await initializeEs({ ...esContext, shouldSetExistingAssetsToHidden: false }); + expect(esContext.esAdapter.getExistingIndexAliases).not.toHaveBeenCalled(); + expect(esContext.esAdapter.setIndexAliasToHidden).not.toHaveBeenCalled(); + }); + test(`should continue initialization if getting existing index aliases throws an error`, async () => { esContext.esAdapter.getExistingIndexAliases.mockRejectedValue(new Error('Fail')); diff --git a/x-pack/plugins/event_log/server/es/init.ts b/x-pack/plugins/event_log/server/es/init.ts index cf737cbf035c6..b0257f3270a55 100644 --- a/x-pack/plugins/event_log/server/es/init.ts +++ b/x-pack/plugins/event_log/server/es/init.ts @@ -31,8 +31,11 @@ export async function initializeEs(esContext: EsContext): Promise<boolean> { async function initializeEsResources(esContext: EsContext) { const steps = new EsInitializationSteps(esContext); - // today, setExistingAssetsToHidden() never throws, but just in case ... - await retry(steps.setExistingAssetsToHidden); + // Only set existing assets to hidden if we're not in serverless + if (esContext.shouldSetExistingAssetsToHidden) { + // today, setExistingAssetsToHidden() never throws, but just in case ... + await retry(steps.setExistingAssetsToHidden); + } await retry(steps.createIndexTemplateIfNotExists); await retry(steps.createDataStreamIfNotExists); diff --git a/x-pack/plugins/event_log/server/plugin.test.ts b/x-pack/plugins/event_log/server/plugin.test.ts index fcfd921557645..35e02459010b1 100644 --- a/x-pack/plugins/event_log/server/plugin.test.ts +++ b/x-pack/plugins/event_log/server/plugin.test.ts @@ -18,7 +18,8 @@ describe('event_log plugin', () => { const coreStart = coreMock.createStart() as CoreStart; const plugin = new Plugin(initializerContext); - const setup = plugin.setup(coreSetup); + // serverless setup is currently empty, and there is no mock + const setup = plugin.setup(coreSetup, { serverless: {} }); expect(typeof setup.getLogger).toBe('function'); expect(typeof setup.getProviderActions).toBe('function'); expect(typeof setup.isIndexingEntries).toBe('function'); @@ -40,7 +41,8 @@ describe('event_log plugin', () => { const plugin = new Plugin(initializerContext); const spaces = spacesMock.createStart(); - plugin.setup(coreSetup); + // serverless setup is currently empty, and there is no mock + plugin.setup(coreSetup, { serverless: {} }); plugin.start(coreStart, { spaces }); await plugin.stop(); expect(mockLogger.debug).toBeCalledWith('shutdown: waiting to finish'); diff --git a/x-pack/plugins/event_log/server/plugin.ts b/x-pack/plugins/event_log/server/plugin.ts index 9c96e2ae8073a..7bd9291ab4091 100644 --- a/x-pack/plugins/event_log/server/plugin.ts +++ b/x-pack/plugins/event_log/server/plugin.ts @@ -14,6 +14,7 @@ import { IClusterClient, } from '@kbn/core/server'; import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; +import { ServerlessPluginSetup } from '@kbn/serverless/server'; import type { IEventLogConfig, @@ -35,6 +36,10 @@ const ACTIONS = { stopping: 'stopping', }; +interface PluginSetupDeps { + serverless?: ServerlessPluginSetup; +} + interface PluginStartDeps { spaces?: SpacesPluginStart; } @@ -56,7 +61,7 @@ export class Plugin implements CorePlugin<IEventLogService, IEventLogClientServi this.kibanaVersion = this.context.env.packageInfo.version; } - setup(core: CoreSetup): IEventLogService { + setup(core: CoreSetup, plugins: PluginSetupDeps): IEventLogService { const kibanaIndex = core.savedObjects.getDefaultIndex(); this.systemLogger.debug('setting up plugin'); @@ -67,6 +72,8 @@ export class Plugin implements CorePlugin<IEventLogService, IEventLogClientServi .getStartServices() .then(([{ elasticsearch }]) => elasticsearch.client.asInternalUser), kibanaVersion: this.kibanaVersion, + // Only non-serverless deployments may have assets that need to be converted + shouldSetExistingAssetsToHidden: !plugins.serverless, }); this.eventLogService = new EventLogService({ diff --git a/x-pack/plugins/event_log/tsconfig.json b/x-pack/plugins/event_log/tsconfig.json index 4f69e9cce2886..cec36c8f2b785 100644 --- a/x-pack/plugins/event_log/tsconfig.json +++ b/x-pack/plugins/event_log/tsconfig.json @@ -20,6 +20,7 @@ "@kbn/utility-types", "@kbn/std", "@kbn/safer-lodash-set", + "@kbn/serverless", ], "exclude": [ "target/**/*", From f8ad13ae1f078aa5f0cb6e1190e3c167dec168c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Kopyci=C5=84ski?= <contact@patrykkopycinski.com> Date: Mon, 28 Aug 2023 20:21:43 +0200 Subject: [PATCH 33/49] [security_solution_cypress] Add support for options in EsArchiver.load (#164988) ## Summary Needed for https://github.com/elastic/kibana/pull/160572#issuecomment-1695775316 --- .../cypress/e2e/detection_alerts/alert_tags.cy.ts | 2 +- .../e2e/detection_alerts/cti_enrichments.cy.ts | 6 +++--- .../cypress/e2e/detection_alerts/enrichments.cy.ts | 6 +++--- .../detection_alerts/ransomware_detection.cy.ts | 4 +++- .../detection_alerts/ransomware_prevention.cy.ts | 6 +++++- .../rule_creation/event_correlation_rule.cy.ts | 2 +- .../rule_creation/indicator_match_rule.cy.ts | 4 ++-- .../entity_analytics_management_page.cy.ts | 2 +- .../alerts_table_flow/endpoint_exceptions.cy.ts | 2 +- .../auto_populate_with_alert_data.cy.ts | 2 +- .../closing_all_matching_alerts.cy.ts | 2 +- .../e2e/exceptions/entry/flyout_validation.cy.ts | 6 +++--- .../e2e/exceptions/entry/use_value_list.cy.ts | 2 +- .../add_edit_endpoint_exception.cy.ts | 2 +- .../rule_details_flow/add_edit_exception.cy.ts | 4 ++-- .../add_edit_exception_data_view.cy.ts | 4 ++-- .../manage_exceptions.cy.ts | 2 +- .../e2e/explore/dashboards/entity_analytics.cy.ts | 14 +++++++------- .../e2e/explore/host_details/risk_tab.cy.ts | 2 +- .../cypress/e2e/explore/hosts/events_viewer.cy.ts | 2 +- .../cypress/e2e/explore/hosts/host_risk_tab.cy.ts | 2 +- .../e2e/explore/hosts/hosts_risk_column.cy.ts | 2 +- .../e2e/explore/network/hover_actions.cy.ts | 2 +- .../e2e/explore/network/overflow_items.cy.ts | 2 +- .../cypress/e2e/explore/overview/overview.cy.ts | 4 ++-- .../e2e/explore/pagination/pagination.cy.ts | 4 ++-- .../cypress/e2e/explore/users/users_tabs.cy.ts | 4 ++-- .../cypress/e2e/inspect/inspect_button.cy.ts | 4 ++-- .../alerts/alert_table_action_column.cy.ts | 4 +++- .../e2e/investigations/alerts/alerts_details.cy.ts | 6 +++--- .../alerts/building_block_alerts.cy.ts | 2 +- .../alerts/changing_alert_status.cy.ts | 2 +- .../timelines/bulk_add_to_timeline.cy.ts | 2 +- .../e2e/investigations/timelines/pagination.cy.ts | 2 +- .../cypress/e2e/overview/cti_link_panel.cy.ts | 2 +- .../cypress/support/es_archiver.ts | 3 ++- 36 files changed, 66 insertions(+), 57 deletions(-) diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/alert_tags.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/alert_tags.cy.ts index 39758e5a097c8..52a6afc2e4f25 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/alert_tags.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/alert_tags.cy.ts @@ -33,7 +33,7 @@ describe('Alert tagging', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { login(); deleteAlertsAndRules(); - cy.task('esArchiverLoad', 'endpoint'); + cy.task('esArchiverLoad', { archiveName: 'endpoint' }); createRule(getNewRule({ rule_id: 'new custom rule' })); visit(ALERTS_URL); waitForAlertsToPopulate(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/cti_enrichments.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/cti_enrichments.cy.ts index 27921bb9b2d70..ebf5f97bbc790 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/cti_enrichments.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/cti_enrichments.cy.ts @@ -31,8 +31,8 @@ import { addsFieldsToTimeline } from '../../tasks/rule_details'; describe('CTI Enrichment', { tags: ['@ess', '@serverless'] }, () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'threat_indicator'); - cy.task('esArchiverLoad', 'suspicious_source_event'); + cy.task('esArchiverLoad', { archiveName: 'threat_indicator' }); + cy.task('esArchiverLoad', { archiveName: 'suspicious_source_event' }); login(); createRule({ ...getNewThreatIndicatorRule(), rule_id: 'rule_testing', enabled: true }); disableExpandableFlyout(); @@ -155,7 +155,7 @@ describe('CTI Enrichment', { tags: ['@ess', '@serverless'] }, () => { describe('with additional indicators', () => { before(() => { - cy.task('esArchiverLoad', 'threat_indicator2'); + cy.task('esArchiverLoad', { archiveName: 'threat_indicator2' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/enrichments.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/enrichments.cy.ts index 3cf0665795cf6..d427a7e3d43a4 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/enrichments.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/enrichments.cy.ts @@ -33,7 +33,7 @@ import { ALERTS_URL } from '../../urls/navigation'; describe('Enrichment', { tags: ['@ess', '@serverless'] }, () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'risk_users'); + cy.task('esArchiverLoad', { archiveName: 'risk_users' }); }); after(() => { @@ -43,7 +43,7 @@ describe('Enrichment', { tags: ['@ess', '@serverless'] }, () => { describe('Custom query rule', () => { beforeEach(() => { disableExpandableFlyout(); - cy.task('esArchiverLoad', 'risk_hosts'); + cy.task('esArchiverLoad', { archiveName: 'risk_hosts' }); deleteAlertsAndRules(); createRule(getNewRule({ rule_id: 'rule1' })); login(); @@ -75,7 +75,7 @@ describe('Enrichment', { tags: ['@ess', '@serverless'] }, () => { closeAlertFlyout(); cy.task('esArchiverUnload', 'risk_hosts'); - cy.task('esArchiverLoad', 'risk_hosts_updated'); + cy.task('esArchiverLoad', { archiveName: 'risk_hosts_updated' }); expandFirstAlert(); cy.get(ENRICHED_DATA_ROW).contains('Critical'); cy.get(ENRICHED_DATA_ROW).contains('Original host risk classification'); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/ransomware_detection.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/ransomware_detection.cy.ts index 93e0ce8ba8f4e..236a23da8e71d 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/ransomware_detection.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/ransomware_detection.cy.ts @@ -16,7 +16,9 @@ import { createTimeline } from '../../tasks/timelines'; describe('Ransomware Detection Alerts', { tags: ['@ess', '@serverless'] }, () => { before(() => { - cy.task('esArchiverLoad', 'ransomware_detection'); + cy.task('esArchiverLoad', { + archiveName: 'ransomware_detection', + }); }); describe('Ransomware display in Alerts Section', () => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/ransomware_prevention.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/ransomware_prevention.cy.ts index 4f6379b3a6bd9..ea80743898686 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/ransomware_prevention.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/ransomware_prevention.cy.ts @@ -13,10 +13,14 @@ import { ALERTS_HISTOGRAM_SERIES, ALERT_RULE_NAME, MESSAGE } from '../../screens import { TIMELINE_QUERY, TIMELINE_VIEW_IN_ANALYZER } from '../../screens/timeline'; import { selectAlertsHistogram } from '../../tasks/alerts'; import { createTimeline } from '../../tasks/timelines'; +import { cleanKibana } from '../../tasks/common'; describe('Ransomware Prevention Alerts', { tags: ['@ess', '@serverless'] }, () => { before(() => { - cy.task('esArchiverLoad', 'ransomware_prevention'); + cleanKibana(); + cy.task('esArchiverLoad', { + archiveName: 'ransomware_prevention', + }); }); after(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/event_correlation_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/event_correlation_rule.cy.ts index 73e501009656a..a767fe7b533e2 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/event_correlation_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/event_correlation_rule.cy.ts @@ -151,7 +151,7 @@ describe('EQL rules', { tags: ['@ess', '@brokenInServerless'] }, () => { const rule = getEqlSequenceRule(); beforeEach(() => { - cy.task('esArchiverLoad', 'auditbeat_big'); + cy.task('esArchiverLoad', { archiveName: 'auditbeat_big' }); }); afterEach(() => { cy.task('esArchiverUnload', 'auditbeat_big'); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/indicator_match_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/indicator_match_rule.cy.ts index b78d67d58980a..6174d07e8ad5d 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/indicator_match_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/indicator_match_rule.cy.ts @@ -120,8 +120,8 @@ describe('indicator match', { tags: ['@ess', '@brokenInServerless'] }, () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'threat_indicator'); - cy.task('esArchiverLoad', 'suspicious_source_event'); + cy.task('esArchiverLoad', { archiveName: 'threat_indicator' }); + cy.task('esArchiverLoad', { archiveName: 'suspicious_source_event' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts index ae83f8b769b17..36bc18210863f 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts @@ -50,7 +50,7 @@ describe( () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'all_users'); + cy.task('esArchiverLoad', { archiveName: 'all_users' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts index 05dfb695956b5..920ddd62909b3 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts @@ -54,7 +54,7 @@ describe.skip( cy.task('esArchiverResetKibana'); login(); deleteAlertsAndRules(); - cy.task('esArchiverLoad', 'endpoint'); + cy.task('esArchiverLoad', { archiveName: 'endpoint' }); createRule(getEndpointRule()); visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); goToRuleDetails(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/auto_populate_with_alert_data.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/auto_populate_with_alert_data.cy.ts index 82cfc48100402..14d002b96b7b4 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/auto_populate_with_alert_data.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/auto_populate_with_alert_data.cy.ts @@ -50,7 +50,7 @@ describe.skip( beforeEach(() => { cy.task('esArchiverUnload', 'endpoint'); cy.task('esArchiverResetKibana'); - cy.task('esArchiverLoad', 'endpoint'); + cy.task('esArchiverLoad', { archiveName: 'endpoint' }); login(); createRule(getEndpointRule()); visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/closing_all_matching_alerts.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/closing_all_matching_alerts.cy.ts index ea905a7774126..9c4a575dccb4e 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/closing_all_matching_alerts.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/closing_all_matching_alerts.cy.ts @@ -36,7 +36,7 @@ describe('Close matching Alerts ', () => { cy.task('esArchiverUnload', 'exceptions'); cy.task('esArchiverResetKibana'); deleteAlertsAndRules(); - cy.task('esArchiverLoad', 'exceptions'); + cy.task('esArchiverLoad', { archiveName: 'exceptions' }); login(); postDataView('exceptions-*'); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/flyout_validation.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/flyout_validation.cy.ts index 078f743e1cea7..e11cace87d8e8 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/flyout_validation.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/flyout_validation.cy.ts @@ -71,10 +71,10 @@ describe.skip('Exceptions flyout', { tags: ['@ess', '@serverless'] }, () => { // this is a made-up index that has just the necessary // mappings to conduct tests, avoiding loading large // amounts of data like in auditbeat_exceptions - cy.task('esArchiverLoad', 'exceptions'); + cy.task('esArchiverLoad', { archiveName: 'exceptions' }); // Comment the Conflicts here as they are skipped - // cy.task('esArchiverLoad', 'conflicts_1'); - // cy.task('esArchiverLoad', 'conflicts_2'); + // cy.task('esArchiverLoad',{ archiveName: 'conflicts_1' }); + // cy.task('esArchiverLoad',{ archiveName: 'conflicts_2' }); login(); createExceptionList(getExceptionList(), getExceptionList().list_id).then((response) => createRule( diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts index 51f0e954f63ce..e45484e5fb834 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts @@ -54,7 +54,7 @@ describe('Use Value list in exception entry', { tags: ['@ess', '@serverless'] }, before(() => { cleanKibana(); login(); - cy.task('esArchiverLoad', 'exceptions'); + cy.task('esArchiverLoad', { archiveName: 'exceptions' }); createRule({ ...getNewRule(), query: 'user.name:*', diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts index 47f6717fa3143..cdf0b56347063 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts @@ -49,7 +49,7 @@ describe('Add endpoint exception from rule details', { tags: ['@ess', '@serverle before(() => { cy.task('esArchiverResetKibana'); - cy.task('esArchiverLoad', 'auditbeat'); + cy.task('esArchiverLoad', { archiveName: 'auditbeat' }); login(); deleteAlertsAndRules(); // create rule with exception diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception.cy.ts index 6a51085df468b..18537145ec582 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception.cy.ts @@ -66,7 +66,7 @@ describe('Add/edit exception from rule details', { tags: ['@ess', '@brokenInServ before(() => { cy.task('esArchiverResetKibana'); - cy.task('esArchiverLoad', 'exceptions'); + cy.task('esArchiverLoad', { archiveName: 'exceptions' }); login(); }); @@ -319,7 +319,7 @@ describe('Add/edit exception from rule details', { tags: ['@ess', '@brokenInServ cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist'); // load more docs - cy.task('esArchiverLoad', 'exceptions_2'); + cy.task('esArchiverLoad', { archiveName: 'exceptions_2' }); // now that there are no more exceptions, the docs should match and populate alerts goToAlertsTab(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception_data_view.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception_data_view.cy.ts index ada21eb844450..229cfce25b9fa 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception_data_view.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception_data_view.cy.ts @@ -50,7 +50,7 @@ describe( before(() => { cy.task('esArchiverResetKibana'); - cy.task('esArchiverLoad', 'exceptions'); + cy.task('esArchiverLoad', { archiveName: 'exceptions' }); login(); postDataView('exceptions-*'); }); @@ -117,7 +117,7 @@ describe( cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist'); // load more docs - cy.task('esArchiverLoad', 'exceptions_2'); + cy.task('esArchiverLoad', { archiveName: 'exceptions_2' }); // now that there are no more exceptions, the docs should match and populate alerts goToAlertsTab(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts index 7f343b46a3467..5c9b93ed1507b 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts @@ -41,7 +41,7 @@ import { describe('Add, edit and delete exception', { tags: ['@ess', '@serverless'] }, () => { before(() => { cy.task('esArchiverResetKibana'); - cy.task('esArchiverLoad', 'exceptions'); + cy.task('esArchiverLoad', { archiveName: 'exceptions' }); createRule(getNewRule()); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/dashboards/entity_analytics.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/dashboards/entity_analytics.cy.ts index cea38567dbf70..07c14cf9f5e8f 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/dashboards/entity_analytics.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/dashboards/entity_analytics.cy.ts @@ -77,8 +77,8 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@brokenInServerless'] } describe('Risk Score enabled but still no data', () => { before(() => { - cy.task('esArchiverLoad', 'risk_hosts_no_data'); - cy.task('esArchiverLoad', 'risk_users_no_data'); + cy.task('esArchiverLoad', { archiveName: 'risk_hosts_no_data' }); + cy.task('esArchiverLoad', { archiveName: 'risk_users_no_data' }); }); beforeEach(() => { @@ -102,8 +102,8 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@brokenInServerless'] } describe('With Legacy data', () => { before(() => { - cy.task('esArchiverLoad', 'risk_hosts_legacy_data'); - cy.task('esArchiverLoad', 'risk_users_legacy_data'); + cy.task('esArchiverLoad', { archiveName: 'risk_hosts_legacy_data' }); + cy.task('esArchiverLoad', { archiveName: 'risk_users_legacy_data' }); }); beforeEach(() => { @@ -127,7 +127,7 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@brokenInServerless'] } describe('With host risk data', () => { before(() => { - cy.task('esArchiverLoad', 'risk_hosts'); + cy.task('esArchiverLoad', { archiveName: 'risk_hosts' }); }); beforeEach(() => { @@ -215,7 +215,7 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@brokenInServerless'] } describe('With user risk data', () => { before(() => { - cy.task('esArchiverLoad', 'risk_users'); + cy.task('esArchiverLoad', { archiveName: 'risk_users' }); }); beforeEach(() => { @@ -304,7 +304,7 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@brokenInServerless'] } describe('With anomalies data', () => { before(() => { - cy.task('esArchiverLoad', 'network'); + cy.task('esArchiverLoad', { archiveName: 'network' }); login(); visit(ENTITY_ANALYTICS_URL); cy.get(ANOMALIES_TABLE).should('be.visible'); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/host_details/risk_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/host_details/risk_tab.cy.ts index cdfd01c034c33..aed7de2110ba6 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/host_details/risk_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/host_details/risk_tab.cy.ts @@ -13,7 +13,7 @@ import { TABLE_CELL, TABLE_ROWS } from '../../../screens/alerts_details'; describe('risk tab', { tags: ['@ess', '@serverless'] }, () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'risk_hosts'); + cy.task('esArchiverLoad', { archiveName: 'risk_hosts' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/events_viewer.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/events_viewer.cy.ts index 95976d90f9557..d8115e40cbb20 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/events_viewer.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/events_viewer.cy.ts @@ -47,7 +47,7 @@ const defaultHeadersInDefaultEcsCategory = [ describe('Events Viewer', { tags: ['@ess', '@brokenInServerless'] }, () => { before(() => { - cy.task('esArchiverLoad', 'auditbeat_big'); + cy.task('esArchiverLoad', { archiveName: 'auditbeat_big' }); }); after(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/host_risk_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/host_risk_tab.cy.ts index ce59d0de0b9ad..1a64f741ebeff 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/host_risk_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/host_risk_tab.cy.ts @@ -24,7 +24,7 @@ import { clearSearchBar, kqlSearch } from '../../../tasks/security_header'; describe('risk tab', { tags: ['@ess', '@brokenInServerless'] }, () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'risk_hosts'); + cy.task('esArchiverLoad', { archiveName: 'risk_hosts' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/hosts_risk_column.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/hosts_risk_column.cy.ts index 664e5767dc2b9..77593f429b1d4 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/hosts_risk_column.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/hosts_risk_column.cy.ts @@ -15,7 +15,7 @@ import { kqlSearch } from '../../../tasks/security_header'; describe('All hosts table', { tags: ['@ess', '@serverless'] }, () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'risk_hosts'); + cy.task('esArchiverLoad', { archiveName: 'risk_hosts' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/hover_actions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/hover_actions.cy.ts index 036fd908a8f0d..4f634ebc3ce2f 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/hover_actions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/hover_actions.cy.ts @@ -32,7 +32,7 @@ describe.skip('Hover actions', { tags: ['@ess', '@serverless'] }, () => { }; before(() => { - cy.task('esArchiverLoad', 'network'); + cy.task('esArchiverLoad', { archiveName: 'network' }); }); after(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/overflow_items.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/overflow_items.cy.ts index 71bdd66b9b381..9ac413d75a6d2 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/overflow_items.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/overflow_items.cy.ts @@ -25,7 +25,7 @@ const testDomainTwo = 'myTest2'; describe('Overflow items', { tags: ['@ess', '@serverless'] }, () => { context('Network stats and tables', () => { before(() => { - cy.task('esArchiverLoad', 'network'); + cy.task('esArchiverLoad', { archiveName: 'network' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/overview/overview.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/overview/overview.cy.ts index eec86830718a7..514569c2c1667 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/overview/overview.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/overview/overview.cy.ts @@ -19,7 +19,7 @@ import { getTimeline } from '../../../objects/timeline'; describe('Overview Page', { tags: ['@ess', '@serverless'] }, () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'overview'); + cy.task('esArchiverLoad', { archiveName: 'overview' }); }); beforeEach(() => { @@ -69,7 +69,7 @@ describe('Overview page with no data', { tags: '@brokenInServerless' }, () => { cy.task('esArchiverUnload', 'auditbeat'); }); after(() => { - cy.task('esArchiverLoad', 'auditbeat'); + cy.task('esArchiverLoad', { archiveName: 'auditbeat' }); }); it('Splash screen should be here', () => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/pagination/pagination.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/pagination/pagination.cy.ts index 3f9b31b819c42..1e7f7d7514404 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/pagination/pagination.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/pagination/pagination.cy.ts @@ -23,7 +23,7 @@ import { goToTablePage, sortFirstTableColumn } from '../../../tasks/table_pagina describe('Pagination', { tags: ['@ess', '@serverless'] }, () => { describe('Host uncommon processes table)', () => { before(() => { - cy.task('esArchiverLoad', 'host_uncommon_processes'); + cy.task('esArchiverLoad', { archiveName: 'host_uncommon_processes' }); }); beforeEach(() => { @@ -99,7 +99,7 @@ describe('Pagination', { tags: ['@ess', '@serverless'] }, () => { describe('All users and all Hosts tables', () => { before(() => { - cy.task('esArchiverLoad', 'all_users'); + cy.task('esArchiverLoad', { archiveName: 'all_users' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/users/users_tabs.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/users/users_tabs.cy.ts index 34401c1743cd9..5b655be068ea9 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/users/users_tabs.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/users/users_tabs.cy.ts @@ -22,9 +22,9 @@ import { USERS_URL } from '../../../urls/navigation'; describe('Users stats and tables', () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'users'); + cy.task('esArchiverLoad', { archiveName: 'users' }); - cy.task('esArchiverLoad', 'risk_users'); + cy.task('esArchiverLoad', { archiveName: 'risk_users' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/inspect/inspect_button.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/inspect/inspect_button.cy.ts index 209422bcf7eb7..fd9fc56c95fc4 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/inspect/inspect_button.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/inspect/inspect_button.cy.ts @@ -24,8 +24,8 @@ const DATA_VIEW = 'auditbeat-*'; describe('Inspect Explore pages', { tags: ['@ess', '@serverless'] }, () => { before(() => { - cy.task('esArchiverLoad', 'risk_users'); - cy.task('esArchiverLoad', 'risk_hosts'); + cy.task('esArchiverLoad', { archiveName: 'risk_users' }); + cy.task('esArchiverLoad', { archiveName: 'risk_hosts' }); login(); // Create and select data view diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alert_table_action_column.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alert_table_action_column.cy.ts index a8acec0019db6..975fdb3ee1d59 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alert_table_action_column.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alert_table_action_column.cy.ts @@ -18,7 +18,9 @@ import { ALERTS_URL } from '../../../urls/navigation'; describe('Alerts Table Action column', { tags: ['@ess', '@serverless'] }, () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'process_ancestry'); + cy.task('esArchiverLoad', { + archiveName: 'process_ancestry', + }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts index d4ecaf16df975..470c8494386e1 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts @@ -60,7 +60,7 @@ describe('Alert details flyout', { tags: ['@ess', '@serverless'] }, () => { describe('With unmapped fields', () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'unmapped_fields'); + cy.task('esArchiverLoad', { archiveName: 'unmapped_fields' }); createRule(getUnmappedRule()); }); @@ -126,7 +126,7 @@ describe('Alert details flyout', { tags: ['@ess', '@serverless'] }, () => { describe('Url state management', () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'query_alert'); + cy.task('esArchiverLoad', { archiveName: 'query_alert' }); }); beforeEach(() => { @@ -172,7 +172,7 @@ describe('Alert details flyout', { tags: ['@ess', '@serverless'] }, () => { describe('Localstorage management', () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'query_alert'); + cy.task('esArchiverLoad', { archiveName: 'query_alert' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts index 6d3dc872e9c3c..0ed530adad451 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts @@ -27,7 +27,7 @@ describe( { tags: ['@ess', '@brokenInServerless'] }, () => { before(() => { - cy.task('esArchiverLoad', 'auditbeat_big'); + cy.task('esArchiverLoad', { archiveName: 'auditbeat_big' }); cleanKibana(); login(); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/changing_alert_status.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/changing_alert_status.cy.ts index 6eb08bb5930a0..d7aa5040072cc 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/changing_alert_status.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/changing_alert_status.cy.ts @@ -40,7 +40,7 @@ import { ALERTS_URL } from '../../../urls/navigation'; describe('Changing alert status', { tags: ['@ess', '@brokenInServerless'] }, () => { before(() => { - cy.task('esArchiverLoad', 'auditbeat_big'); + cy.task('esArchiverLoad', { archiveName: 'auditbeat_big' }); cleanKibana(); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/bulk_add_to_timeline.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/bulk_add_to_timeline.cy.ts index 3470c21aa0ed3..3ba223097023a 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/bulk_add_to_timeline.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/bulk_add_to_timeline.cy.ts @@ -25,7 +25,7 @@ import { ALERTS_URL, HOSTS_URL } from '../../../urls/navigation'; describe('Bulk Investigate in Timeline', { tags: ['@ess', '@serverless'] }, () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'bulk_process'); + cy.task('esArchiverLoad', { archiveName: 'bulk_process' }); login(); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/pagination.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/pagination.cy.ts index a92956be8e134..a8ab36c7bd837 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/pagination.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/pagination.cy.ts @@ -26,7 +26,7 @@ const defaultPageSize = 25; describe('Pagination', { tags: ['@ess', '@serverless'] }, () => { before(() => { cleanKibana(); - cy.task('esArchiverLoad', 'timeline'); + cy.task('esArchiverLoad', { archiveName: 'timeline' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/overview/cti_link_panel.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/overview/cti_link_panel.cy.ts index fd41df836216d..eb6548a5e5834 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/overview/cti_link_panel.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/overview/cti_link_panel.cy.ts @@ -32,7 +32,7 @@ describe('CTI Link Panel', { tags: ['@ess', '@serverless'] }, () => { describe('enabled threat intel module', () => { before(() => { - cy.task('esArchiverLoad', 'threat_indicator'); + cy.task('esArchiverLoad', { archiveName: 'threat_indicator' }); }); beforeEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/support/es_archiver.ts b/x-pack/test/security_solution_cypress/cypress/support/es_archiver.ts index 42ddb4a526387..bf2277c95e289 100644 --- a/x-pack/test/security_solution_cypress/cypress/support/es_archiver.ts +++ b/x-pack/test/security_solution_cypress/cypress/support/es_archiver.ts @@ -34,7 +34,8 @@ export const esArchiver = ( }); on('task', { - esArchiverLoad: async (archiveName) => esArchiverInstance.load(archiveName), + esArchiverLoad: async ({ archiveName, ...options }) => + esArchiverInstance.load(archiveName, options), esArchiverUnload: async (archiveName) => esArchiverInstance.unload(archiveName), esArchiverResetKibana: async () => esArchiverInstance.emptyKibanaIndex(), }); From eaf9269667db66a5b69eb137e3444830b8b33cb6 Mon Sep 17 00:00:00 2001 From: Lisa Cawley <lcawley@elastic.co> Date: Mon, 28 Aug 2023 11:25:53 -0700 Subject: [PATCH 34/49] [OAS] Add more Elasticsearch query rule examples (#164386) --- .../alerting/docs/openapi/bundled.json | 149 +++++++++++++++++- .../alerting/docs/openapi/bundled.yaml | 114 +++++++++++++- .../create_es_query_kql_rule_request.yaml | 23 +++ .../create_es_query_kql_rule_response.yaml | 43 +++++ .../create_es_query_rule_request.yaml | 43 +++-- .../create_es_query_rule_response.yaml | 65 +++++--- .../paths/s@{spaceid}@api@alerting@rule.yaml | 4 + ...@{spaceid}@api@alerting@rule@{ruleid}.yaml | 4 + 8 files changed, 404 insertions(+), 41 deletions(-) create mode 100644 x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_request.yaml create mode 100644 x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_response.yaml diff --git a/x-pack/plugins/alerting/docs/openapi/bundled.json b/x-pack/plugins/alerting/docs/openapi/bundled.json index ad42d43569b82..7a169c842a8e6 100644 --- a/x-pack/plugins/alerting/docs/openapi/bundled.json +++ b/x-pack/plugins/alerting/docs/openapi/bundled.json @@ -60,6 +60,9 @@ "createEsQueryRuleRequest": { "$ref": "#/components/examples/create_es_query_rule_request" }, + "createEsQueryKqlRuleRequest": { + "$ref": "#/components/examples/create_es_query_kql_rule_request" + }, "createIndexThresholdRuleRequest": { "$ref": "#/components/examples/create_index_threshold_rule_request" } @@ -79,6 +82,9 @@ "createEsQueryRuleResponse": { "$ref": "#/components/examples/create_es_query_rule_response" }, + "createEsQueryKqlRuleResponse": { + "$ref": "#/components/examples/create_es_query_kql_rule_response" + }, "createIndexThresholdRuleResponse": { "$ref": "#/components/examples/create_index_threshold_rule_response" } @@ -263,6 +269,9 @@ "createEsQueryRuleIdRequest": { "$ref": "#/components/examples/create_es_query_rule_request" }, + "createEsQueryKqlRuleIdRequest": { + "$ref": "#/components/examples/create_es_query_kql_rule_request" + }, "createIndexThreholdRuleIdRequest": { "$ref": "#/components/examples/create_index_threshold_rule_request" } @@ -282,6 +291,9 @@ "createEsQueryRuleIdResponse": { "$ref": "#/components/examples/create_es_query_rule_response" }, + "createEsQueryKqlRuleIdResponse": { + "$ref": "#/components/examples/create_es_query_kql_rule_response" + }, "createIndexThresholdRuleIdResponse": { "$ref": "#/components/examples/create_index_threshold_rule_response" } @@ -6790,10 +6802,62 @@ }, "examples": { "create_es_query_rule_request": { - "summary": "Create an Elasticsearch query rule.", + "summary": "Create an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL) to define its query and a server log connector to send notifications.", "value": { + "actions": [ + { + "group": "query matched", + "params": { + "level": "info", + "message": "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts." + }, + "id": "fdbece50-406c-11ee-850e-c71febc4ca7f", + "frequency": { + "throttle": "1d", + "summary": true, + "notify_when": "onThrottleInterval" + } + }, + { + "group": "recovered", + "params": { + "level": "info", + "message": "Recovered" + }, + "id": "fdbece50-406c-11ee-850e-c71febc4ca7f", + "frequency": { + "summary": false, + "notify_when": "onActionGroupChange" + } + } + ], "consumer": "alerts", "name": "my Elasticsearch query rule", + "params": { + "esQuery": "\"\"\"{\"query\":{\"match_all\" : {}}}\"\"\"", + "index": [ + "kibana_sample_data_logs" + ], + "size": 100, + "threshold": [ + 100 + ], + "thresholdComparator": ">", + "timeField": "@timestamp", + "timeWindowSize": 1, + "timeWindowUnit": "d" + }, + "rule_type_id": ".es-query", + "schedule": { + "interval": "1d" + } + } + }, + "create_es_query_kql_rule_request": { + "summary": "Create an Elasticsearch query rule that uses Kibana query language (KQL).", + "value": { + "consumer": "alerts", + "name": "my Elasticsearch query KQL rule", "params": { "aggType": "count", "excludeHitsFromPreviousRun": true, @@ -6866,11 +6930,92 @@ } }, "create_es_query_rule_response": { + "summary": "The create rule API returns a JSON object that contains details about the rule.", + "value": { + "id": "58148c70-407f-11ee-850e-c71febc4ca7f", + "enabled": true, + "name": "my Elasticsearch query rule", + "tags": [], + "rule_type_id": ".es-query", + "consumer": "alerts", + "schedule": { + "interval": "1d" + }, + "actions": [ + { + "group": "query matched", + "id": "fdbece50-406c-11ee-850e-c71febc4ca7f", + "params": { + "level": "info", + "message": "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts." + }, + "connector_type_id": ".server-log", + "frequency": { + "summary": true, + "notify_when": "onThrottleInterval", + "throttle": "1d" + }, + "uuid": "53f3c2a3-e5d0-4cfa-af3b-6f0881385e78" + }, + { + "group": "recovered", + "id": "fdbece50-406c-11ee-850e-c71febc4ca7f", + "params": { + "level": "info", + "message": "Recovered" + }, + "connector_type_id": ".server-log", + "frequency": { + "summary": false, + "notify_when": "onActionGroupChange", + "throttle": null + }, + "uuid": "2324e45b-c0df-45c7-9d70-4993e30be758" + } + ], + "params": { + "thresholdComparator": ">", + "timeWindowSize": 1, + "timeWindowUnit": "d", + "threshold": [ + 100 + ], + "size": 100, + "timeField": "@timestamp", + "index": [ + "kibana_sample_data_logs" + ], + "esQuery": "\"\"\"{\"query\":{\"match_all\" : {}}}\"\"\"", + "excludeHitsFromPreviousRun": true, + "aggType": "count", + "groupBy": "all", + "searchType": "esQuery" + }, + "scheduled_task_id": "58148c70-407f-11ee-850e-c71febc4ca7f", + "created_by": "elastic", + "updated_by": "elastic", + "created_at": "2023-08-22T00:03:38.263Z", + "updated_at": "2023-08-22T00:03:38.263Z", + "api_key_owner": "elastic", + "api_key_created_by_user": false, + "throttle": null, + "mute_all": false, + "notify_when": null, + "muted_alert_ids": [], + "execution_status": { + "status": "pending", + "last_execution_date": "2023-08-22T00:03:38.263Z" + }, + "revision": 0, + "running": false + } + }, + "create_es_query_kql_rule_response": { "summary": "The create rule API returns a JSON object that contains details about the rule.", "value": { "id": "7bd506d0-2284-11ee-8fad-6101956ced88", "enabled": true, - "name": "my Elasticsearch query rule\"", + "name": "my Elasticsearch query KQL rule\"", "tags": [], "rule_type_id": ".es-query", "consumer": "alerts", diff --git a/x-pack/plugins/alerting/docs/openapi/bundled.yaml b/x-pack/plugins/alerting/docs/openapi/bundled.yaml index 6f328ca879b43..0465a9218f2db 100644 --- a/x-pack/plugins/alerting/docs/openapi/bundled.yaml +++ b/x-pack/plugins/alerting/docs/openapi/bundled.yaml @@ -38,6 +38,8 @@ paths: examples: createEsQueryRuleRequest: $ref: '#/components/examples/create_es_query_rule_request' + createEsQueryKqlRuleRequest: + $ref: '#/components/examples/create_es_query_kql_rule_request' createIndexThresholdRuleRequest: $ref: '#/components/examples/create_index_threshold_rule_request' responses: @@ -50,6 +52,8 @@ paths: examples: createEsQueryRuleResponse: $ref: '#/components/examples/create_es_query_rule_response' + createEsQueryKqlRuleResponse: + $ref: '#/components/examples/create_es_query_kql_rule_response' createIndexThresholdRuleResponse: $ref: '#/components/examples/create_index_threshold_rule_response' '401': @@ -158,6 +162,8 @@ paths: examples: createEsQueryRuleIdRequest: $ref: '#/components/examples/create_es_query_rule_request' + createEsQueryKqlRuleIdRequest: + $ref: '#/components/examples/create_es_query_kql_rule_request' createIndexThreholdRuleIdRequest: $ref: '#/components/examples/create_index_threshold_rule_request' responses: @@ -170,6 +176,8 @@ paths: examples: createEsQueryRuleIdResponse: $ref: '#/components/examples/create_es_query_rule_response' + createEsQueryKqlRuleIdResponse: + $ref: '#/components/examples/create_es_query_kql_rule_response' createIndexThresholdRuleIdResponse: $ref: '#/components/examples/create_index_threshold_rule_response' '401': @@ -4633,10 +4641,47 @@ components: example: elastic examples: create_es_query_rule_request: - summary: Create an Elasticsearch query rule. + summary: Create an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL) to define its query and a server log connector to send notifications. value: + actions: + - group: query matched + params: + level: info + message: The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts. + id: fdbece50-406c-11ee-850e-c71febc4ca7f + frequency: + throttle: 1d + summary: true + notify_when: onThrottleInterval + - group: recovered + params: + level: info + message: Recovered + id: fdbece50-406c-11ee-850e-c71febc4ca7f + frequency: + summary: false + notify_when: onActionGroupChange consumer: alerts name: my Elasticsearch query rule + params: + esQuery: '"""{"query":{"match_all" : {}}}"""' + index: + - kibana_sample_data_logs + size: 100 + threshold: + - 100 + thresholdComparator: '>' + timeField: '@timestamp' + timeWindowSize: 1 + timeWindowUnit: d + rule_type_id: .es-query + schedule: + interval: 1d + create_es_query_kql_rule_request: + summary: Create an Elasticsearch query rule that uses Kibana query language (KQL). + value: + consumer: alerts + name: my Elasticsearch query KQL rule params: aggType: count excludeHitsFromPreviousRun: true @@ -4695,11 +4740,76 @@ components: tags: - cpu create_es_query_rule_response: + summary: The create rule API returns a JSON object that contains details about the rule. + value: + id: 58148c70-407f-11ee-850e-c71febc4ca7f + enabled: true + name: my Elasticsearch query rule + tags: [] + rule_type_id: .es-query + consumer: alerts + schedule: + interval: 1d + actions: + - group: query matched + id: fdbece50-406c-11ee-850e-c71febc4ca7f + params: + level: info + message: The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts. + connector_type_id: .server-log + frequency: + summary: true + notify_when: onThrottleInterval + throttle: 1d + uuid: 53f3c2a3-e5d0-4cfa-af3b-6f0881385e78 + - group: recovered + id: fdbece50-406c-11ee-850e-c71febc4ca7f + params: + level: info + message: Recovered + connector_type_id: .server-log + frequency: + summary: false + notify_when: onActionGroupChange + throttle: null + uuid: 2324e45b-c0df-45c7-9d70-4993e30be758 + params: + thresholdComparator: '>' + timeWindowSize: 1 + timeWindowUnit: d + threshold: + - 100 + size: 100 + timeField: '@timestamp' + index: + - kibana_sample_data_logs + esQuery: '"""{"query":{"match_all" : {}}}"""' + excludeHitsFromPreviousRun: true + aggType: count + groupBy: all + searchType: esQuery + scheduled_task_id: 58148c70-407f-11ee-850e-c71febc4ca7f + created_by: elastic + updated_by: elastic + created_at: '2023-08-22T00:03:38.263Z' + updated_at: '2023-08-22T00:03:38.263Z' + api_key_owner: elastic + api_key_created_by_user: false + throttle: null + mute_all: false + notify_when: null + muted_alert_ids: [] + execution_status: + status: pending + last_execution_date: '2023-08-22T00:03:38.263Z' + revision: 0 + running: false + create_es_query_kql_rule_response: summary: The create rule API returns a JSON object that contains details about the rule. value: id: 7bd506d0-2284-11ee-8fad-6101956ced88 enabled: true - name: my Elasticsearch query rule" + name: my Elasticsearch query KQL rule" tags: [] rule_type_id: .es-query consumer: alerts diff --git a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_request.yaml b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_request.yaml new file mode 100644 index 0000000000000..e505fd8964463 --- /dev/null +++ b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_request.yaml @@ -0,0 +1,23 @@ +summary: Create an Elasticsearch query rule that uses Kibana query language (KQL). +value: + consumer: alerts + name: my Elasticsearch query KQL rule + params: + aggType: count + excludeHitsFromPreviousRun: true + groupBy: all + searchConfiguration: + query: + query: '""geo.src : "US" ""' + language: kuery + index: 90943e30-9a47-11e8-b64d-95841ca0b247 + searchType: searchSource + size: 100 + threshold: + - 1000 + thresholdComparator: ">" + timeWindowSize: 5 + timeWindowUnit: m + rule_type_id: .es-query + schedule: + interval: 1m diff --git a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_response.yaml b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_response.yaml new file mode 100644 index 0000000000000..0a30c4e6dd41e --- /dev/null +++ b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_response.yaml @@ -0,0 +1,43 @@ +summary: The create rule API returns a JSON object that contains details about the rule. +value: + id: 7bd506d0-2284-11ee-8fad-6101956ced88 + enabled: true + name: my Elasticsearch query KQL rule" + tags: [] + rule_type_id: .es-query + consumer: alerts + schedule: + interval: 1m + actions: [] + params: + searchConfiguration: + query: + query: '""geo.src : "US" ""' + language: kuery + index: 90943e30-9a47-11e8-b64d-95841ca0b247 + searchType: searchSource + timeWindowSize: 5 + timeWindowUnit: m + threshold: + - 1000 + thresholdComparator: ">" + size: 100 + aggType: count + groupBy: all + excludeHitsFromPreviousRun: true + created_by: elastic + updated_by: elastic + created_at: '2023-07-14T20:24:50.729Z' + updated_at: '2023-07-14T20:24:50.729Z' + api_key_owner: elastic + api_key_created_by_user: false + throttle: null + notify_when: null + mute_all: false + muted_alert_ids: [] + scheduled_task_id: 7bd506d0-2284-11ee-8fad-6101956ced88 + execution_status: + status: pending + last_execution_date: '2023-07-14T20:24:50.729Z' + revision: 0 + running: false \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_request.yaml b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_request.yaml index b17f6626b34dc..bff7a8f0bd8f6 100644 --- a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_request.yaml +++ b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_request.yaml @@ -1,23 +1,36 @@ -summary: Create an Elasticsearch query rule. +summary: Create an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL) to define its query and a server log connector to send notifications. value: + actions: + - group: query matched + params: + level: info + message: "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts." + id: fdbece50-406c-11ee-850e-c71febc4ca7f + frequency: + throttle: "1d" + summary: true + notify_when: onThrottleInterval + - group: recovered + params: + level: info + message: Recovered + id: fdbece50-406c-11ee-850e-c71febc4ca7f + frequency: + summary: false + notify_when: onActionGroupChange consumer: alerts name: my Elasticsearch query rule - params: - aggType: count - excludeHitsFromPreviousRun: true - groupBy: all - searchConfiguration: - query: - query: '""geo.src : "US" ""' - language: kuery - index: 90943e30-9a47-11e8-b64d-95841ca0b247 - searchType: searchSource + params: + esQuery: '"""{"query":{"match_all" : {}}}"""' + index: + - kibana_sample_data_logs size: 100 threshold: - - 1000 + - 100 thresholdComparator: ">" - timeWindowSize: 5 - timeWindowUnit: m + timeField: "@timestamp" + timeWindowSize: 1 + timeWindowUnit: d rule_type_id: .es-query schedule: - interval: 1m + interval: 1d \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_response.yaml b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_response.yaml index 5f24e00421a6f..9601843a42e3b 100644 --- a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_response.yaml +++ b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_response.yaml @@ -1,43 +1,64 @@ summary: The create rule API returns a JSON object that contains details about the rule. value: - id: 7bd506d0-2284-11ee-8fad-6101956ced88 + id: 58148c70-407f-11ee-850e-c71febc4ca7f enabled: true - name: my Elasticsearch query rule" + name: my Elasticsearch query rule tags: [] rule_type_id: .es-query consumer: alerts - schedule: - interval: 1m - actions: [] - params: - searchConfiguration: - query: - query: '""geo.src : "US" ""' - language: kuery - index: 90943e30-9a47-11e8-b64d-95841ca0b247 - searchType: searchSource - timeWindowSize: 5 - timeWindowUnit: m - threshold: - - 1000 + schedule: + interval: 1d + actions: + - group: query matched + id: fdbece50-406c-11ee-850e-c71febc4ca7f + params: + level: info + message: "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts." + connector_type_id: .server-log + frequency: + summary: true + notify_when: onThrottleInterval + throttle: "1d" + uuid: 53f3c2a3-e5d0-4cfa-af3b-6f0881385e78 + - group: recovered + id: fdbece50-406c-11ee-850e-c71febc4ca7f + params: + level: info + message: Recovered + connector_type_id: .server-log + frequency: + summary: false + notify_when: onActionGroupChange + throttle: null + uuid: 2324e45b-c0df-45c7-9d70-4993e30be758 + params: thresholdComparator: ">" + timeWindowSize: 1 + timeWindowUnit: d + threshold: + - 100 size: 100 + timeField: "@timestamp" + index: + - kibana_sample_data_logs + esQuery: '"""{"query":{"match_all" : {}}}"""' + excludeHitsFromPreviousRun: true aggType: count groupBy: all - excludeHitsFromPreviousRun: true + searchType: esQuery + scheduled_task_id: 58148c70-407f-11ee-850e-c71febc4ca7f created_by: elastic updated_by: elastic - created_at: '2023-07-14T20:24:50.729Z' - updated_at: '2023-07-14T20:24:50.729Z' + created_at: '2023-08-22T00:03:38.263Z' + updated_at: '2023-08-22T00:03:38.263Z' api_key_owner: elastic api_key_created_by_user: false throttle: null - notify_when: null mute_all: false + notify_when: null muted_alert_ids: [] - scheduled_task_id: 7bd506d0-2284-11ee-8fad-6101956ced88 execution_status: status: pending - last_execution_date: '2023-07-14T20:24:50.729Z' + last_execution_date: '2023-08-22T00:03:38.263Z' revision: 0 running: false \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule.yaml index 5a7ebd986a234..f88f69a437a9c 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule.yaml @@ -23,6 +23,8 @@ post: examples: createEsQueryRuleRequest: $ref: '../components/examples/create_es_query_rule_request.yaml' + createEsQueryKqlRuleRequest: + $ref: '../components/examples/create_es_query_kql_rule_request.yaml' createIndexThresholdRuleRequest: $ref: '../components/examples/create_index_threshold_rule_request.yaml' responses: @@ -35,6 +37,8 @@ post: examples: createEsQueryRuleResponse: $ref: '../components/examples/create_es_query_rule_response.yaml' + createEsQueryKqlRuleResponse: + $ref: '../components/examples/create_es_query_kql_rule_response.yaml' createIndexThresholdRuleResponse: $ref: '../components/examples/create_index_threshold_rule_response.yaml' '401': diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}.yaml index 9bfd620d9bfd5..058e825f1aac3 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}.yaml @@ -104,6 +104,8 @@ post: examples: createEsQueryRuleIdRequest: $ref: '../components/examples/create_es_query_rule_request.yaml' + createEsQueryKqlRuleIdRequest: + $ref: '../components/examples/create_es_query_kql_rule_request.yaml' createIndexThreholdRuleIdRequest: $ref: '../components/examples/create_index_threshold_rule_request.yaml' responses: @@ -116,6 +118,8 @@ post: examples: createEsQueryRuleIdResponse: $ref: '../components/examples/create_es_query_rule_response.yaml' + createEsQueryKqlRuleIdResponse: + $ref: '../components/examples/create_es_query_kql_rule_response.yaml' createIndexThresholdRuleIdResponse: $ref: '../components/examples/create_index_threshold_rule_response.yaml' '401': From 958060353193b95afe00ce50783c6c8a919f2738 Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" <christiane.heiligers@elastic.co> Date: Mon, 28 Aug 2023 11:36:27 -0700 Subject: [PATCH 35/49] Revert "[SOR] Allow optionally downgrading documents with a higher version model in API READ methods" (#164991) --- .../src/apis/find.ts | 1 - .../src/lib/apis/bulk_get.ts | 4 +- .../src/lib/apis/bulk_resolve.ts | 6 +- .../src/lib/apis/find.ts | 5 +- .../src/lib/apis/get.ts | 6 +- .../src/lib/apis/helpers/migration.ts | 13 +-- .../apis/internals/internal_bulk_resolve.ts | 11 +-- .../src/lib/apis/resolve.ts | 6 +- .../src/lib/repository.ts | 5 +- .../src/saved_objects_client.ts | 5 +- .../core-saved-objects-api-server/index.ts | 1 + .../src/apis/find.ts | 5 +- .../src/apis/get.ts | 1 - .../src/apis/index.ts | 2 +- .../src/apis/resolve.ts | 11 +++ .../src/saved_objects_client.ts | 9 ++- .../src/saved_objects_repository.ts | 9 ++- .../document_migrator.test.ts | 2 +- .../document_migrator/document_migrator.ts | 11 +-- .../zdt_2/sor_higher_version_docs.test.ts | 80 ------------------- 20 files changed, 52 insertions(+), 141 deletions(-) diff --git a/packages/core/saved-objects/core-saved-objects-api-browser/src/apis/find.ts b/packages/core/saved-objects/core-saved-objects-api-browser/src/apis/find.ts index 7dc54a9f6404b..8b2b154cb0a71 100644 --- a/packages/core/saved-objects/core-saved-objects-api-browser/src/apis/find.ts +++ b/packages/core/saved-objects/core-saved-objects-api-browser/src/apis/find.ts @@ -25,7 +25,6 @@ export type SavedObjectsFindOptions = Omit< | 'sortOrder' | 'typeToNamespacesMap' | 'migrationVersionCompatibility' - | 'downwardConversion' >; /** diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_get.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_get.ts index f45946add7132..3a135d4b73ce8 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_get.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_get.ts @@ -65,7 +65,7 @@ export const performBulkGet = async <T>( const { securityExtension, spacesExtension } = extensions; const namespace = commonHelper.getCurrentNamespace(options.namespace); - const { migrationVersionCompatibility, downwardConversion } = options; + const { migrationVersionCompatibility } = options; if (objects.length === 0) { return { saved_objects: [] }; @@ -204,7 +204,7 @@ export const performBulkGet = async <T>( const document = getSavedObjectFromSource(registry, type, id, doc, { migrationVersionCompatibility, }); - const migrated = migrationHelper.migrateStorageDocument(document, { downwardConversion }); + const migrated = migrationHelper.migrateStorageDocument(document); return migrated; }), diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_resolve.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_resolve.ts index f937f3646ec26..a18b69ec29bf6 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_resolve.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_resolve.ts @@ -10,7 +10,7 @@ import { type SavedObject, BulkResolveError } from '@kbn/core-saved-objects-serv import { SavedObjectsBulkResolveObject, SavedObjectsBulkResolveResponse, - SavedObjectsGetOptions, + SavedObjectsResolveOptions, SavedObjectsResolveResponse, } from '@kbn/core-saved-objects-api-server'; import { errorContent } from './utils'; @@ -20,7 +20,7 @@ import { incrementCounterInternal } from './internals/increment_counter_internal export interface PerformCreateParams<T = unknown> { objects: SavedObjectsBulkResolveObject[]; - options: SavedObjectsGetOptions; + options: SavedObjectsResolveOptions; } export const performBulkResolve = async <T>( @@ -52,7 +52,7 @@ export const performBulkResolve = async <T>( encryptionExtension, securityExtension, objects, - options: { ...options, namespace }, // note: Includes downwardConversion?: 'forbid' + options: { ...options, namespace }, }); const resolvedObjects = bulkResults.map<SavedObjectsResolveResponse<T>>((result) => { // extract payloads from saved object errors diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/find.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/find.ts index c46f4c3eda8ea..3346e6552646a 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/find.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/find.ts @@ -92,7 +92,6 @@ export const performFind = async <T = unknown, A = unknown>( preference, aggs, migrationVersionCompatibility, - downwardConversion, } = options; if (!type) { @@ -245,9 +244,7 @@ export const performFind = async <T = unknown, A = unknown>( }); // can't migrate a document with partial attributes if (!fields) { - savedObject = migrationHelper.migrateStorageDocument(savedObject, { - downwardConversion, - }) as SavedObject; + savedObject = migrationHelper.migrateStorageDocument(savedObject) as SavedObject; } return { ...savedObject, diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/get.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/get.ts index edc9fdcb8106e..215036f29583c 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/get.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/get.ts @@ -42,7 +42,7 @@ export const performGet = async <T>( const { securityExtension } = extensions; const namespace = commonHelper.getCurrentNamespace(options.namespace); - const { migrationVersionCompatibility, downwardConversion } = options; + const { migrationVersionCompatibility } = options; if (!allowedTypes.includes(type)) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); @@ -86,9 +86,7 @@ export const performGet = async <T>( let migrated: SavedObject<T>; try { - migrated = migrationHelper.migrateStorageDocument(document, { - downwardConversion, - }) as SavedObject<T>; + migrated = migrationHelper.migrateStorageDocument(document) as SavedObject<T>; } catch (error) { throw SavedObjectsErrorHelpers.decorateGeneralError( error, diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/migration.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/migration.ts index 42af825280f4f..c7ae86b101984 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/migration.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/migration.ts @@ -35,17 +35,8 @@ export class MigrationHelper { * Migrate the given SO document, accepting downgrades. * This function is meant to be used by read APIs (get, find) for documents fetched from the index. * It will therefore accept downgrading the document before returning it from the API. - * - * Note: to opt out of downgrades, use the downwardConversion: 'forbid' API option in READ API operations: - * get, resolve, find, bulk_get, bulk_resolve */ - migrateStorageDocument( - document: SavedObjectUnsanitizedDoc, - options: { downwardConversion?: 'allow' | 'forbid' } - ): SavedObjectUnsanitizedDoc { - return this.migrator.migrateDocument(document, { - allowDowngrade: - options?.downwardConversion && options.downwardConversion === 'forbid' ? false : true, - }); // allowDowngrade conditional on downwardConversion + migrateStorageDocument(document: SavedObjectUnsanitizedDoc): SavedObjectUnsanitizedDoc { + return this.migrator.migrateDocument(document, { allowDowngrade: true }); } } diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/internal_bulk_resolve.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/internal_bulk_resolve.ts index 57748b95ef0d5..53cb04453555c 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/internal_bulk_resolve.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/internal_bulk_resolve.ts @@ -11,7 +11,7 @@ import type { MgetResponseItem } from '@elastic/elasticsearch/lib/api/typesWithB import { isNotFoundFromUnsupportedServer } from '@kbn/core-elasticsearch-server-internal'; import type { SavedObjectsBulkResolveObject, - SavedObjectsGetOptions, + SavedObjectsResolveOptions, SavedObjectsResolveResponse, SavedObjectsIncrementCounterField, SavedObjectsIncrementCounterOptions, @@ -74,7 +74,7 @@ export interface InternalBulkResolveParams { encryptionExtension: ISavedObjectsEncryptionExtension | undefined; securityExtension: ISavedObjectsSecurityExtension | undefined; objects: SavedObjectsBulkResolveObject[]; - options?: SavedObjectsGetOptions; + options?: SavedObjectsResolveOptions; } /** @@ -120,7 +120,7 @@ export async function internalBulkResolve<T>( const validObjects = allObjects.filter(isRight); const namespace = normalizeNamespace(options.namespace); - const { migrationVersionCompatibility, downwardConversion } = options; + const { migrationVersionCompatibility } = options; const aliasDocs = await fetchAndUpdateAliases( validObjects, @@ -186,11 +186,8 @@ export async function internalBulkResolve<T>( // @ts-expect-error MultiGetHit._source is optional const object = getSavedObjectFromSource<T>(registry, objectType, objectId, doc, { migrationVersionCompatibility, - downwardConversion, }); - const migrated = migrator.migrateDocument(object, { - allowDowngrade: downwardConversion && downwardConversion === 'forbid' ? false : true, // 'forbid' => docMigrator throws on when documents have higher model versions than current. - }) as SavedObject<T>; + const migrated = migrator.migrateDocument(object, { allowDowngrade: true }) as SavedObject<T>; if (!encryptionExtension?.isEncryptableType(migrated.type)) { return migrated; diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/resolve.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/resolve.ts index 48d78181ba571..50de472546344 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/resolve.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/resolve.ts @@ -7,7 +7,7 @@ */ import { - SavedObjectsGetOptions, + SavedObjectsResolveOptions, SavedObjectsResolveResponse, } from '@kbn/core-saved-objects-api-server'; import { ApiExecutionContext } from './types'; @@ -17,7 +17,7 @@ import { incrementCounterInternal } from './internals/increment_counter_internal export interface PerformCreateParams<T = unknown> { type: string; id: string; - options: SavedObjectsGetOptions; + options: SavedObjectsResolveOptions; } export const performResolve = async <T>( @@ -51,7 +51,7 @@ export const performResolve = async <T>( encryptionExtension, securityExtension, objects: [{ type, id }], - options: { ...options, namespace }, // note: Includes downwardConversion?: 'forbid' + options: { ...options, namespace }, }); const [result] = bulkResults; if (isBulkResolveError(result)) { diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.ts index beb47219985f4..321c5811ea6d8 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.ts @@ -35,6 +35,7 @@ import type { SavedObjectsClosePointInTimeResponse, ISavedObjectsPointInTimeFinder, SavedObjectsCreatePointInTimeFinderDependencies, + SavedObjectsResolveOptions, SavedObjectsResolveResponse, SavedObjectsCollectMultiNamespaceReferencesObject, SavedObjectsUpdateObjectsSpacesObject, @@ -347,7 +348,7 @@ export class SavedObjectsRepository implements ISavedObjectsRepository { */ async bulkResolve<T = unknown>( objects: SavedObjectsBulkResolveObject[], - options: SavedObjectsGetOptions = {} + options: SavedObjectsResolveOptions = {} ): Promise<SavedObjectsBulkResolveResponse<T>> { return await performBulkResolve( { @@ -382,7 +383,7 @@ export class SavedObjectsRepository implements ISavedObjectsRepository { async resolve<T = unknown>( type: string, id: string, - options: SavedObjectsGetOptions = {} + options: SavedObjectsResolveOptions = {} ): Promise<SavedObjectsResolveResponse<T>> { return await performResolve( { diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.ts index 23f014d393ce0..925caae1061b7 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.ts @@ -31,6 +31,7 @@ import type { SavedObjectsBulkUpdateObject, ISavedObjectsPointInTimeFinder, SavedObjectsCreatePointInTimeFinderDependencies, + SavedObjectsResolveOptions, SavedObjectsResolveResponse, SavedObjectsCollectMultiNamespaceReferencesObject, SavedObjectsUpdateObjectsSpacesObject, @@ -121,7 +122,7 @@ export class SavedObjectsClient implements SavedObjectsClientContract { /** {@inheritDoc SavedObjectsClientContract.bulkResolve} */ async bulkResolve<T = unknown>( objects: SavedObjectsBulkResolveObject[], - options?: SavedObjectsGetOptions + options?: SavedObjectsResolveOptions ): Promise<SavedObjectsBulkResolveResponse<T>> { return await this._repository.bulkResolve(objects, options); } @@ -130,7 +131,7 @@ export class SavedObjectsClient implements SavedObjectsClientContract { async resolve<T = unknown>( type: string, id: string, - options: SavedObjectsGetOptions = {} + options: SavedObjectsResolveOptions = {} ): Promise<SavedObjectsResolveResponse<T>> { return await this._repository.resolve(type, id, options); } diff --git a/packages/core/saved-objects/core-saved-objects-api-server/index.ts b/packages/core/saved-objects/core-saved-objects-api-server/index.ts index 809a8e4f98945..a3cb5fa4045a4 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/index.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/index.ts @@ -44,6 +44,7 @@ export type { ISavedObjectsPointInTimeFinder, SavedObjectsCreatePointInTimeFinderDependencies, SavedObjectsPitParams, + SavedObjectsResolveOptions, SavedObjectsResolveResponse, SavedObjectsCollectMultiNamespaceReferencesObject, SavedObjectsUpdateObjectsSpacesResponseObject, diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/find.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/find.ts index a6b3c085dcb6c..e0e035abea34b 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/find.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/find.ts @@ -11,7 +11,7 @@ import type { AggregationsAggregationContainer, SortResults, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import type { SavedObject, SavedObjectsGetOptions } from '../..'; +import type { SavedObject } from '../..'; type KueryNode = any; @@ -153,8 +153,7 @@ export interface SavedObjectsFindOptions { */ pit?: SavedObjectsPitParams; /** {@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility} */ - migrationVersionCompatibility?: SavedObjectsGetOptions['migrationVersionCompatibility']; - downwardConversion?: SavedObjectsGetOptions['downwardConversion']; + migrationVersionCompatibility?: 'compatible' | 'raw'; } /** diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/get.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/get.ts index 48a6ecb9b9dd4..884e7cba4f570 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/get.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/get.ts @@ -16,5 +16,4 @@ import { SavedObjectsBaseOptions } from './base'; export interface SavedObjectsGetOptions extends SavedObjectsBaseOptions { /** {@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility} */ migrationVersionCompatibility?: 'compatible' | 'raw'; - downwardConversion?: 'allow' | 'forbid'; } diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/index.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/index.ts index b01010c100a77..ab3c3ca12f572 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/index.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/index.ts @@ -65,7 +65,7 @@ export type { SavedObjectsRemoveReferencesToOptions, SavedObjectsRemoveReferencesToResponse, } from './remove_references_to'; -export type { SavedObjectsResolveResponse } from './resolve'; +export type { SavedObjectsResolveOptions, SavedObjectsResolveResponse } from './resolve'; export type { SavedObjectsUpdateResponse, SavedObjectsUpdateOptions } from './update'; export type { SavedObjectsUpdateObjectsSpacesObject, diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/resolve.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/resolve.ts index b15075a67aa0c..d32f36bdcce4f 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/resolve.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/resolve.ts @@ -6,8 +6,19 @@ * Side Public License, v 1. */ +import { SavedObjectsBaseOptions } from './base'; import type { SavedObject } from '../..'; +/** + * Options for the saved objects get operation + * + * @public + */ +export interface SavedObjectsResolveOptions extends SavedObjectsBaseOptions { + /** {@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility} */ + migrationVersionCompatibility?: 'compatible' | 'raw'; +} + /** * * @public diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_client.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_client.ts index b81f5c3b6349f..532c2dc58d992 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_client.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_client.ts @@ -20,6 +20,7 @@ import type { SavedObjectsUpdateObjectsSpacesOptions, SavedObjectsCollectMultiNamespaceReferencesObject, SavedObjectsUpdateObjectsSpacesResponse, + SavedObjectsResolveOptions, SavedObjectsResolveResponse, ISavedObjectsPointInTimeFinder, SavedObjectsRemoveReferencesToOptions, @@ -216,7 +217,7 @@ export interface SavedObjectsClientContract { * See documentation for `.resolve`. * * @param objects - an array of objects to resolve (contains id and type) - * @param options {@link SavedObjectsGetOptions} - options for the bulk resolve operation + * @param options {@link SavedObjectsResolveOptions} - options for the bulk resolve operation * @returns the {@link SavedObjectsBulkResolveResponse} * @example * @@ -231,7 +232,7 @@ export interface SavedObjectsClientContract { */ bulkResolve<T = unknown>( objects: SavedObjectsBulkResolveObject[], - options?: SavedObjectsGetOptions + options?: SavedObjectsResolveOptions ): Promise<SavedObjectsBulkResolveResponse<T>>; /** @@ -247,13 +248,13 @@ export interface SavedObjectsClientContract { * * @param type - The type of SavedObject to retrieve * @param id - The ID of the SavedObject to retrieve - * @param options {@link SavedObjectsGetOptions} - options for the resolve operation + * @param options {@link SavedObjectsResolveOptions} - options for the resolve operation * @returns the {@link SavedObjectsResolveResponse} */ resolve<T = unknown>( type: string, id: string, - options?: SavedObjectsGetOptions + options?: SavedObjectsResolveOptions ): Promise<SavedObjectsResolveResponse<T>>; /** diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts index 85dff61775391..dc748e48123ad 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts @@ -20,6 +20,7 @@ import type { SavedObjectsUpdateObjectsSpacesOptions, SavedObjectsCollectMultiNamespaceReferencesObject, SavedObjectsUpdateObjectsSpacesResponse, + SavedObjectsResolveOptions, SavedObjectsResolveResponse, ISavedObjectsPointInTimeFinder, SavedObjectsRemoveReferencesToOptions, @@ -200,7 +201,7 @@ export interface ISavedObjectsRepository { * Resolves an array of objects by id, using any legacy URL aliases if they exist * * @param {array} objects - an array of objects containing id, type - * @param {object} [options={}] {@link SavedObjectsGetOptions} - options for the bulk resolve operation + * @param {object} [options={}] {@link SavedObjectsResolveOptions} - options for the bulk resolve operation * @property {string} [options.migrationVersionCompatibility] * @property {string} [options.namespace] * @returns {promise} - { resolved_objects: [{ saved_object, outcome }] } @@ -213,7 +214,7 @@ export interface ISavedObjectsRepository { */ bulkResolve<T = unknown>( objects: SavedObjectsBulkResolveObject[], - options?: SavedObjectsGetOptions + options?: SavedObjectsResolveOptions ): Promise<SavedObjectsBulkResolveResponse<T>>; /** @@ -237,7 +238,7 @@ export interface ISavedObjectsRepository { * * @param {string} type - the type of the object to resolve * @param {string} id - the id of the object to resolve - * @param {object} [options={}] {@link SavedObjectsGetOptions} - options for the resolve operation + * @param {object} [options={}] {@link SavedObjectsResolveOptions} - options for the resolve operation * @property {string} [options.migrationVersionCompatibility] * @property {string} [options.namespace] * @returns {promise} - { saved_object, outcome } @@ -245,7 +246,7 @@ export interface ISavedObjectsRepository { resolve<T = unknown>( type: string, id: string, - options?: SavedObjectsGetOptions + options?: SavedObjectsResolveOptions ): Promise<SavedObjectsResolveResponse<T>>; /** diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/document_migrator/document_migrator.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/document_migrator/document_migrator.test.ts index 5e132143d5c6b..2e3a99b4b463e 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/document_migrator/document_migrator.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/document_migrator/document_migrator.test.ts @@ -1462,7 +1462,7 @@ describe('DocumentMigrator', () => { expect(() => migrator.migrate(document, { allowDowngrade: false }) ).toThrowErrorMatchingInlineSnapshot( - `"[NewerModelVersionError]: Document \\"smelly\\" belongs to a more recent version of Kibana [10.2.0] when the last known version is [10.1.0]."` + `"Document \\"smelly\\" belongs to a more recent version of Kibana [10.2.0] when the last known version is [10.1.0]."` ); }); }); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/document_migrator/document_migrator.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/document_migrator/document_migrator.ts index 387e037e7a0bf..8ca15093d5827 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/document_migrator/document_migrator.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/document_migrator/document_migrator.ts @@ -81,9 +81,6 @@ export interface VersionedTransformer { migrateAndConvert(doc: SavedObjectUnsanitizedDoc): SavedObjectUnsanitizedDoc[]; } -export function createNewerModelVersionError(message: string) { - return Boom.boomify(Boom.badData(message), { message: '[NewerModelVersionError]' }); -} /** * A concrete implementation of the {@link VersionedTransformer} interface. */ @@ -184,11 +181,9 @@ export class DocumentMigrator implements VersionedTransformer { const currentVersion = doc.typeMigrationVersion ?? doc.migrationVersion?.[doc.type]; const latestVersion = this.migrations[doc.type].latestVersion[TransformType.Migrate]; if (!allowDowngrade) { - if (!allowDowngrade) { - throw createNewerModelVersionError( - `Document "${doc.id}" belongs to a more recent version of Kibana [${currentVersion}] when the last known version is [${latestVersion}].` - ); - } + throw Boom.badData( + `Document "${doc.id}" belongs to a more recent version of Kibana [${currentVersion}] when the last known version is [${latestVersion}].` + ); } return this.transformDown(doc, { targetTypeVersion: latestVersion! }); } else { diff --git a/src/core/server/integration_tests/saved_objects/migrations/zdt_2/sor_higher_version_docs.test.ts b/src/core/server/integration_tests/saved_objects/migrations/zdt_2/sor_higher_version_docs.test.ts index 960752c63d369..e431c3607d983 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/zdt_2/sor_higher_version_docs.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/zdt_2/sor_higher_version_docs.test.ts @@ -138,26 +138,6 @@ describe('Higher version doc conversion', () => { newField: 'someValue', }); }); - it('throws error for documents using higher version model than current', async () => { - try { - await repositoryV1.get('test-type', 'doc-1', { - downwardConversion: 'forbid', - }); - } catch (err) { - expect(err.message).toBe( - '[NewerModelVersionError]: Document "doc-1" belongs to a more recent version of Kibana [10.2.0] when the last known version is [10.1.0].' - ); - } - }); - it("doesn't throw error for documents using current version model when 'downwardConversion' is 'forbid'", async () => { - try { - await repositoryV2.get('test-type', 'doc-1', { - downwardConversion: 'forbid', - }); - } catch (err) { - expect(err).toBeUndefined(); - } - }); }); describe('#bulkGet', () => { @@ -175,26 +155,6 @@ describe('Higher version doc conversion', () => { newField: 'someValue', }); }); - it('throws error for documents using higher version model than current', async () => { - try { - await repositoryV2.bulkGet([{ type: 'test-type', id: 'doc-1' }], { - downwardConversion: 'forbid', - }); - } catch (err) { - expect(err.message).toBe( - '[NewerModelVersionError]: Document "doc-1" belongs to a more recent version of Kibana [10.2.0] when the last known version is [10.1.0].' - ); - } - }); - it("doesn't throw error for documents using current version model when 'downwardConversion' is 'forbid'", async () => { - try { - await repositoryV2.get('test-type', 'doc-1', { - downwardConversion: 'forbid', - }); - } catch (err) { - expect(err).toBeUndefined(); - } - }); }); describe('#resolve', () => { @@ -212,26 +172,6 @@ describe('Higher version doc conversion', () => { newField: 'someValue', }); }); - it('throws error for documents using higher version model than current', async () => { - try { - await repositoryV2.resolve('test-type', 'doc-1', { - downwardConversion: 'forbid', - }); - } catch (err) { - expect(err.message).toBe( - '[NewerModelVersionError]: Document "doc-1" belongs to a more recent version of Kibana [10.2.0] when the last known version is [10.1.0].' - ); - } - }); - it("doesn't throw error for documents using current version model when 'downwardConversion' is 'forbid'", async () => { - try { - await repositoryV2.get('test-type', 'doc-1', { - downwardConversion: 'forbid', - }); - } catch (err) { - expect(err).toBeUndefined(); - } - }); }); describe('#bulkResolve', () => { @@ -249,25 +189,5 @@ describe('Higher version doc conversion', () => { newField: 'someValue', }); }); - it('throws error for documents using higher version model than current', async () => { - try { - await repositoryV2.bulkResolve([{ type: 'test-type', id: 'doc-1' }], { - downwardConversion: 'forbid', - }); - } catch (err) { - expect(err.message).toBe( - '[NewerModelVersionError]: Document "doc-1" belongs to a more recent version of Kibana [10.2.0] when the last known version is [10.1.0].' - ); - } - }); - it("doesn't throw error for documents using current version model when 'downwardConversion' is 'forbid'", async () => { - try { - await repositoryV2.get('test-type', 'doc-1', { - downwardConversion: 'forbid', - }); - } catch (err) { - expect(err).toBeUndefined(); - } - }); }); }); From 733869e9e5774c4813126c80e8c00532ba8659ed Mon Sep 17 00:00:00 2001 From: Kevin Delemme <kevin.delemme@elastic.co> Date: Mon, 28 Aug 2023 14:50:38 -0400 Subject: [PATCH 36/49] chore(slo): general enhancement (#164723) --- .../kbn-slo-schema/src/rest_specs/slo.ts | 5 - .../hooks/slo/use_fetch_active_alerts.ts | 1 + .../hooks/slo/use_fetch_global_diagnosis.ts | 85 ++++------- .../slo/use_fetch_index_pattern_fields.ts | 2 +- .../hooks/slo/use_fetch_rules_for_slo.ts | 7 +- .../pages/slos_welcome/slos_welcome.test.tsx | 25 +++- .../pages/slos_welcome/slos_welcome.tsx | 9 +- .../register_observability_rule_types.ts | 6 +- .../slo_summary_settings_template.ts | 2 +- .../observability/server/routes/slo/route.ts | 19 +-- .../observability/server/saved_objects/slo.ts | 2 +- .../server/services/slo/get_diagnosis.ts | 137 +----------------- .../server/services/slo/transform_manager.ts | 2 +- 13 files changed, 79 insertions(+), 223 deletions(-) diff --git a/x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts b/x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts index 4e1aa86aff6e2..17b8e86d9fc5a 100644 --- a/x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts +++ b/x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts @@ -188,10 +188,6 @@ const findSloDefinitionsParamsSchema = t.type({ */ const findSloDefinitionsResponseSchema = t.array(sloResponseSchema); -const getSLODiagnosisParamsSchema = t.type({ - path: t.type({ id: t.string }), -}); - const getSLOBurnRatesResponseSchema = t.type({ burnRates: t.array( t.type({ @@ -277,7 +273,6 @@ export { findSLOResponseSchema, getPreviewDataParamsSchema, getPreviewDataResponseSchema, - getSLODiagnosisParamsSchema, getSLOParamsSchema, getSLOResponseSchema, fetchHistoricalSummaryParamsSchema, diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts index 601fc8f024a89..7f4e6fdce5b2b 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts @@ -135,6 +135,7 @@ export function useFetchActiveAlerts({ sloIdsAndInstanceIds = [] }: Params): Use } }, refetchOnWindowFocus: false, + enabled: Boolean(sloIdsAndInstanceIds.length), }); return { diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_global_diagnosis.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_global_diagnosis.ts index 94ec7c625a1b1..45ef877bf2472 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_global_diagnosis.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_global_diagnosis.ts @@ -5,32 +5,17 @@ * 2.0. */ -import { - QueryObserverResult, - RefetchOptions, - RefetchQueryFilters, - useQuery, -} from '@tanstack/react-query'; +import type { SecurityHasPrivilegesResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; import type { PublicLicenseJSON } from '@kbn/licensing-plugin/public'; -import type { - SecurityGetUserPrivilegesResponse, - TransformGetTransformStatsResponse, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { useQuery } from '@tanstack/react-query'; import { useKibana } from '../../utils/kibana_react'; import { convertErrorForUseInToast } from './helpers/convert_error_for_use_in_toast'; import { sloKeys } from './query_key_factory'; interface SloGlobalDiagnosisResponse { licenseAndFeatures: PublicLicenseJSON; - userPrivileges: SecurityGetUserPrivilegesResponse; - sloResources: { - [x: string]: 'OK' | 'NOT_OK'; - }; - sloSummaryResources: { - [x: string]: 'OK' | 'NOT_OK'; - }; - sloSummaryTransformsStats: TransformGetTransformStatsResponse; + userPrivileges: { write: SecurityHasPrivilegesResponse; read: SecurityHasPrivilegesResponse }; } export interface UseFetchSloGlobalDiagnoseResponse { @@ -39,10 +24,7 @@ export interface UseFetchSloGlobalDiagnoseResponse { isRefetching: boolean; isSuccess: boolean; isError: boolean; - globalSloDiagnosis: SloGlobalDiagnosisResponse | undefined; - refetch: <TPageData>( - options?: (RefetchOptions & RefetchQueryFilters<TPageData>) | undefined - ) => Promise<QueryObserverResult<SloGlobalDiagnosisResponse | undefined, unknown>>; + data: SloGlobalDiagnosisResponse | undefined; } export function useFetchSloGlobalDiagnosis(): UseFetchSloGlobalDiagnoseResponse { @@ -51,44 +33,41 @@ export function useFetchSloGlobalDiagnosis(): UseFetchSloGlobalDiagnoseResponse notifications: { toasts }, } = useKibana().services; - const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data, refetch } = useQuery( - { - queryKey: sloKeys.globalDiagnosis(), - queryFn: async ({ signal }) => { - try { - const response = await http.get<SloGlobalDiagnosisResponse>( - '/internal/observability/slos/_diagnosis', - { - query: {}, - signal, - } - ); + const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data } = useQuery({ + queryKey: sloKeys.globalDiagnosis(), + queryFn: async ({ signal }) => { + try { + const response = await http.get<SloGlobalDiagnosisResponse>( + '/internal/observability/slos/_diagnosis', + { + query: {}, + signal, + } + ); - return response; - } catch (error) { - throw convertErrorForUseInToast(error); - } - }, - keepPreviousData: true, - refetchOnWindowFocus: false, - retry: false, - onError: (error: Error) => { - toasts.addError(error, { - title: i18n.translate('xpack.observability.slo.globalDiagnosis.errorNotification', { - defaultMessage: 'You do not have the right permissions to use this feature.', - }), - }); - }, - } - ); + return response; + } catch (error) { + throw convertErrorForUseInToast(error); + } + }, + keepPreviousData: true, + refetchOnWindowFocus: false, + retry: false, + onError: (error: Error) => { + toasts.addError(error, { + title: i18n.translate('xpack.observability.slo.globalDiagnosis.errorNotification', { + defaultMessage: 'You do not have the right permissions to use this feature.', + }), + }); + }, + }); return { - globalSloDiagnosis: data, + data, isLoading, isInitialLoading, isRefetching, isSuccess, isError, - refetch, }; } diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_index_pattern_fields.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_index_pattern_fields.ts index 2f51e4d7faf26..3363d501fae22 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_index_pattern_fields.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_index_pattern_fields.ts @@ -34,7 +34,7 @@ export function useFetchIndexPatternFields( return []; } try { - return await dataViews.getFieldsForWildcard({ pattern: indexPattern }); + return await dataViews.getFieldsForWildcard({ pattern: indexPattern, allowNoIndex: true }); } catch (error) { throw new Error(`Something went wrong. Error: ${error}`); } diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_rules_for_slo.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_rules_for_slo.ts index a31e6f8f35f47..21d34fc55289b 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_rules_for_slo.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_rules_for_slo.ts @@ -54,8 +54,7 @@ export function useFetchRulesForSlo({ sloIds = [] }: Params): UseFetchRulesForSl queryFn: async () => { try { const body = JSON.stringify({ - filter: - sloIds?.map((sloId) => `alert.attributes.params.sloId:${sloId}`).join(' or ') ?? '', + filter: sloIds.map((sloId) => `alert.attributes.params.sloId:${sloId}`).join(' or '), fields: ['params.sloId', 'name'], per_page: 1000, }); @@ -64,7 +63,7 @@ export function useFetchRulesForSlo({ sloIds = [] }: Params): UseFetchRulesForSl body, }); - const init = sloIds?.reduce((acc, sloId) => ({ ...acc, [sloId]: [] }), {}); + const init = sloIds.reduce((acc, sloId) => ({ ...acc, [sloId]: [] }), {}); return response.data.reduce( (acc, rule) => ({ @@ -77,7 +76,7 @@ export function useFetchRulesForSlo({ sloIds = [] }: Params): UseFetchRulesForSl // ignore error for retrieving slos } }, - enabled: Boolean(sloIds?.length), + enabled: Boolean(sloIds.length), refetchOnWindowFocus: false, keepPreviousData: true, } diff --git a/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.test.tsx b/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.test.tsx index 155e49c3976fc..fbeae4cb872b2 100644 --- a/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.test.tsx +++ b/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.test.tsx @@ -59,7 +59,9 @@ describe('SLOs Welcome Page', () => { useFetchSloListMock.mockReturnValue({ isLoading: false, sloList: emptySloList }); useLicenseMock.mockReturnValue({ hasAtLeast: () => false }); useGlobalDiagnosisMock.mockReturnValue({ - isError: false, + data: { + userPrivileges: { write: { has_all_requested: true }, read: { has_all_requested: true } }, + }, }); render(<SlosWelcomePage />); @@ -104,7 +106,12 @@ describe('SLOs Welcome Page', () => { hasReadCapabilities: true, }); useGlobalDiagnosisMock.mockReturnValue({ - isError: true, + data: { + userPrivileges: { + write: { has_all_requested: false }, + read: { has_all_requested: true }, + }, + }, }); render(<SlosWelcomePage />); @@ -116,7 +123,12 @@ describe('SLOs Welcome Page', () => { it('should display the welcome message with a Create new SLO button which should navigate to the SLO Creation page', async () => { useGlobalDiagnosisMock.mockReturnValue({ - isError: false, + data: { + userPrivileges: { + write: { has_all_requested: true }, + read: { has_all_requested: true }, + }, + }, }); render(<SlosWelcomePage />); @@ -136,7 +148,12 @@ describe('SLOs Welcome Page', () => { beforeEach(() => { useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); useGlobalDiagnosisMock.mockReturnValue({ - isError: false, + data: { + userPrivileges: { + write: { has_all_requested: true }, + read: { has_all_requested: true }, + }, + }, }); }); diff --git a/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx b/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx index 2f0ef6ad1389e..5c4317cd4e138 100644 --- a/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx +++ b/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx @@ -34,7 +34,7 @@ export function SlosWelcomePage() { http: { basePath }, } = useKibana().services; const { hasWriteCapabilities } = useCapabilities(); - const { isError: hasErrorInGlobalDiagnosis } = useFetchSloGlobalDiagnosis(); + const { data: globalDiagnosis } = useFetchSloGlobalDiagnosis(); const { ObservabilityPageTemplate } = usePluginContext(); const { hasAtLeast } = useLicense(); @@ -43,12 +43,15 @@ export function SlosWelcomePage() { const { isLoading, sloList } = useFetchSloList(); const { total } = sloList || { total: 0 }; + const hasRequiredWritePrivileges = !!globalDiagnosis?.userPrivileges.write.has_all_requested; + const hasRequiredReadPrivileges = !!globalDiagnosis?.userPrivileges.read.has_all_requested; + const handleClickCreateSlo = () => { navigateToUrl(basePath.prepend(paths.observability.sloCreate)); }; const hasSlosAndHasPermissions = - total > 0 && hasAtLeast('platinum') === true && !hasErrorInGlobalDiagnosis; + total > 0 && hasAtLeast('platinum') === true && hasRequiredReadPrivileges; useEffect(() => { if (hasSlosAndHasPermissions) { @@ -115,7 +118,7 @@ export function SlosWelcomePage() { fill color="primary" onClick={handleClickCreateSlo} - disabled={!hasWriteCapabilities || hasErrorInGlobalDiagnosis} + disabled={!hasWriteCapabilities || !hasRequiredWritePrivileges} > {i18n.translate('xpack.observability.slo.sloList.welcomePrompt.buttonLabel', { defaultMessage: 'Create SLO', diff --git a/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts b/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts index 18d2ae5aa998b..c06bd84e02c77 100644 --- a/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts +++ b/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts @@ -9,7 +9,7 @@ import { lazy } from 'react'; import { i18n } from '@kbn/i18n'; import { ALERT_REASON } from '@kbn/rule-data-utils'; -import { SLO_ID_FIELD } from '../../common/field_names/slo'; +import { SLO_ID_FIELD, SLO_INSTANCE_ID_FIELD } from '../../common/field_names/slo'; import { ConfigSchema } from '../plugin'; import { ObservabilityRuleTypeRegistry } from './create_observability_rule_type_registry'; import { @@ -86,7 +86,9 @@ export const registerObservabilityRuleTypes = ( format: ({ fields }) => { return { reason: fields[ALERT_REASON] ?? '-', - link: `/app/observability/slos/${fields[SLO_ID_FIELD]}`, + link: `/app/observability/slos/${fields[SLO_ID_FIELD]}?instanceId=${ + fields[SLO_INSTANCE_ID_FIELD] ?? '*' + }`, }; }, iconClass: 'bell', diff --git a/x-pack/plugins/observability/server/assets/component_templates/slo_summary_settings_template.ts b/x-pack/plugins/observability/server/assets/component_templates/slo_summary_settings_template.ts index 286434003f540..336b7d9e0c35c 100644 --- a/x-pack/plugins/observability/server/assets/component_templates/slo_summary_settings_template.ts +++ b/x-pack/plugins/observability/server/assets/component_templates/slo_summary_settings_template.ts @@ -11,7 +11,7 @@ export const getSLOSummarySettingsTemplate = (name: string) => ({ name, template: { settings: { - auto_expand_replicas: '0-all', + auto_expand_replicas: '0-1', hidden: true, }, }, diff --git a/x-pack/plugins/observability/server/routes/slo/route.ts b/x-pack/plugins/observability/server/routes/slo/route.ts index e991f2b6a9d4f..f77f173675c68 100644 --- a/x-pack/plugins/observability/server/routes/slo/route.ts +++ b/x-pack/plugins/observability/server/routes/slo/route.ts @@ -15,7 +15,6 @@ import { findSLOParamsSchema, getPreviewDataParamsSchema, getSLOBurnRatesParamsSchema, - getSLODiagnosisParamsSchema, getSLOInstancesParamsSchema, getSLOParamsSchema, manageSLOParamsSchema, @@ -35,7 +34,7 @@ import { import { FetchHistoricalSummary } from '../../services/slo/fetch_historical_summary'; import { FindSLODefinitions } from '../../services/slo/find_slo_definitions'; import { getBurnRates } from '../../services/slo/get_burn_rates'; -import { getGlobalDiagnosis, getSloDiagnosis } from '../../services/slo/get_diagnosis'; +import { getGlobalDiagnosis } from '../../services/slo/get_diagnosis'; import { GetPreviewData } from '../../services/slo/get_preview_data'; import { GetSLOInstances } from '../../services/slo/get_slo_instances'; import { DefaultHistoricalSummaryClient } from '../../services/slo/historical_summary_client'; @@ -310,21 +309,6 @@ const getDiagnosisRoute = createObservabilityServerRoute({ }, }); -const getSloDiagnosisRoute = createObservabilityServerRoute({ - endpoint: 'GET /internal/observability/slos/{id}/_diagnosis', - options: { - tags: [], - }, - params: getSLODiagnosisParamsSchema, - handler: async ({ context, params }) => { - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const soClient = (await context.core).savedObjects.client; - const repository = new KibanaSavedObjectsSLORepository(soClient); - - return getSloDiagnosis(params.path.id, { esClient, repository }); - }, -}); - const getSloBurnRates = createObservabilityServerRoute({ endpoint: 'POST /internal/observability/slos/{id}/_burn_rates', options: { @@ -375,7 +359,6 @@ export const sloRouteRepository = { ...getSLORoute, ...updateSLORoute, ...getDiagnosisRoute, - ...getSloDiagnosisRoute, ...getSloBurnRates, ...getPreviewData, ...getSLOInstancesRoute, diff --git a/x-pack/plugins/observability/server/saved_objects/slo.ts b/x-pack/plugins/observability/server/saved_objects/slo.ts index 508f2ea8aae7a..41cb509d83755 100644 --- a/x-pack/plugins/observability/server/saved_objects/slo.ts +++ b/x-pack/plugins/observability/server/saved_objects/slo.ts @@ -57,7 +57,7 @@ export const slo: SavedObjectsType = { }, management: { displayName: 'SLO', - importableAndExportable: true, + importableAndExportable: false, getTitle(sloSavedObject: SavedObject<StoredSLO>) { return `SLO: [${sloSavedObject.attributes.name}]`; }, diff --git a/x-pack/plugins/observability/server/services/slo/get_diagnosis.ts b/x-pack/plugins/observability/server/services/slo/get_diagnosis.ts index 4bdf43e143342..697d3ceb560df 100644 --- a/x-pack/plugins/observability/server/services/slo/get_diagnosis.ts +++ b/x-pack/plugins/observability/server/services/slo/get_diagnosis.ts @@ -5,147 +5,24 @@ * 2.0. */ -import { errors } from '@elastic/elasticsearch'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { LicensingApiRequestHandlerContext } from '@kbn/licensing-plugin/server'; -import { - getSLOTransformId, - SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME, - SLO_COMPONENT_TEMPLATE_SETTINGS_NAME, - SLO_INDEX_TEMPLATE_NAME, - SLO_INGEST_PIPELINE_NAME, - SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, - SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, - SLO_SUMMARY_INDEX_TEMPLATE_NAME, - SLO_SUMMARY_TRANSFORM_NAME_PREFIX, -} from '../../assets/constants'; -import { SLO } from '../../domain/models'; -import { SLORepository } from './slo_repository'; - -const OK = 'OK'; -const NOT_OK = 'NOT_OK'; export async function getGlobalDiagnosis( esClient: ElasticsearchClient, licensing: LicensingApiRequestHandlerContext ) { const licenseInfo = licensing.license.toJSON(); - const userPrivileges = await esClient.security.getUserPrivileges(); - const sloResources = await getSloResourcesDiagnosis(esClient); - const sloSummaryResources = await getSloSummaryResourcesDiagnosis(esClient); - - const sloSummaryTransformsStats = await esClient.transform.getTransformStats({ - transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}*`, - allow_no_match: true, - }); - - return { - licenseAndFeatures: licenseInfo, - userPrivileges, - sloResources, - sloSummaryResources, - sloSummaryTransformsStats, - }; -} - -export async function getSloDiagnosis( - sloId: string, - services: { esClient: ElasticsearchClient; repository: SLORepository } -) { - const { esClient, repository } = services; - - const sloResources = await getSloResourcesDiagnosis(esClient); - const sloSummaryResources = await getSloSummaryResourcesDiagnosis(esClient); - - let slo: SLO | undefined; - try { - slo = await repository.findById(sloId); - } catch (err) { - // noop - } - - const sloTransformStats = await esClient.transform.getTransformStats({ - transform_id: getSLOTransformId(sloId, slo?.revision ?? 1), - allow_no_match: true, + const userWritePrivileges = await esClient.security.hasPrivileges({ + cluster: ['manage_transform'], + index: [{ names: '.slo-*', privileges: ['all'] }], }); - - const sloSummaryTransformsStats = await esClient.transform.getTransformStats({ - transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}*`, - allow_no_match: true, + const userReadPrivileges = await esClient.security.hasPrivileges({ + index: [{ names: '.slo-*', privileges: ['read'] }], }); return { - sloResources, - sloSummaryResources, - slo: slo ?? NOT_OK, - sloTransformStats, - sloSummaryTransformsStats, + licenseAndFeatures: licenseInfo, + userPrivileges: { write: userWritePrivileges, read: userReadPrivileges }, }; } - -async function getSloResourcesDiagnosis(esClient: ElasticsearchClient) { - try { - const indexTemplateExists = await esClient.indices.existsIndexTemplate({ - name: SLO_INDEX_TEMPLATE_NAME, - }); - - const mappingsTemplateExists = await esClient.cluster.existsComponentTemplate({ - name: SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME, - }); - - const settingsTemplateExists = await esClient.cluster.existsComponentTemplate({ - name: SLO_COMPONENT_TEMPLATE_SETTINGS_NAME, - }); - - let ingestPipelineExists = true; - try { - await esClient.ingest.getPipeline({ id: SLO_INGEST_PIPELINE_NAME }); - } catch (err) { - ingestPipelineExists = false; - throw err; - } - - return { - [SLO_INDEX_TEMPLATE_NAME]: indexTemplateExists ? OK : NOT_OK, - [SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME]: mappingsTemplateExists ? OK : NOT_OK, - [SLO_COMPONENT_TEMPLATE_SETTINGS_NAME]: settingsTemplateExists ? OK : NOT_OK, - [SLO_INGEST_PIPELINE_NAME]: ingestPipelineExists ? OK : NOT_OK, - }; - } catch (err) { - if ( - err instanceof errors.ResponseError && - (err.statusCode === 403 || err.meta.statusCode === 403) - ) { - throw new Error('Insufficient permissions to access Elasticsearch Cluster', { cause: err }); - } - } -} - -async function getSloSummaryResourcesDiagnosis(esClient: ElasticsearchClient) { - try { - const indexTemplateExists = await esClient.indices.existsIndexTemplate({ - name: SLO_SUMMARY_INDEX_TEMPLATE_NAME, - }); - - const mappingsTemplateExists = await esClient.cluster.existsComponentTemplate({ - name: SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, - }); - - const settingsTemplateExists = await esClient.cluster.existsComponentTemplate({ - name: SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, - }); - - return { - [SLO_SUMMARY_INDEX_TEMPLATE_NAME]: indexTemplateExists ? OK : NOT_OK, - [SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME]: mappingsTemplateExists ? OK : NOT_OK, - [SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME]: settingsTemplateExists ? OK : NOT_OK, - }; - } catch (err) { - if ( - err instanceof errors.ResponseError && - (err.statusCode === 403 || err.meta.statusCode === 403) - ) { - throw new Error('Insufficient permissions to access Elasticsearch Cluster', { cause: err }); - } - } -} diff --git a/x-pack/plugins/observability/server/services/slo/transform_manager.ts b/x-pack/plugins/observability/server/services/slo/transform_manager.ts index 3bd56669046ac..14b600a746cac 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_manager.ts +++ b/x-pack/plugins/observability/server/services/slo/transform_manager.ts @@ -65,7 +65,7 @@ export class DefaultTransformManager implements TransformManager { await retryTransientEsErrors( () => this.esClient.transform.stopTransform( - { transform_id: transformId, wait_for_completion: true }, + { transform_id: transformId, wait_for_completion: true, force: true }, { ignore: [404] } ), { logger: this.logger } From 8ac82e38d79c0031d76de472d1b1e0f2f7b9fef2 Mon Sep 17 00:00:00 2001 From: James Rodewig <james.rodewig@elastic.co> Date: Mon, 28 Aug 2023 15:02:22 -0400 Subject: [PATCH 37/49] [DOCS] Add cross-link for other encryption key settings (#165014) Problem: The [Configure security in Kibana](https://www.elastic.co/guide/en/kibana/current/using-kibana-with-security.html) docs page only covers the `xpack.security.encryptionKey` setting for session encryption. Users may not know that encryption for Kibana's reporting and saved objects features also require encryption keys. Solution: Add a cross-link to the respective encryption key settings for reporting and saved objects --- docs/user/security/securing-kibana.asciidoc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/user/security/securing-kibana.asciidoc b/docs/user/security/securing-kibana.asciidoc index 875830ab88b46..98290bb093e41 100644 --- a/docs/user/security/securing-kibana.asciidoc +++ b/docs/user/security/securing-kibana.asciidoc @@ -27,7 +27,7 @@ configure additional security settings and authentication. . Set the `xpack.security.encryptionKey` property in the `kibana.yml` configuration file. You can use any text string that is 32 characters or longer -as the encryption key. +as the encryption key. Refer to <<xpack-security-encryptionKey,`xpack.security.encryptionKey`>>. + -- [source,yaml] @@ -35,7 +35,10 @@ as the encryption key. xpack.security.encryptionKey: "something_at_least_32_characters" ---- -For more information, see <<security-settings-kb,Security settings in {kib}>>. +{kib}'s reporting and saved objects features also have encryption key settings. +Refer to <<xpack-reporting-encryptionKey,`xpack.reporting.encryptionKey`>> and +<<xpack-encryptedSavedObjects-encryptionKey,`xpack.encryptedSavedObjects.encryptionKey`>> +respectively. -- . Optional: <<xpack-security-session-management,Configure {kib}'s session expiration settings>>. From 3835392e329b1a3cc1dba0a1b6f36a36a87c1cfa Mon Sep 17 00:00:00 2001 From: Davis Plumlee <56367316+dplumlee@users.noreply.github.com> Date: Mon, 28 Aug 2023 16:39:20 -0400 Subject: [PATCH 38/49] [Security Solution] Coverage Overview follow-up 2 (#164986) --- .../common/experimental_features.ts | 9 ------ .../links_to_docs/links_components.tsx | 4 +++ .../links_to_docs/links_translations.ts | 8 +++++ .../build_coverage_overview_mitre_graph.ts | 24 +++++++++++++- .../coverage_overview/mitre_technique.test.ts | 32 +++++++++++++++++++ .../coverage_overview/mitre_technique.ts | 18 +++++++++++ .../pages/coverage_overview/constants.ts | 10 +++--- .../coverage_overview_dashboard.tsx | 32 ++++++++++--------- .../pages/coverage_overview/helpers.test.ts | 25 +-------------- .../pages/coverage_overview/helpers.ts | 23 +++---------- .../coverage_overview/technique_panel.tsx | 3 +- .../pages/coverage_overview/translations.ts | 11 ++----- .../security_solution/public/rules/links.ts | 1 - .../security_solution/public/rules/routes.tsx | 23 ++++--------- .../rule_management/api/register_routes.ts | 6 ++-- .../common/config.ts | 1 - 16 files changed, 124 insertions(+), 106 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.test.ts diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index b06a5532ec12c..cbc84c3314e88 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -89,15 +89,6 @@ export const allowedExperimentalValues = Object.freeze({ **/ newUserDetailsFlyout: false, - /** - * Enables Protections/Detections Coverage Overview page (Epic link https://github.com/elastic/security-team/issues/2905) - * - * This flag aims to facilitate the development process as the feature may not make it to 8.10 release. - * - * The flag doesn't have to be documented and has to be removed after the feature is ready to release. - */ - detectionsCoverageOverview: true, - /** * Enable risk engine client and initialisation of datastream, component templates and mappings */ diff --git a/x-pack/plugins/security_solution/public/common/components/links_to_docs/links_components.tsx b/x-pack/plugins/security_solution/public/common/components/links_to_docs/links_components.tsx index 82d4c5b5a3e27..f5595ac4a826c 100644 --- a/x-pack/plugins/security_solution/public/common/components/links_to_docs/links_components.tsx +++ b/x-pack/plugins/security_solution/public/common/components/links_to_docs/links_components.tsx @@ -29,3 +29,7 @@ export const MlJobCompatibilityLink = () => ( linkText={i18n.ML_JOB_COMPATIBILITY_LINK_TEXT} /> ); + +export const CoverageOverviewLink = () => ( + <DocLink docPath={i18n.COVERAGE_OVERVIEW_LINK_PATH} linkText={i18n.COVERAGE_OVERVIEW_LINK_TEXT} /> +); diff --git a/x-pack/plugins/security_solution/public/common/components/links_to_docs/links_translations.ts b/x-pack/plugins/security_solution/public/common/components/links_to_docs/links_translations.ts index a495d95b3cf37..fcb17b6db540f 100644 --- a/x-pack/plugins/security_solution/public/common/components/links_to_docs/links_translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/links_to_docs/links_translations.ts @@ -41,3 +41,11 @@ export const ML_JOB_COMPATIBILITY_LINK_TEXT = i18n.translate( defaultMessage: 'ML job compatibility', } ); + +export const COVERAGE_OVERVIEW_LINK_PATH = 'rules-coverage.html'; +export const COVERAGE_OVERVIEW_LINK_TEXT = i18n.translate( + 'xpack.securitySolution.documentationLinks.coverageOverview.text', + { + defaultMessage: 'Learn more.', + } +); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/coverage_overview/build_coverage_overview_mitre_graph.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/coverage_overview/build_coverage_overview_mitre_graph.ts index 7a775b3292991..acae46d0f3701 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/coverage_overview/build_coverage_overview_mitre_graph.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/coverage_overview/build_coverage_overview_mitre_graph.ts @@ -15,6 +15,24 @@ import type { CoverageOverviewMitreSubTechnique } from '../../model/coverage_ove import type { CoverageOverviewMitreTactic } from '../../model/coverage_overview/mitre_tactic'; import type { CoverageOverviewMitreTechnique } from '../../model/coverage_overview/mitre_technique'; +// The order the tactic columns will appear in on the coverage overview page +const tacticOrder = [ + 'TA0043', + 'TA0042', + 'TA0001', + 'TA0002', + 'TA0003', + 'TA0004', + 'TA0005', + 'TA0006', + 'TA0007', + 'TA0008', + 'TA0009', + 'TA0011', + 'TA0010', + 'TA0040', +]; + export function buildCoverageOverviewMitreGraph( tactics: MitreTactic[], techniques: MitreTechnique[], @@ -67,9 +85,13 @@ export function buildCoverageOverviewMitreGraph( } } + const sortedTactics = tactics.sort( + (a, b) => tacticOrder.indexOf(a.id) - tacticOrder.indexOf(b.id) + ); + const result: CoverageOverviewMitreTactic[] = []; - for (const tactic of tactics) { + for (const tactic of sortedTactics) { result.push({ id: tactic.id, name: tactic.name, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.test.ts new file mode 100644 index 0000000000000..01794b34c8ee7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.test.ts @@ -0,0 +1,32 @@ +/* + * 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 { CoverageOverviewRuleActivity } from '../../../../../common/api/detection_engine'; +import { getTotalRuleCount } from './mitre_technique'; +import { getMockCoverageOverviewMitreTechnique } from './__mocks__'; + +describe('getTotalRuleCount', () => { + it('returns count of all rules when no activity filter is present', () => { + const payload = getMockCoverageOverviewMitreTechnique(); + expect(getTotalRuleCount(payload)).toEqual(2); + }); + + it('returns count of one rule type when an activity filter is present', () => { + const payload = getMockCoverageOverviewMitreTechnique(); + expect(getTotalRuleCount(payload, [CoverageOverviewRuleActivity.Disabled])).toEqual(1); + }); + + it('returns count of multiple rule type when multiple activity filter is present', () => { + const payload = getMockCoverageOverviewMitreTechnique(); + expect( + getTotalRuleCount(payload, [ + CoverageOverviewRuleActivity.Enabled, + CoverageOverviewRuleActivity.Disabled, + ]) + ).toEqual(2); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.ts index 35587ca59fdda..589629d643810 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { CoverageOverviewRuleActivity } from '../../../../../common/api/detection_engine'; import type { CoverageOverviewMitreSubTechnique } from './mitre_subtechnique'; import type { CoverageOverviewRule } from './rule'; @@ -20,3 +21,20 @@ export interface CoverageOverviewMitreTechnique { disabledRules: CoverageOverviewRule[]; availableRules: CoverageOverviewRule[]; } + +export const getTotalRuleCount = ( + technique: CoverageOverviewMitreTechnique, + activity?: CoverageOverviewRuleActivity[] +): number => { + if (!activity) { + return technique.enabledRules.length + technique.disabledRules.length; + } + let totalRuleCount = 0; + if (activity.includes(CoverageOverviewRuleActivity.Enabled)) { + totalRuleCount += technique.enabledRules.length; + } + if (activity.includes(CoverageOverviewRuleActivity.Disabled)) { + totalRuleCount += technique.disabledRules.length; + } + return totalRuleCount; +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/constants.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/constants.ts index 7c170579a217a..3bbc2f5dfbfb9 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/constants.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/constants.ts @@ -11,8 +11,6 @@ import { } from '../../../../../common/api/detection_engine'; import * as i18n from './translations'; -export const coverageOverviewPaletteColors = ['#00BFB326', '#00BFB34D', '#00BFB399', '#00BFB3']; - export const coverageOverviewPanelWidth = 160; export const coverageOverviewLegendWidth = 380; @@ -25,10 +23,10 @@ export const coverageOverviewFilterWidth = 300; * A corresponding color is applied if rules count >= a specific threshold */ export const coverageOverviewCardColorThresholds = [ - { threshold: 10, color: coverageOverviewPaletteColors[3] }, - { threshold: 7, color: coverageOverviewPaletteColors[2] }, - { threshold: 3, color: coverageOverviewPaletteColors[1] }, - { threshold: 1, color: coverageOverviewPaletteColors[0] }, + { threshold: 10, color: '#00BFB3' }, + { threshold: 7, color: '#00BFB399' }, + { threshold: 3, color: '#00BFB34D' }, + { threshold: 1, color: '#00BFB326' }, ]; export const ruleActivityFilterDefaultOptions = [ diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/coverage_overview_dashboard.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/coverage_overview_dashboard.tsx index 6762ee6b1b0e2..11ee8f0d70bbc 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/coverage_overview_dashboard.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/coverage_overview_dashboard.tsx @@ -5,7 +5,8 @@ * 2.0. */ import React from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiSpacer, EuiText } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; +import { CoverageOverviewLink } from '../../../../common/components/links_to_docs'; import { HeaderPage } from '../../../../common/components/header_page'; import * as i18n from './translations'; @@ -14,26 +15,27 @@ import { CoverageOverviewMitreTechniquePanelPopover } from './technique_panel_po import { CoverageOverviewFiltersPanel } from './filters_panel'; import { useCoverageOverviewDashboardContext } from './coverage_overview_dashboard_context'; +const CoverageOverviewHeaderComponent = () => ( + <HeaderPage + title={i18n.COVERAGE_OVERVIEW_DASHBOARD_TITLE} + subtitle={ + <EuiText color="subdued" size="s"> + <span>{i18n.CoverageOverviewDashboardInformation}</span> <CoverageOverviewLink /> + </EuiText> + } + /> +); + +const CoverageOverviewHeader = React.memo(CoverageOverviewHeaderComponent); + const CoverageOverviewDashboardComponent = () => { const { state: { data }, } = useCoverageOverviewDashboardContext(); - const subtitle = ( - <EuiText color="subdued" size="s"> - <span>{i18n.CoverageOverviewDashboardInformation}</span>{' '} - <EuiLink - external={true} - href={'https://www.elastic.co/'} // TODO: change to actual docs link before release - rel="noopener noreferrer" - target="_blank" - > - {i18n.CoverageOverviewDashboardInformationLink} - </EuiLink> - </EuiText> - ); + return ( <> - <HeaderPage title={i18n.COVERAGE_OVERVIEW_DASHBOARD_TITLE} subtitle={subtitle} /> + <CoverageOverviewHeader /> <CoverageOverviewFiltersPanel /> <EuiSpacer /> <EuiFlexGroup gutterSize="m" className="eui-xScroll"> diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.test.ts index 738eb981f37bb..5a1aee424352a 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CoverageOverviewRuleActivity } from '../../../../../common/api/detection_engine'; +import type { CoverageOverviewRuleActivity } from '../../../../../common/api/detection_engine'; import { getCoverageOverviewFilterMock } from '../../../../../common/api/detection_engine/rule_management/coverage_overview/coverage_overview_route.mock'; import { getMockCoverageOverviewMitreSubTechnique, @@ -17,7 +17,6 @@ import { extractSelected, getNumOfCoveredSubtechniques, getNumOfCoveredTechniques, - getTotalRuleCount, populateSelected, } from './helpers'; @@ -89,26 +88,4 @@ describe('helpers', () => { ]); }); }); - - describe('getTotalRuleCount', () => { - it('returns count of all rules when no activity filter is present', () => { - const payload = getMockCoverageOverviewMitreTechnique(); - expect(getTotalRuleCount(payload)).toEqual(2); - }); - - it('returns count of one rule type when an activity filter is present', () => { - const payload = getMockCoverageOverviewMitreTechnique(); - expect(getTotalRuleCount(payload, [CoverageOverviewRuleActivity.Disabled])).toEqual(1); - }); - - it('returns count of multiple rule type when multiple activity filter is present', () => { - const payload = getMockCoverageOverviewMitreTechnique(); - expect( - getTotalRuleCount(payload, [ - CoverageOverviewRuleActivity.Enabled, - CoverageOverviewRuleActivity.Disabled, - ]) - ).toEqual(2); - }); - }); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts index 7e8f757561a78..82d50e7b9721b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts @@ -6,8 +6,10 @@ */ import type { EuiSelectableOption } from '@elastic/eui'; -import type { CoverageOverviewRuleSource } from '../../../../../common/api/detection_engine'; -import { CoverageOverviewRuleActivity } from '../../../../../common/api/detection_engine'; +import type { + CoverageOverviewRuleActivity, + CoverageOverviewRuleSource, +} from '../../../../../common/api/detection_engine'; import type { CoverageOverviewMitreTactic } from '../../../rule_management/model/coverage_overview/mitre_tactic'; import type { CoverageOverviewMitreTechnique } from '../../../rule_management/model/coverage_overview/mitre_technique'; import { coverageOverviewCardColorThresholds } from './constants'; @@ -41,20 +43,3 @@ export const populateSelected = ( allOptions.map((option) => selected.includes(option.label) ? { ...option, checked: 'on' } : option ); - -export const getTotalRuleCount = ( - technique: CoverageOverviewMitreTechnique, - activity?: CoverageOverviewRuleActivity[] -): number => { - if (!activity) { - return technique.enabledRules.length + technique.disabledRules.length; - } - let totalRuleCount = 0; - if (activity.includes(CoverageOverviewRuleActivity.Enabled)) { - totalRuleCount += technique.enabledRules.length; - } - if (activity.includes(CoverageOverviewRuleActivity.Disabled)) { - totalRuleCount += technique.disabledRules.length; - } - return totalRuleCount; -}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/technique_panel.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/technique_panel.tsx index e182b6445513c..821f0f18dcd72 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/technique_panel.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/technique_panel.tsx @@ -9,9 +9,10 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui'; import { css } from '@emotion/css'; import React, { memo, useCallback, useMemo } from 'react'; import type { CoverageOverviewMitreTechnique } from '../../../rule_management/model/coverage_overview/mitre_technique'; +import { getTotalRuleCount } from '../../../rule_management/model/coverage_overview/mitre_technique'; import { coverageOverviewPanelWidth } from './constants'; import { useCoverageOverviewDashboardContext } from './coverage_overview_dashboard_context'; -import { getCardBackgroundColor, getTotalRuleCount } from './helpers'; +import { getCardBackgroundColor } from './helpers'; import { CoverageOverviewPanelRuleStats } from './shared_components/panel_rule_stats'; import * as i18n from './translations'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/translations.ts index c3e205531fdce..eb9f06c350421 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/translations.ts @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; export const COVERAGE_OVERVIEW_DASHBOARD_TITLE = i18n.translate( 'xpack.securitySolution.coverageOverviewDashboard.pageTitle', { - defaultMessage: 'MITRE ATT&CK\u00AE Coverage', + defaultMessage: 'MITRE ATT&CK\u00AE coverage', } ); @@ -174,13 +174,6 @@ export const CoverageOverviewDashboardInformation = i18n.translate( 'xpack.securitySolution.coverageOverviewDashboard.dashboardInformation', { defaultMessage: - 'The interactive MITRE ATT&CK coverage below shows the current state of your coverage from installed rules, click on a cell to view further details. Unmapped rules will not be displayed. View further information from our', - } -); - -export const CoverageOverviewDashboardInformationLink = i18n.translate( - 'xpack.securitySolution.coverageOverviewDashboard.dashboardInformationLink', - { - defaultMessage: 'docs.', + "Your current coverage of MITRE ATT&CK\u00AE tactics and techniques, based on installed rules. Click a cell to view and enable a technique's rules. Rules must be mapped to the MITRE ATT&CK\u00AE framework to be displayed.", } ); diff --git a/x-pack/plugins/security_solution/public/rules/links.ts b/x-pack/plugins/security_solution/public/rules/links.ts index 276a4f1b2f7af..67d9a4df4a048 100644 --- a/x-pack/plugins/security_solution/public/rules/links.ts +++ b/x-pack/plugins/security_solution/public/rules/links.ts @@ -104,7 +104,6 @@ export const links: LinkItem = { defaultMessage: 'MITRE ATT&CK Coverage', }), ], - experimentalKey: 'detectionsCoverageOverview', }, ], categories: [ diff --git a/x-pack/plugins/security_solution/public/rules/routes.tsx b/x-pack/plugins/security_solution/public/rules/routes.tsx index 7badb0c82a159..add8a5911df21 100644 --- a/x-pack/plugins/security_solution/public/rules/routes.tsx +++ b/x-pack/plugins/security_solution/public/rules/routes.tsx @@ -28,7 +28,6 @@ import { AllRulesTabs } from '../detection_engine/rule_management_ui/components/ import { AddRulesPage } from '../detection_engine/rule_management_ui/pages/add_rules'; import type { SecuritySubPluginRoutes } from '../app/types'; import { RulesLandingPage } from './landing'; -import { useIsExperimentalFeatureEnabled } from '../common/hooks/use_experimental_features'; import { CoverageOverviewPage } from '../detection_engine/rule_management_ui/pages/coverage_overview'; import { RuleDetailTabs } from '../detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs'; @@ -107,21 +106,13 @@ const RulesContainerComponent: React.FC = () => { const Rules = React.memo(RulesContainerComponent); -const CoverageOverviewRoutes = () => { - const isDetectionsCoverageOverviewEnabled = useIsExperimentalFeatureEnabled( - 'detectionsCoverageOverview' - ); - - return isDetectionsCoverageOverviewEnabled ? ( - <PluginTemplateWrapper> - <TrackApplicationView viewId={SecurityPageName.coverageOverview}> - <CoverageOverviewPage /> - </TrackApplicationView> - </PluginTemplateWrapper> - ) : ( - <Redirect to={SecurityPageName.landing} /> - ); -}; +const CoverageOverviewRoutes = () => ( + <PluginTemplateWrapper> + <TrackApplicationView viewId={SecurityPageName.coverageOverview}> + <CoverageOverviewPage /> + </TrackApplicationView> + </PluginTemplateWrapper> +); export const routes: SecuritySubPluginRoutes = [ { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/register_routes.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/register_routes.ts index f7c865605dc3d..ed0f19c7015b6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/register_routes.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/register_routes.ts @@ -62,8 +62,6 @@ export const registerRuleManagementRoutes = ( // Rules filters getRuleManagementFilters(router); - // Rules dashboard - if (config.experimentalFeatures.detectionsCoverageOverview) { - getCoverageOverviewRoute(router); - } + // Rules coverage overview + getCoverageOverviewRoute(router); }; diff --git a/x-pack/test/detection_engine_api_integration/common/config.ts b/x-pack/test/detection_engine_api_integration/common/config.ts index 7f3598ee8d5e8..c4c3c44f1c418 100644 --- a/x-pack/test/detection_engine_api_integration/common/config.ts +++ b/x-pack/test/detection_engine_api_integration/common/config.ts @@ -78,7 +78,6 @@ export function createTestConfig(options: CreateTestConfigOptions, testFiles?: s 'previewTelemetryUrlEnabled', 'riskScoringPersistence', 'riskScoringRoutesEnabled', - 'detectionsCoverageOverview', ])}`, '--xpack.task_manager.poll_interval=1000', `--xpack.actions.preconfigured=${JSON.stringify({ From 5f9651e0ef99e35e9a4a3b5dfbd7e40160038f07 Mon Sep 17 00:00:00 2001 From: Garrett Spong <spong@users.noreply.github.com> Date: Mon, 28 Aug 2023 14:46:33 -0600 Subject: [PATCH 39/49] [Security Solution] Fixes Preconfigured Connectors not working with Assistant (#164900) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Fixes Preconfigured Connectors not working with the Assistant, and also ensures default `model` from connector will be used first if available (instead of defaulting to `gpt-3.5-turbo`). <p align="center"> <img width="500" src="https://github.com/elastic/kibana/assets/2946766/637f5919-7560-40b0-a8db-681096e77ac0" /> </p> Note how `Model` is not displayed even though this is an OpenAI connector: <p align="center"> <img width="500" src="https://github.com/elastic/kibana/assets/2946766/2c4bbe91-2851-48d7-8bfe-20e07db52155" /> </p> Additionally, resolves issue with Detection Rule Assistant CTA not displaying correctly on some platforms/browsers. It now shows as a `Chat` button to the right of the table tabs, matching the other assistant CTA's throughout the application. <p align="center"> <img width="500" src="https://github.com/elastic/kibana/assets/2946766/9fcecd54-8e1a-423a-be05-7137632acbc4" /> </p> And lastly removes `Beta` title from callout since we're going GA in `8.10` 🎉 <p align="center"> <img width="500" src="https://github.com/elastic/kibana/assets/2946766/5beb379a-1bc7-4afc-b4bc-09f1d6085211" /> </p> Resolves: https://github.com/elastic/kibana/issues/163394#issuecomment-1693431066 Resolves: https://github.com/elastic/kibana/issues/164819 ### Checklist Delete any items that are not applicable to this PR. - [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) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials --- .../impl/assistant/assistant_title/index.tsx | 4 +- .../conversation_settings.tsx | 62 +++++++++++-------- .../impl/assistant/translations.ts | 7 --- .../connector_selector/index.tsx | 40 +++++------- .../connector_selector_inline.test.tsx | 3 - .../connector_selector_inline.tsx | 50 +++++---------- .../connectorland/connector_setup/index.tsx | 20 +++--- .../impl/connectorland/helpers.tsx | 31 ++++++++++ .../impl/connectorland/translations.ts | 7 +++ .../rules_table/rules_table_toolbar.tsx | 42 ++++++++++++- .../pages/rule_management/index.tsx | 6 +- .../pages/rule_management/super_header.tsx | 61 ------------------ 12 files changed, 157 insertions(+), 176 deletions(-) create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/connectorland/helpers.tsx delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/super_header.tsx diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx index 766811d70ebe6..ccf04c38f5c93 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx @@ -56,7 +56,7 @@ export const AssistantTitle: React.FC<{ const content = useMemo( () => ( <FormattedMessage - defaultMessage="The Elastic AI Assistant is currently in beta. For more information on the assistant feature and its usage, please reference the {documentationLink}." + defaultMessage="Responses from AI systems may not always be entirely accurate. For more information on the assistant feature and its usage, please reference the {documentationLink}." id="xpack.elasticAssistant.assistant.technicalPreview.tooltipContent" values={{ documentationLink, @@ -99,7 +99,6 @@ export const AssistantTitle: React.FC<{ anchorPosition="rightUp" > <EuiText data-test-subj="tooltipContent" grow={false} css={{ maxWidth: '400px' }}> - <h4>{i18n.TOOLTIP_TITLE}</h4> <EuiText size={'s'}> <p>{content}</p> </EuiText> @@ -112,7 +111,6 @@ export const AssistantTitle: React.FC<{ <ConnectorSelectorInline isDisabled={isDisabled || selectedConversation === undefined} onConnectorModalVisibilityChange={() => {}} - onConnectorSelectionChange={() => {}} selectedConnectorId={selectedConnectorId} selectedConversation={selectedConversation} /> diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx index 853501da409c1..a0c8226b3ea7e 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx @@ -23,6 +23,8 @@ import { ModelSelector } from '../../../connectorland/models/model_selector/mode import { UseAssistantContext } from '../../../assistant_context'; import { ConversationSelectorSettings } from '../conversation_selector_settings'; import { getDefaultSystemPrompt } from '../../use_conversation/helpers'; +import { useLoadConnectors } from '../../../connectorland/use_load_connectors'; +import { getGenAiConfig } from '../../../connectorland/helpers'; export interface ConversationSettingsProps { actionTypeRegistry: ActionTypeRegistryContract; @@ -63,6 +65,8 @@ export const ConversationSettings: React.FC<ConversationSettingsProps> = React.m return getDefaultSystemPrompt({ allSystemPrompts, conversation: selectedConversation }); }, [allSystemPrompts, selectedConversation]); + const { data: connectors, isSuccess: areConnectorsFetched } = useLoadConnectors({ http }); + // Conversation callbacks // When top level conversation selection changes const onConversationSelectionChange = useCallback( @@ -131,10 +135,13 @@ export const ConversationSettings: React.FC<ConversationSettingsProps> = React.m [selectedConversation, setUpdatedConversationSettings] ); - const selectedConnectorId = useMemo( - () => selectedConversation?.apiConfig.connectorId, - [selectedConversation?.apiConfig.connectorId] - ); + const selectedConnector = useMemo(() => { + const selectedConnectorId = selectedConversation?.apiConfig.connectorId; + if (areConnectorsFetched) { + return connectors?.find((c) => c.id === selectedConnectorId); + } + return undefined; + }, [areConnectorsFetched, connectors, selectedConversation?.apiConfig.connectorId]); const selectedProvider = useMemo( () => selectedConversation?.apiConfig.provider, @@ -142,16 +149,19 @@ export const ConversationSettings: React.FC<ConversationSettingsProps> = React.m ); const handleOnConnectorSelectionChange = useCallback( - (connectorId: string, provider: OpenAiProviderType) => { + (connector) => { if (selectedConversation != null) { + const config = getGenAiConfig(connector); + setUpdatedConversationSettings((prev) => ({ ...prev, [selectedConversation.id]: { ...selectedConversation, apiConfig: { ...selectedConversation.apiConfig, - connectorId, - provider, + connectorId: connector?.id, + provider: config?.apiProvider, + model: config?.defaultModel, }, }, })); @@ -160,10 +170,11 @@ export const ConversationSettings: React.FC<ConversationSettingsProps> = React.m [selectedConversation, setUpdatedConversationSettings] ); - const selectedModel = useMemo( - () => selectedConversation?.apiConfig.model, - [selectedConversation?.apiConfig.model] - ); + const selectedModel = useMemo(() => { + const connectorModel = getGenAiConfig(selectedConnector)?.defaultModel; + // Prefer conversation configuration over connector default + return selectedConversation?.apiConfig.model ?? connectorModel; + }, [selectedConnector, selectedConversation?.apiConfig.model]); const handleOnModelSelectionChange = useCallback( (model?: string) => { @@ -244,23 +255,24 @@ export const ConversationSettings: React.FC<ConversationSettingsProps> = React.m isDisabled={selectedConversation == null} onConnectorModalVisibilityChange={() => {}} onConnectorSelectionChange={handleOnConnectorSelectionChange} - selectedConnectorId={selectedConnectorId} + selectedConnectorId={selectedConnector?.id} /> </EuiFormRow> - {selectedProvider === OpenAiProviderType.OpenAi && ( - <EuiFormRow - data-test-subj="model-field" - display="rowCompressed" - label={i18nModel.MODEL_TITLE} - helpText={i18nModel.HELP_LABEL} - > - <ModelSelector - onModelSelectionChange={handleOnModelSelectionChange} - selectedModel={selectedModel} - /> - </EuiFormRow> - )} + {selectedConnector?.isPreconfigured === false && + selectedProvider === OpenAiProviderType.OpenAi && ( + <EuiFormRow + data-test-subj="model-field" + display="rowCompressed" + label={i18nModel.MODEL_TITLE} + helpText={i18nModel.HELP_LABEL} + > + <ModelSelector + onModelSelectionChange={handleOnModelSelectionChange} + selectedModel={selectedModel} + /> + </EuiFormRow> + )} </> ); } diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/translations.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/translations.ts index 580e02247e3ee..7afa89f8f4ab6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/translations.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/translations.ts @@ -41,13 +41,6 @@ export const API_ERROR = i18n.translate('xpack.elasticAssistant.assistant.apiErr 'An error occurred sending your message. If the problem persists, please test the connector configuration.', }); -export const TOOLTIP_TITLE = i18n.translate( - 'xpack.elasticAssistant.assistant.technicalPreview.tooltipTitle', - { - defaultMessage: 'Beta', - } -); - export const TOOLTIP_ARIA_LABEL = i18n.translate( 'xpack.elasticAssistant.documentationLinks.ariaLabel', { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx index f1a03329657b6..df3f0b54cd14f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx @@ -14,31 +14,24 @@ import { } from '@kbn/triggers-actions-ui-plugin/public'; import { HttpSetup } from '@kbn/core-http-browser'; -import { ActionConnectorProps } from '@kbn/triggers-actions-ui-plugin/public/types'; import { ConnectorAddModal } from '@kbn/triggers-actions-ui-plugin/public/common/constants'; -import { - GEN_AI_CONNECTOR_ID, - OpenAiProviderType, -} from '@kbn/stack-connectors-plugin/public/common'; +import { GEN_AI_CONNECTOR_ID } from '@kbn/stack-connectors-plugin/public/common'; import { useLoadConnectors } from '../use_load_connectors'; import * as i18n from '../translations'; import { useLoadActionTypes } from '../use_load_action_types'; import { useAssistantContext } from '../../assistant_context'; +import { getGenAiConfig } from '../helpers'; export const ADD_NEW_CONNECTOR = 'ADD_NEW_CONNECTOR'; interface Props { actionTypeRegistry: ActionTypeRegistryContract; http: HttpSetup; isDisabled?: boolean; - onConnectorSelectionChange: (connectorId: string, provider: OpenAiProviderType) => void; + onConnectorSelectionChange: (connector: ActionConnector | undefined) => void; selectedConnectorId?: string; onConnectorModalVisibilityChange?: (isVisible: boolean) => void; } -interface Config { - apiProvider: string; -} - export const ConnectorSelector: React.FC<Props> = React.memo( ({ actionTypeRegistry, @@ -95,18 +88,19 @@ export const ConnectorSelector: React.FC<Props> = React.memo( const connectorOptions = useMemo(() => { return ( connectors?.map((connector) => { - const apiProvider: string | undefined = ( - connector as ActionConnectorProps<Config, unknown> - )?.config?.apiProvider; + const apiProvider = getGenAiConfig(connector)?.apiProvider; + const connectorDetails = connector.isPreconfigured + ? i18n.PRECONFIGURED_CONNECTOR + : apiProvider; return { value: connector.id, inputDisplay: connector.name, dropdownDisplay: ( <React.Fragment key={connector.id}> <strong>{connector.name}</strong> - {apiProvider && ( - <EuiText size="s" color="subdued"> - <p>{apiProvider}</p> + {connectorDetails && ( + <EuiText size="xs" color="subdued"> + <p>{connectorDetails}</p> </EuiText> )} </React.Fragment> @@ -138,10 +132,8 @@ export const ConnectorSelector: React.FC<Props> = React.memo( return; } - const apiProvider = ( - connectors?.find((c) => c.id === connectorId) as ActionConnectorProps<Config, unknown> - )?.config.apiProvider as OpenAiProviderType; - onConnectorSelectionChange(connectorId, apiProvider); + const connector = connectors?.find((c) => c.id === connectorId); + onConnectorSelectionChange(connector); }, [connectors, onConnectorSelectionChange, onConnectorModalVisibilityChange] ); @@ -162,12 +154,8 @@ export const ConnectorSelector: React.FC<Props> = React.memo( <ConnectorAddModal actionType={actionType} onClose={cleanupAndCloseModal} - postSaveEventHandler={(savedAction: ActionConnector) => { - onConnectorSelectionChange( - savedAction.id, - (savedAction as ActionConnectorProps<Config, unknown>)?.config - .apiProvider as OpenAiProviderType - ); + postSaveEventHandler={(connector: ActionConnector) => { + onConnectorSelectionChange(connector); refetchConnectors?.(); cleanupAndCloseModal(); }} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.test.tsx index 774098eba8b2e..3b1ff0be86181 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.test.tsx @@ -65,7 +65,6 @@ describe('ConnectorSelectorInline', () => { <ConnectorSelectorInline isDisabled={false} onConnectorModalVisibilityChange={noop} - onConnectorSelectionChange={noop} selectedConnectorId={undefined} selectedConversation={undefined} /> @@ -85,7 +84,6 @@ describe('ConnectorSelectorInline', () => { <ConnectorSelectorInline isDisabled={false} onConnectorModalVisibilityChange={noop} - onConnectorSelectionChange={noop} selectedConnectorId={'missing-connector-id'} selectedConversation={conversation} /> @@ -105,7 +103,6 @@ describe('ConnectorSelectorInline', () => { <ConnectorSelectorInline isDisabled={false} onConnectorModalVisibilityChange={noop} - onConnectorSelectionChange={noop} selectedConnectorId={mockConnectors[0].id} selectedConversation={conversation} /> diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.tsx index 66d7971731deb..d7f4a50f90ae9 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.tsx @@ -10,7 +10,6 @@ import React, { useCallback, useMemo, useState } from 'react'; import { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public'; -import { ActionConnectorProps } from '@kbn/triggers-actions-ui-plugin/public/types'; import { ConnectorAddModal } from '@kbn/triggers-actions-ui-plugin/public/common/constants'; import { GEN_AI_CONNECTOR_ID, @@ -23,20 +22,16 @@ import * as i18n from '../translations'; import { useLoadActionTypes } from '../use_load_action_types'; import { useAssistantContext } from '../../assistant_context'; import { useConversation } from '../../assistant/use_conversation'; +import { getGenAiConfig } from '../helpers'; export const ADD_NEW_CONNECTOR = 'ADD_NEW_CONNECTOR'; interface Props { isDisabled?: boolean; - onConnectorSelectionChange: (connectorId: string, provider: OpenAiProviderType) => void; selectedConnectorId?: string; selectedConversation?: Conversation; onConnectorModalVisibilityChange?: (isVisible: boolean) => void; } -interface Config { - apiProvider: string; -} - const inputContainerClassName = css` height: 32px; @@ -82,7 +77,6 @@ export const ConnectorSelectorInline: React.FC<Props> = React.memo( onConnectorModalVisibilityChange, selectedConnectorId, selectedConversation, - onConnectorSelectionChange, }) => { const [isOpen, setIsOpen] = useState<boolean>(false); const { actionTypeRegistry, assistantAvailability, http } = useAssistantContext(); @@ -136,9 +130,10 @@ export const ConnectorSelectorInline: React.FC<Props> = React.memo( const connectorOptions = useMemo(() => { return ( connectors?.map((connector) => { - const apiProvider: string | undefined = ( - connector as ActionConnectorProps<Config, unknown> - )?.config?.apiProvider; + const apiProvider = getGenAiConfig(connector)?.apiProvider; + const connectorDetails = connector.isPreconfigured + ? i18n.PRECONFIGURED_CONNECTOR + : apiProvider; return { value: connector.id, inputDisplay: ( @@ -149,9 +144,9 @@ export const ConnectorSelectorInline: React.FC<Props> = React.memo( dropdownDisplay: ( <React.Fragment key={connector.id}> <strong>{connector.name}</strong> - {apiProvider && ( + {connectorDetails && ( <EuiText size="xs" color="subdued"> - <p>{apiProvider}</p> + <p>{connectorDetails}</p> </EuiText> )} </React.Fragment> @@ -182,7 +177,7 @@ export const ConnectorSelectorInline: React.FC<Props> = React.memo( const handleOnBlur = useCallback(() => setIsOpen(false), []); const onChange = useCallback( - (connectorId: string, apiProvider?: OpenAiProviderType) => { + (connectorId: string, apiProvider?: OpenAiProviderType, model?: string) => { setIsOpen(false); if (connectorId === ADD_NEW_CONNECTOR) { @@ -191,31 +186,22 @@ export const ConnectorSelectorInline: React.FC<Props> = React.memo( return; } - const provider = - apiProvider ?? - ((connectors?.find((c) => c.id === connectorId) as ActionConnectorProps<Config, unknown>) - ?.config.apiProvider as OpenAiProviderType); - + const connector = connectors?.find((c) => c.id === connectorId); + const config = getGenAiConfig(connector); if (selectedConversation != null) { setApiConfig({ conversationId: selectedConversation.id, apiConfig: { ...selectedConversation.apiConfig, connectorId, - provider, + // With the inline component, prefer config args to handle 'new connector' case + provider: apiProvider ?? config?.apiProvider, + model: model ?? config?.defaultModel, }, }); } - - onConnectorSelectionChange(connectorId, provider); }, - [ - connectors, - selectedConversation, - onConnectorSelectionChange, - onConnectorModalVisibilityChange, - setApiConfig, - ] + [connectors, selectedConversation, onConnectorModalVisibilityChange, setApiConfig] ); const placeholderComponent = useMemo( @@ -276,11 +262,9 @@ export const ConnectorSelectorInline: React.FC<Props> = React.memo( <ConnectorAddModal actionType={actionType} onClose={cleanupAndCloseModal} - postSaveEventHandler={(savedAction: ActionConnector) => { - const provider = (savedAction as ActionConnectorProps<Config, unknown>)?.config - .apiProvider as OpenAiProviderType; - onChange(savedAction.id, provider); - onConnectorSelectionChange(savedAction.id, provider); + postSaveEventHandler={(connector: ActionConnector) => { + const config = getGenAiConfig(connector); + onChange(connector.id, config?.apiProvider, config?.defaultModel); refetchConnectors?.(); cleanupAndCloseModal(); }} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx index 23ccc51943655..9429ad9435ea7 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx @@ -14,11 +14,7 @@ import { ConnectorAddModal } from '@kbn/triggers-actions-ui-plugin/public/common import type { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public'; import { ActionType } from '@kbn/triggers-actions-ui-plugin/public'; -import { - GEN_AI_CONNECTOR_ID, - OpenAiProviderType, -} from '@kbn/stack-connectors-plugin/public/common'; -import { ActionConnectorProps } from '@kbn/triggers-actions-ui-plugin/public/types'; +import { GEN_AI_CONNECTOR_ID } from '@kbn/stack-connectors-plugin/public/common'; import { WELCOME_CONVERSATION } from '../../assistant/use_conversation/sample_conversations'; import { Conversation, Message } from '../../..'; import { useLoadActionTypes } from '../use_load_action_types'; @@ -30,6 +26,7 @@ import * as i18n from '../translations'; import { useAssistantContext } from '../../assistant_context'; import { useLoadConnectors } from '../use_load_connectors'; import { AssistantAvatar } from '../../assistant/assistant_avatar/assistant_avatar'; +import { getGenAiConfig } from '../helpers'; const ConnectorButtonWrapper = styled.div` margin-bottom: 10px; @@ -39,10 +36,6 @@ const SkipEuiText = styled(EuiText)` margin-top: 20px; `; -interface Config { - apiProvider: string; -} - export interface ConnectorSetupProps { conversation?: Conversation; onSetupComplete?: () => void; @@ -223,16 +216,17 @@ export const useConnectorSetup = ({ <ConnectorAddModal actionType={actionType} onClose={() => setIsConnectorModalVisible(false)} - postSaveEventHandler={(savedAction: ActionConnector) => { + postSaveEventHandler={(connector: ActionConnector) => { + const config = getGenAiConfig(connector); // Add connector to all conversations Object.values(conversations).forEach((c) => { setApiConfig({ conversationId: c.id, apiConfig: { ...c.apiConfig, - connectorId: savedAction.id, - provider: (savedAction as ActionConnectorProps<Config, unknown>)?.config - .apiProvider as OpenAiProviderType, + connectorId: connector.id, + provider: config?.apiProvider, + model: config?.defaultModel, }, }); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/helpers.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/helpers.tsx new file mode 100644 index 0000000000000..ffd9604ab328f --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/helpers.tsx @@ -0,0 +1,31 @@ +/* + * 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 { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public'; +import { ActionConnectorProps } from '@kbn/triggers-actions-ui-plugin/public/types'; +import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/common/gen_ai/constants'; + +interface GenAiConfig { + apiProvider?: OpenAiProviderType; + apiUrl?: string; + defaultModel?: string; +} + +/** + * Returns the GenAiConfig for a given ActionConnector. Note that if the connector is preconfigured, + * the config will be undefined as the connector is neither available nor editable. + * + * TODO: Extract and use separate types from GenAiConfig from '@kbn/stack-connectors-plugin/common/gen_ai/types' + * + * @param connector + */ +export const getGenAiConfig = (connector: ActionConnector | undefined): GenAiConfig | undefined => { + if (!connector?.isPreconfigured) { + return (connector as ActionConnectorProps<GenAiConfig, unknown>)?.config; + } + return undefined; +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/translations.ts b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/translations.ts index dbc692d6b5493..ae84527b21c7d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/translations.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/translations.ts @@ -31,6 +31,13 @@ export const WELCOME_SECURITY = i18n.translate( } ); +export const PRECONFIGURED_CONNECTOR = i18n.translate( + 'xpack.elasticAssistant.assistant.connectors.preconfiguredTitle', + { + defaultMessage: 'Preconfigured', + } +); + export const CONNECTOR_SELECTOR_TITLE = i18n.translate( 'xpack.elasticAssistant.assistant.connectors.connectorSelector.ariaLabel', { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx index c1aec33b2a2f7..fb2c17ddb2fa1 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx @@ -5,12 +5,18 @@ * 2.0. */ -import React, { useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { NewChat } from '@kbn/elastic-assistant'; import { useUserData } from '../../../../detections/components/user_info'; import { TabNavigation } from '../../../../common/components/navigation/tab_navigation'; import { usePrebuiltRulesStatus } from '../../../rule_management/logic/prebuilt_rules/use_prebuilt_rules_status'; import { useRuleManagementFilters } from '../../../rule_management/logic/use_rule_management_filters'; import * as i18n from './translations'; +import { getPromptContextFromDetectionRules } from '../../../../assistant/helpers'; +import { useRulesTableContext } from './rules_table/rules_table_context'; +import { useAssistantAvailability } from '../../../../assistant/use_assistant_availability'; +import * as i18nAssistant from '../../../../detections/pages/detection_engine/rules/translations'; export enum AllRulesTabs { management = 'management', @@ -71,7 +77,39 @@ export const RulesTableToolbar = React.memo(() => { [installedTotal, updateTotal, shouldDisplayRuleUpdatesTab] ); - return <TabNavigation navTabs={ruleTabs} />; + // Assistant integration for using selected rules as prompt context + const { hasAssistantPrivilege } = useAssistantAvailability(); + const { + state: { rules, selectedRuleIds }, + } = useRulesTableContext(); + const selectedRules = useMemo( + () => rules.filter((rule) => selectedRuleIds.includes(rule.id)), + [rules, selectedRuleIds] + ); + const getPromptContext = useCallback( + async () => getPromptContextFromDetectionRules(selectedRules), + [selectedRules] + ); + + return ( + <EuiFlexGroup justifyContent={'spaceBetween'}> + <EuiFlexItem grow={false}> + <TabNavigation navTabs={ruleTabs} /> + </EuiFlexItem> + <EuiFlexItem grow={false}> + {hasAssistantPrivilege && selectedRules.length > 0 && ( + <NewChat + category="detection-rules" + conversationId={i18nAssistant.DETECTION_RULES_CONVERSATION_ID} + description={i18nAssistant.RULE_MANAGEMENT_CONTEXT_DESCRIPTION} + getPromptContext={getPromptContext} + suggestedUserPrompt={i18nAssistant.EXPLAIN_THEN_SUMMARIZE_RULE_DETAILS} + tooltip={i18nAssistant.RULE_MANAGEMENT_CONTEXT_TOOLTIP} + /> + )} + </EuiFlexItem> + </EuiFlexGroup> + ); }); RulesTableToolbar.displayName = 'RulesTableToolbar'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx index 2f5a202459f79..b27a322331fc7 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx @@ -32,8 +32,8 @@ import { useInvalidateFindRulesQuery } from '../../../rule_management/api/hooks/ import { importRules } from '../../../rule_management/logic'; import { AllRules } from '../../components/rules_table'; import { RulesTableContextProvider } from '../../components/rules_table/rules_table/rules_table_context'; -import { SuperHeader } from './super_header'; import { useInvalidateFetchCoverageOverviewQuery } from '../../../rule_management/api/hooks/use_fetch_coverage_overview'; +import { HeaderPage } from '../../../../common/components/header_page'; const RulesPageComponent: React.FC = () => { const [isImportModalVisible, showImportModal, hideImportModal] = useBoolState(); @@ -110,7 +110,7 @@ const RulesPageComponent: React.FC = () => { <RulesTableContextProvider> <SecuritySolutionPageWrapper> - <SuperHeader> + <HeaderPage title={i18n.PAGE_TITLE}> <EuiFlexGroup alignItems="center" gutterSize="s" responsive={false} wrap={true}> <EuiFlexItem grow={false}> <AddElasticRulesButton isDisabled={!canUserCRUD || loading} /> @@ -149,7 +149,7 @@ const RulesPageComponent: React.FC = () => { </SecuritySolutionLinkButton> </EuiFlexItem> </EuiFlexGroup> - </SuperHeader> + </HeaderPage> <MaintenanceWindowCallout kibanaServices={kibanaServices} /> <AllRules data-test-subj="all-rules" /> </SecuritySolutionPageWrapper> diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/super_header.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/super_header.tsx deleted file mode 100644 index b3e7d6f3f6401..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/super_header.tsx +++ /dev/null @@ -1,61 +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 { NewChat } from '@kbn/elastic-assistant'; -import React, { useCallback, useMemo } from 'react'; - -import { useAssistantAvailability } from '../../../../assistant/use_assistant_availability'; -import { getPromptContextFromDetectionRules } from '../../../../assistant/helpers'; -import { HeaderPage } from '../../../../common/components/header_page'; -import { useRulesTableContext } from '../../components/rules_table/rules_table/rules_table_context'; -import * as i18n from '../../../../detections/pages/detection_engine/rules/translations'; - -export const SuperHeader: React.FC<{ children: React.ReactNode }> = React.memo(({ children }) => { - const { hasAssistantPrivilege } = useAssistantAvailability(); - const memoizedChildren = useMemo(() => children, [children]); - // Rules state - const { - state: { rules, selectedRuleIds }, - } = useRulesTableContext(); - - const selectedRules = useMemo( - () => rules.filter((rule) => selectedRuleIds.includes(rule.id)), - [rules, selectedRuleIds] - ); - - const getPromptContext = useCallback( - async () => getPromptContextFromDetectionRules(selectedRules), - [selectedRules] - ); - - return ( - <HeaderPage - title={ - <> - {i18n.PAGE_TITLE}{' '} - {hasAssistantPrivilege && selectedRules.length > 0 && ( - <NewChat - category="detection-rules" - conversationId={i18n.DETECTION_RULES_CONVERSATION_ID} - description={i18n.RULE_MANAGEMENT_CONTEXT_DESCRIPTION} - getPromptContext={getPromptContext} - iconType={null} - suggestedUserPrompt={i18n.EXPLAIN_THEN_SUMMARIZE_RULE_DETAILS} - tooltip={i18n.RULE_MANAGEMENT_CONTEXT_TOOLTIP} - > - {'🪄✨'} - </NewChat> - )} - </> - } - > - {memoizedChildren} - </HeaderPage> - ); -}); - -SuperHeader.displayName = 'NewChatComponent'; From e574281fbaaf766c88d9062f6f2e5b6ef3956a96 Mon Sep 17 00:00:00 2001 From: christineweng <18648970+christineweng@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:20:20 -0500 Subject: [PATCH 40/49] [Security Solution] Expandable flyout - update risk classification ui in entities overview (#165022) ## Summary This PR updates the right section of Expandable flyout -> Overview tab -> Insights -> Entities overview - In cases when risk classification is not available, an empty tag is shown instead of `Unknown` as previously presented - Added back tech preview tooltip icon to stay consistent with tech preview badge in the old flyout ![image](https://github.com/elastic/kibana/assets/18648970/a18b02d7-42ac-46fc-b58e-39fb94bb3c50) ### Checklist - [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] [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 --- .../components/host_entity_overview.test.tsx | 2 +- .../right/components/host_entity_overview.tsx | 29 ++++++++++++++----- .../flyout/right/components/test_ids.ts | 2 ++ .../flyout/right/components/translations.ts | 5 ++++ .../components/user_entity_overview.test.tsx | 2 +- .../right/components/user_entity_overview.tsx | 29 ++++++++++++++----- 6 files changed, 53 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/host_entity_overview.test.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/host_entity_overview.test.tsx index 8b61c823fb299..f737cfc006419 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/host_entity_overview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/host_entity_overview.test.tsx @@ -96,7 +96,7 @@ describe('<HostEntityContent />', () => { </TestProviders> ); expect(getByTestId(ENTITIES_HOST_OVERVIEW_OS_FAMILY_TEST_ID)).toHaveTextContent('—'); - expect(getByTestId(ENTITIES_HOST_OVERVIEW_RISK_LEVEL_TEST_ID)).toHaveTextContent('Unknown'); + expect(getByTestId(ENTITIES_HOST_OVERVIEW_RISK_LEVEL_TEST_ID)).toHaveTextContent('—'); }); }); diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/host_entity_overview.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/host_entity_overview.tsx index 18cac803894a9..88804ffb97d12 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/host_entity_overview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/host_entity_overview.tsx @@ -13,6 +13,7 @@ import { EuiIcon, useEuiTheme, useEuiFontSize, + EuiIconTip, } from '@elastic/eui'; import { css } from '@emotion/css'; import { getOr } from 'lodash/fp'; @@ -23,11 +24,8 @@ import { FirstLastSeen, FirstLastSeenType, } from '../../../common/components/first_last_seen/first_last_seen'; -import { - buildHostNamesFilter, - RiskScoreEntity, - RiskSeverity, -} from '../../../../common/search_strategy'; +import { buildHostNamesFilter, RiskScoreEntity } from '../../../../common/search_strategy'; +import { getEmptyTagValue } from '../../../common/components/empty_value'; import { DefaultFieldRenderer } from '../../../timelines/components/field_renderers/field_renderers'; import { DescriptionListStyled } from '../../../common/components/page'; import { OverviewDescriptionList } from '../../../common/components/overview_description_list'; @@ -44,7 +42,9 @@ import { ENTITIES_HOST_OVERVIEW_LAST_SEEN_TEST_ID, ENTITIES_HOST_OVERVIEW_RISK_LEVEL_TEST_ID, ENTITIES_HOST_OVERVIEW_LINK_TEST_ID, + TECHNICAL_PREVIEW_ICON_TEST_ID, } from './test_ids'; +import { TECHNICAL_PREVIEW_TITLE, TECHNICAL_PREVIEW_MESSAGE } from './translations'; import { LeftPanelInsightsTab, LeftPanelKey } from '../../left'; const HOST_ICON = 'storage'; @@ -146,13 +146,28 @@ export const HostEntityOverview: React.FC<HostEntityOverviewProps> = ({ hostName const hostRiskData = hostRisk && hostRisk.length > 0 ? hostRisk[0] : undefined; return [ { - title: i18n.HOST_RISK_CLASSIFICATION, + title: ( + <> + {i18n.HOST_RISK_CLASSIFICATION} + <EuiIconTip + title={TECHNICAL_PREVIEW_TITLE} + size="m" + type="iInCircle" + content={TECHNICAL_PREVIEW_MESSAGE} + position="bottom" + iconProps={{ + className: 'eui-alignTop', + }} + data-test-subj={TECHNICAL_PREVIEW_ICON_TEST_ID} + /> + </> + ), description: ( <> {hostRiskData ? ( <RiskScore severity={hostRiskData.host.risk.calculated_level} /> ) : ( - <RiskScore severity={RiskSeverity.unknown} /> + getEmptyTagValue() )} </> ), diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts index 0d7bac7493e6a..c4eb67f5ddba9 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts +++ b/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts @@ -95,6 +95,8 @@ export const ENTITIES_HOST_OVERVIEW_LINK_TEST_ID = `${ENTITIES_HOST_OVERVIEW_TES export const ENTITIES_HOST_OVERVIEW_OS_FAMILY_TEST_ID = `${ENTITIES_HOST_OVERVIEW_TEST_ID}OsFamily`; export const ENTITIES_HOST_OVERVIEW_LAST_SEEN_TEST_ID = `${ENTITIES_HOST_OVERVIEW_TEST_ID}LastSeen`; export const ENTITIES_HOST_OVERVIEW_RISK_LEVEL_TEST_ID = `${ENTITIES_HOST_OVERVIEW_TEST_ID}RiskLevel`; +export const TECHNICAL_PREVIEW_ICON_TEST_ID = + 'securitySolutionDocumentDetailsFlyoutTechnicalPreviewIcon'; /* Insights Threat Intelligence */ diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts b/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts index 24df07b006401..3a04a68ac0ebf 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts +++ b/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts @@ -300,6 +300,11 @@ export const RESPONSE_EMPTY = i18n.translate('xpack.securitySolution.flyout.resp defaultMessage: 'There are no response actions defined for this event.', }); +export const TECHNICAL_PREVIEW_TITLE = i18n.translate( + 'xpack.securitySolution.flyout.documentDetails.technicalPreviewTitle', + { defaultMessage: 'Technical preview' } +); + export const TECHNICAL_PREVIEW_MESSAGE = i18n.translate( 'xpack.securitySolution.flyout.documentDetails.technicalPreviewMessage', { diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/user_entity_overview.test.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/user_entity_overview.test.tsx index 4739130949e96..821b0ee5d19f6 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/user_entity_overview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/user_entity_overview.test.tsx @@ -96,7 +96,7 @@ describe('<UserEntityOverview />', () => { </TestProviders> ); expect(getByTestId(ENTITIES_USER_OVERVIEW_DOMAIN_TEST_ID)).toHaveTextContent('—'); - expect(getByTestId(ENTITIES_USER_OVERVIEW_RISK_LEVEL_TEST_ID)).toHaveTextContent('Unknown'); + expect(getByTestId(ENTITIES_USER_OVERVIEW_RISK_LEVEL_TEST_ID)).toHaveTextContent('—'); }); }); diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/user_entity_overview.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/user_entity_overview.tsx index ed3da595b7a21..998f6f71b02a7 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/user_entity_overview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/user_entity_overview.tsx @@ -13,6 +13,7 @@ import { EuiLink, useEuiTheme, useEuiFontSize, + EuiIconTip, } from '@elastic/eui'; import { css } from '@emotion/css'; import { getOr } from 'lodash/fp'; @@ -25,11 +26,8 @@ import { FirstLastSeen, FirstLastSeenType, } from '../../../common/components/first_last_seen/first_last_seen'; -import { - buildUserNamesFilter, - RiskScoreEntity, - RiskSeverity, -} from '../../../../common/search_strategy'; +import { buildUserNamesFilter, RiskScoreEntity } from '../../../../common/search_strategy'; +import { getEmptyTagValue } from '../../../common/components/empty_value'; import { DefaultFieldRenderer } from '../../../timelines/components/field_renderers/field_renderers'; import { DescriptionListStyled } from '../../../common/components/page'; import { OverviewDescriptionList } from '../../../common/components/overview_description_list'; @@ -44,7 +42,9 @@ import { ENTITIES_USER_OVERVIEW_LAST_SEEN_TEST_ID, ENTITIES_USER_OVERVIEW_RISK_LEVEL_TEST_ID, ENTITIES_USER_OVERVIEW_LINK_TEST_ID, + TECHNICAL_PREVIEW_ICON_TEST_ID, } from './test_ids'; +import { TECHNICAL_PREVIEW_TITLE, TECHNICAL_PREVIEW_MESSAGE } from './translations'; import { useObservedUserDetails } from '../../../explore/users/containers/users/observed_details'; const USER_ICON = 'user'; @@ -145,13 +145,28 @@ export const UserEntityOverview: React.FC<UserEntityOverviewProps> = ({ userName return [ { - title: i18n.USER_RISK_CLASSIFICATION, + title: ( + <> + {i18n.USER_RISK_CLASSIFICATION} + <EuiIconTip + title={TECHNICAL_PREVIEW_TITLE} + size="m" + type="iInCircle" + content={TECHNICAL_PREVIEW_MESSAGE} + position="bottom" + iconProps={{ + className: 'eui-alignTop', + }} + data-test-subj={TECHNICAL_PREVIEW_ICON_TEST_ID} + /> + </> + ), description: ( <> {userRiskData ? ( <RiskScore severity={userRiskData.user.risk.calculated_level} /> ) : ( - <RiskScore severity={RiskSeverity.unknown} /> + getEmptyTagValue() )} </> ), From 145fefee3f2ac114009ed71148f04faa5c316621 Mon Sep 17 00:00:00 2001 From: Rickyanto Ang <rickyangwyn@gmail.com> Date: Mon, 28 Aug 2023 15:43:03 -0700 Subject: [PATCH 41/49] [Cloud Security][CIS GCP]cis gcp now use updated gcp field name + small last minute changes (#164792) This PR is for updating GCP forms - Manifest for GCP has been changed (this PR updates the field name that was updated on the manifest) - EuiCodeBlock for CloudShell is interactive now - Static hover name for AWS and GCP icon on dashboard - MIN_VERSION for CIS GCP has now been update to 1.5.2 from 1.5.0 <img width="739" alt="Screenshot 2023-08-24 at 10 58 44 PM" src="https://github.com/elastic/kibana/assets/8703149/b88f4787-8396-4913-a475-5a381c802021"> ## Summary --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../common/constants.ts | 12 +- .../cloud_security_posture/common/types.ts | 6 + .../common/utils/helpers.test.ts | 104 ++++++++++++++++++ .../common/utils/helpers.ts | 28 ++++- .../public/common/constants.ts | 2 +- .../components/accounts_evaluated_widget.tsx | 4 +- .../fleet_extensions/gcp_credential_form.tsx | 78 ++++++------- .../components/fleet_extensions/mocks.ts | 9 +- .../policy_template_form.test.tsx | 22 ++-- .../components/google_cloud_shell_guide.tsx | 4 +- 10 files changed, 203 insertions(+), 66 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/constants.ts b/x-pack/plugins/cloud_security_posture/common/constants.ts index 5ba3648638e61..fa5737f7f1531 100644 --- a/x-pack/plugins/cloud_security_posture/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/common/constants.ts @@ -5,7 +5,12 @@ * 2.0. */ -import { PostureTypes, VulnSeverity, AwsCredentialsTypeFieldMap } from './types'; +import { + PostureTypes, + VulnSeverity, + AwsCredentialsTypeFieldMap, + GcpCredentialsTypeFieldMap, +} from './types'; export const STATUS_ROUTE_PATH = '/internal/cloud_security_posture/status'; export const STATUS_API_CURRENT_VERSION = '1'; @@ -143,3 +148,8 @@ export const SETUP_ACCESS_CLOUD_SHELL = 'google_cloud_shell'; export const SETUP_ACCESS_MANUAL = 'manual'; export const DETECTION_ENGINE_ALERTS_INDEX_DEFAULT = '.alerts-security.alerts-default'; + +export const GCP_CREDENTIALS_TYPE_TO_FIELDS_MAP: GcpCredentialsTypeFieldMap = { + 'credentials-file': ['gcp.credentials.file'], + 'credentials-json': ['gcp.credentials.json'], +}; diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index 956493de4c573..f2b6c00399915 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -24,6 +24,12 @@ export type AwsCredentialsTypeFieldMap = { [key in AwsCredentialsType]: string[]; }; +export type GcpCredentialsType = 'credentials-file' | 'credentials-json'; + +export type GcpCredentialsTypeFieldMap = { + [key in GcpCredentialsType]: string[]; +}; + export type Evaluation = 'passed' | 'failed' | 'NA'; export type PostureTypes = 'cspm' | 'kspm' | 'vuln_mgmt' | 'all'; diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts index 479cc2f62c36a..7e7d25a5b28bd 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts @@ -185,5 +185,109 @@ describe('test helper methods', () => { shared_credential_file: { value: undefined, type: 'text' }, }); }); + + it('when aws credential type is undefined, return unchanged policy', () => { + const mockPackagePolicy = createPackagePolicyMock(); + mockPackagePolicy.inputs = [ + { + type: 'cloudbeat/cis_eks', + enabled: true, + streams: [ + { + id: 'findings', + enabled: true, + data_stream: { + dataset: 'cloud_security_posture.findings', + type: 'logs', + }, + vars: { + 'aws.credentials.type': { value: undefined }, + access_key_id: { value: 'used', type: 'text' }, + credential_profile_name: { value: 'unused', type: 'text' }, + role_arn: { value: 'unused' }, + secret_access_key: { value: 'used', type: 'text' }, + session_token: { value: 'unused', type: 'text' }, + shared_credential_file: { value: 'unused', type: 'text' }, + }, + }, + ], + }, + ]; + + const cleanedPackage = cleanupCredentials(mockPackagePolicy); + expect(cleanedPackage.inputs[0].streams[0].vars).toEqual({ + 'aws.credentials.type': { value: undefined }, + access_key_id: { value: 'used', type: 'text' }, + credential_profile_name: { value: 'unused', type: 'text' }, + role_arn: { value: 'unused' }, + secret_access_key: { value: 'used', type: 'text' }, + session_token: { value: 'unused', type: 'text' }, + shared_credential_file: { value: 'unused', type: 'text' }, + }); + }); + + it('cleans unused gcp credential methods, when using credentials-file method ', () => { + const mockPackagePolicy = createPackagePolicyMock(); + mockPackagePolicy.inputs = [ + { + type: 'cloudbeat/cis_gcp', + enabled: true, + streams: [ + { + id: 'findings', + enabled: true, + data_stream: { + dataset: 'cloud_security_posture.findings', + type: 'logs', + }, + vars: { + 'gcp.credentials.type': { value: 'credentials-file' }, + 'gcp.credentials.file': { value: 'used' }, + 'gcp.credentials.json': { value: 'unused' }, + }, + }, + ], + }, + ]; + + const cleanedPackage = cleanupCredentials(mockPackagePolicy); + expect(cleanedPackage.inputs[0].streams[0].vars).toEqual({ + 'gcp.credentials.type': { value: 'credentials-file' }, + 'gcp.credentials.file': { value: 'used' }, + 'gcp.credentials.json': { value: undefined }, + }); + }); + + it('when gcp credential type is undefined, return unchanged policy', () => { + const mockPackagePolicy = createPackagePolicyMock(); + mockPackagePolicy.inputs = [ + { + type: 'cloudbeat/cis_gcp', + enabled: true, + streams: [ + { + id: 'findings', + enabled: true, + data_stream: { + dataset: 'cloud_security_posture.findings', + type: 'logs', + }, + vars: { + 'gcp.credentials.type': { value: undefined }, + 'gcp.credentials.file': { value: 'used' }, + 'gcp.credentials.json': { value: 'unused' }, + }, + }, + ], + }, + ]; + + const cleanedPackage = cleanupCredentials(mockPackagePolicy); + expect(cleanedPackage.inputs[0].streams[0].vars).toEqual({ + 'gcp.credentials.type': { value: undefined }, + 'gcp.credentials.file': { value: 'used' }, + 'gcp.credentials.json': { value: 'unused' }, + }); + }); }); }); diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index f50a5ef47bb59..9cf31c944d27a 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -19,8 +19,15 @@ import { CLOUDBEAT_VANILLA, CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, AWS_CREDENTIALS_TYPE_TO_FIELDS_MAP, + GCP_CREDENTIALS_TYPE_TO_FIELDS_MAP, } from '../constants'; -import type { BenchmarkId, Score, BaseCspSetupStatus, AwsCredentialsType } from '../types'; +import type { + BenchmarkId, + Score, + BaseCspSetupStatus, + AwsCredentialsType, + GcpCredentialsType, +} from '../types'; /** * @example @@ -103,12 +110,21 @@ export const getStatusForIndexName = (indexName: string, status?: BaseCspSetupSt export const cleanupCredentials = (packagePolicy: NewPackagePolicy | UpdatePackagePolicy) => { const enabledInput = packagePolicy.inputs.find((i) => i.enabled); - const credentialType: AwsCredentialsType | undefined = + const awsCredentialType: AwsCredentialsType | undefined = enabledInput?.streams?.[0].vars?.['aws.credentials.type']?.value; - - if (credentialType) { - const credsToKeep = AWS_CREDENTIALS_TYPE_TO_FIELDS_MAP[credentialType]; - const credFields = Object.values(AWS_CREDENTIALS_TYPE_TO_FIELDS_MAP).flat(); + const gcpCredentialType: GcpCredentialsType | undefined = + enabledInput?.streams?.[0].vars?.['gcp.credentials.type']?.value; + + if (awsCredentialType || gcpCredentialType) { + let credsToKeep: string[] = [' ']; + let credFields: string[] = [' ']; + if (awsCredentialType) { + credsToKeep = AWS_CREDENTIALS_TYPE_TO_FIELDS_MAP[awsCredentialType]; + credFields = Object.values(AWS_CREDENTIALS_TYPE_TO_FIELDS_MAP).flat(); + } else if (gcpCredentialType) { + credsToKeep = GCP_CREDENTIALS_TYPE_TO_FIELDS_MAP[gcpCredentialType]; + credFields = Object.values(GCP_CREDENTIALS_TYPE_TO_FIELDS_MAP).flat(); + } if (credsToKeep) { // we need to return a copy of the policy with the unused diff --git a/x-pack/plugins/cloud_security_posture/public/common/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/constants.ts index 8f51456c009e4..4a5d5bfc7bd9a 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/constants.ts @@ -214,7 +214,7 @@ export const cloudPostureIntegrations: CloudPostureIntegrations = { }, }; export const FINDINGS_DOCS_URL = 'https://ela.st/findings'; -export const MIN_VERSION_GCP_CIS = '1.5.0'; +export const MIN_VERSION_GCP_CIS = '1.5.2'; export const NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS = 10000; diff --git a/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx b/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx index 490df0c3d9215..39b37c85aee39 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx @@ -33,8 +33,8 @@ export const AccountsEvaluatedWidget = ({ const cisAwsClusterAmount = filterClustersById(CIS_AWS).length; const cisGcpClusterAmount = filterClustersById(CIS_GCP).length; - const cisAwsBenchmarkName = filterClustersById(CIS_AWS)[0]?.meta.benchmark.name || ''; - const cisGcpBenchmarkName = filterClustersById(CIS_GCP)[0]?.meta.benchmark.name || ''; + const cisAwsBenchmarkName = 'Amazon Web Services (AWS)'; + const cisGcpBenchmarkName = 'Google Cloud Platform (GCP)'; return ( <> diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx index 88f6ff77fde21..74685000a98cc 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx @@ -110,56 +110,58 @@ const GoogleCloudShellSetup = () => { ); }; -type GcpFields = Record<string, { label: string; type?: 'password' | 'text' }>; +const credentialOptionsList = [ + { + text: i18n.translate('xpack.csp.gcpIntegration.credentialsFileOption', { + defaultMessage: 'Credentials File', + }), + value: 'credentials-file', + }, + { + text: i18n.translate('xpack.csp.gcpIntegration.credentialsJsonOption', { + defaultMessage: 'Credentials JSON', + }), + value: 'credentials-json', + }, +]; + +type GcpFields = Record<string, { label: string; type?: 'password' | 'text'; value?: string }>; interface GcpInputFields { fields: GcpFields; } export const gcpField: GcpInputFields = { fields: { - project_id: { + 'gcp.project_id': { label: i18n.translate('xpack.csp.gcpIntegration.projectidFieldLabel', { defaultMessage: 'Project ID', }), type: 'text', }, - credentials_file: { + 'gcp.credentials.file': { label: i18n.translate('xpack.csp.findings.gcpIntegration.gcpInputText.credentialFileText', { defaultMessage: 'Path to JSON file containing the credentials and key used to subscribe', }), type: 'text', }, - credentials_json: { + 'gcp.credentials.json': { label: i18n.translate('xpack.csp.findings.gcpIntegration.gcpInputText.credentialJSONText', { defaultMessage: 'JSON blob containing the credentials and key used to subscribe', }), type: 'text', }, - credentials_type: { + 'gcp.credentials.type': { label: i18n.translate( 'xpack.csp.findings.gcpIntegration.gcpInputText.credentialSelectBoxTitle', - { defaultMessage: 'Credential' } + { + defaultMessage: 'Credential', + } ), type: 'text', }, }, }; -const credentialOptionsList = [ - { - text: i18n.translate('xpack.csp.gcpIntegration.credentialsFileOption', { - defaultMessage: 'Credentials File', - }), - value: 'credentials-file', - }, - { - text: i18n.translate('xpack.csp.gcpIntegration.credentialsJsonOption', { - defaultMessage: 'Credentials JSON', - }), - value: 'credentials-json', - }, -]; - const getSetupFormatOptions = (): Array<{ id: SetupFormatGCP; label: string; @@ -193,10 +195,7 @@ interface GcpFormProps { onChange: any; } -const getInputVarsFields = ( - input: NewPackagePolicyInput, - fields: GcpInputFields[keyof GcpInputFields] -) => +const getInputVarsFields = (input: NewPackagePolicyInput, fields: GcpFields) => Object.entries(input.streams[0].vars || {}) .filter(([id]) => id in fields) .map(([id, inputVar]) => { @@ -348,7 +347,7 @@ export const GcpCredentialsForm = ({ // Integration is Invalid IF Version is not at least 1.5.0 OR Setup Access is manual but Project ID is empty useEffect(() => { const isProjectIdEmpty = - setupFormat === SETUP_ACCESS_MANUAL && !getFieldById('project_id')?.value; + setupFormat === SETUP_ACCESS_MANUAL && !getFieldById('gcp.project_id')?.value; const isInvalidPolicy = isInvalid || isProjectIdEmpty; setIsValid(!isInvalidPolicy); @@ -411,19 +410,21 @@ const GcpInputVarFields = ({ const getFieldById = (id: keyof GcpInputFields['fields']) => { return fields.find((element) => element.id === id); }; - const projectIdFields = getFieldById('project_id'); - const credentialsTypeFields = getFieldById('credentials_type') || credentialOptionsList[0]; - const credentialFilesFields = getFieldById('credentials_file'); - const credentialJSONFields = getFieldById('credentials_json'); + const projectIdFields = getFieldById('gcp.project_id'); + const credentialsTypeFields = getFieldById('gcp.credentials.type'); + const credentialFilesFields = getFieldById('gcp.credentials.file'); + const credentialJSONFields = getFieldById('gcp.credentials.json'); const credentialFieldValue = credentialOptionsList[0].value; const credentialJSONValue = credentialOptionsList[1].value; + const credentialsTypeValue = credentialsTypeFields?.value || credentialOptionsList[0].value; + return ( <div> <EuiForm component="form"> {projectIdFields && ( - <EuiFormRow fullWidth label={gcpField.fields.project_id.label}> + <EuiFormRow fullWidth label={gcpField.fields['gcp.project_id'].label}> <EuiFieldText data-test-subj={CIS_GCP_INPUT_FIELDS_TEST_SUBJECTS.PROJECT_ID} id={projectIdFields.id} @@ -433,22 +434,21 @@ const GcpInputVarFields = ({ /> </EuiFormRow> )} - {credentialFilesFields && credentialJSONFields && ( - <EuiFormRow fullWidth label={gcpField.fields.credentials_type.label}> + {credentialsTypeFields && credentialFilesFields && credentialJSONFields && ( + <EuiFormRow fullWidth label={gcpField.fields['gcp.credentials.type'].label}> <EuiSelect data-test-subj={CIS_GCP_INPUT_FIELDS_TEST_SUBJECTS.CREDENTIALS_TYPE} fullWidth options={credentialOptionsList} value={credentialsTypeFields?.value || credentialOptionsList[0].value} onChange={(optionElem) => { - onChange('credentials_type', optionElem.target.value); + onChange(credentialsTypeFields?.id, optionElem.target.value); }} /> </EuiFormRow> )} - - {credentialsTypeFields.value === credentialFieldValue && credentialFilesFields && ( - <EuiFormRow fullWidth label={gcpField.fields.credentials_file.label}> + {credentialsTypeValue === credentialFieldValue && credentialFilesFields && ( + <EuiFormRow fullWidth label={gcpField.fields['gcp.credentials.file'].label}> <EuiFieldText data-test-subj={CIS_GCP_INPUT_FIELDS_TEST_SUBJECTS.CREDENTIALS_FILE} id={credentialFilesFields.id} @@ -458,8 +458,8 @@ const GcpInputVarFields = ({ /> </EuiFormRow> )} - {credentialsTypeFields?.value === credentialJSONValue && credentialJSONFields && ( - <EuiFormRow fullWidth label={gcpField.fields.credentials_json.label}> + {credentialsTypeValue === credentialJSONValue && credentialJSONFields && ( + <EuiFormRow fullWidth label={gcpField.fields['gcp.credentials.json'].label}> <EuiTextArea data-test-subj={CIS_GCP_INPUT_FIELDS_TEST_SUBJECTS.CREDENTIALS_JSON} id={credentialJSONFields.id} diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts index 6d8b8b648bf20..2f2d44895db36 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts @@ -80,7 +80,7 @@ export const getMockPackageInfoCspmAWS = (packageVersion = '1.5.0') => { } as PackageInfo; }; -export const getMockPackageInfoCspmGCP = (packageVersion = '1.5.0') => { +export const getMockPackageInfoCspmGCP = (packageVersion = '1.5.2') => { return { version: packageVersion, name: 'cspm', @@ -130,9 +130,10 @@ const getPolicyMock = ( }; const gcpVarsMock = { - project_id: { type: 'text' }, - credentials_file: { type: 'text' }, - credentials_json: { type: 'text' }, + 'gcp.project_id': { type: 'text' }, + 'gcp.credentials.file': { type: 'text' }, + 'gcp.credentials.json': { type: 'text' }, + 'gcp.credentials.type': { type: 'text' }, }; const dataStream = { type: 'logs', dataset: 'cloud_security_posture.findings' }; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx index 213d03b95266f..c5d4c0e8de3e2 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx @@ -979,7 +979,7 @@ describe('<CspPolicyTemplateForm />', () => { }); describe('GCP Credentials input fields', () => { - it(`renders ${CLOUDBEAT_GCP} Not supported when version is not at least version 1.5.0`, () => { + it(`renders ${CLOUDBEAT_GCP} Not supported when version is not at least version 1.5.2`, () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { credentials_type: { value: 'credentials-file' }, @@ -1024,7 +1024,7 @@ describe('<CspPolicyTemplateForm />', () => { it(`project ID is required for Manual users`, () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - project_id: { value: undefined }, + 'gcp.project_id': { value: undefined }, setup_access: { value: 'manual' }, }); @@ -1036,7 +1036,7 @@ describe('<CspPolicyTemplateForm />', () => { updatedPolicy: policy, }); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - project_id: { value: '' }, + 'gcp.project_id': { value: '' }, setup_access: { value: 'manual' }, }); rerender(<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmGCP()} />); @@ -1049,7 +1049,7 @@ describe('<CspPolicyTemplateForm />', () => { it(`renders ${CLOUDBEAT_GCP} Credentials File fields`, () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - credentials_type: { value: 'credentials-file' }, + 'gcp.credentials.type': { value: 'credentials-file' }, setup_access: { value: 'manual' }, }); @@ -1067,8 +1067,8 @@ describe('<CspPolicyTemplateForm />', () => { it(`updates ${CLOUDBEAT_GCP} Credentials File fields`, () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - project_id: { value: 'a' }, - credentials_type: { value: 'credentials-file' }, + 'gcp.project_id': { value: 'a' }, + 'gcp.credentials.type': { value: 'credentials-file' }, setup_access: { value: 'manual' }, }); @@ -1079,7 +1079,7 @@ describe('<CspPolicyTemplateForm />', () => { userEvent.type(getByTestId(CIS_GCP_INPUT_FIELDS_TEST_SUBJECTS.CREDENTIALS_FILE), 'b'); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - credentials_file: { value: 'b' }, + 'gcp.credentials.file': { value: 'b' }, }); expect(onChange).toHaveBeenCalledWith({ @@ -1092,7 +1092,7 @@ describe('<CspPolicyTemplateForm />', () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { setup_access: { value: 'manual' }, - credentials_type: { value: 'credentials-json' }, + 'gcp.credentials.type': { value: 'credentials-json' }, }); const { getByRole, getByLabelText } = render( @@ -1109,8 +1109,8 @@ describe('<CspPolicyTemplateForm />', () => { it(`updates ${CLOUDBEAT_GCP} Credentials JSON fields`, () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - project_id: { value: 'a' }, - credentials_type: { value: 'credentials-json' }, + 'gcp.project_id': { value: 'a' }, + 'gcp.credentials.type': { value: 'credentials-json' }, setup_access: { value: 'manual' }, }); @@ -1121,7 +1121,7 @@ describe('<CspPolicyTemplateForm />', () => { userEvent.type(getByTestId(CIS_GCP_INPUT_FIELDS_TEST_SUBJECTS.CREDENTIALS_JSON), 'b'); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - credentials_json: { value: 'b' }, + 'gcp.credentials.json': { value: 'b' }, }); expect(onChange).toHaveBeenCalledWith({ diff --git a/x-pack/plugins/fleet/public/components/google_cloud_shell_guide.tsx b/x-pack/plugins/fleet/public/components/google_cloud_shell_guide.tsx index 89b490f2d0967..d494fc1075f41 100644 --- a/x-pack/plugins/fleet/public/components/google_cloud_shell_guide.tsx +++ b/x-pack/plugins/fleet/public/components/google_cloud_shell_guide.tsx @@ -50,10 +50,10 @@ export const GoogleCloudShellGuide = (props: { commandText: string }) => { <> <FormattedMessage id="xpack.fleet.googleCloudShell.guide.steps.copy" - defaultMessage="Copy the following command and replace <PROJECT_ID> with your project ID." + defaultMessage="Replace <PROJECT_ID> in the following command with your project ID and copy the command" /> <EuiSpacer size="m" /> - <EuiCodeBlock language="bash" isCopyable> + <EuiCodeBlock language="bash" isCopyable contentEditable="true"> {props.commandText} </EuiCodeBlock> </> From a8de305b2c205bdb8b86f2353d07d8681c78481e Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 29 Aug 2023 01:06:05 -0400 Subject: [PATCH 42/49] [api-docs] 2023-08-29 Daily api_docs build (#165056) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/444 --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.mdx | 2 +- api_docs/apm.devdocs.json | 54 ++++- api_docs/apm.mdx | 2 +- api_docs/apm_data_access.devdocs.json | 8 +- api_docs/apm_data_access.mdx | 2 +- api_docs/asset_manager.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_chat.mdx | 2 +- api_docs/cloud_chat_provider.mdx | 2 +- api_docs/cloud_data_migration.mdx | 2 +- api_docs/cloud_defend.mdx | 2 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/content_management.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.devdocs.json | 8 +- api_docs/data.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.devdocs.json | 2 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.devdocs.json | 12 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/deprecations_by_api.mdx | 2 +- api_docs/deprecations_by_plugin.mdx | 2 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.mdx | 2 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/ecs_data_quality_dashboard.mdx | 2 +- api_docs/elastic_assistant.devdocs.json | 101 ++++++++ api_docs/elastic_assistant.mdx | 33 +++ api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_log.mdx | 2 +- api_docs/exploratory_view.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/files_management.mdx | 2 +- api_docs/fleet.mdx | 2 +- api_docs/global_search.mdx | 2 +- api_docs/guided_onboarding.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/image_embeddable.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.devdocs.json | 126 ++++++++++ api_docs/index_management.mdx | 4 +- api_docs/infra.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_utils.mdx | 2 +- .../kbn_alerting_api_integration_helpers.mdx | 2 +- api_docs/kbn_alerting_state_types.mdx | 2 +- api_docs/kbn_alerts_as_data_utils.mdx | 2 +- api_docs/kbn_alerts_ui_shared.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_client.mdx | 2 +- ..._analytics_shippers_elastic_v3_browser.mdx | 2 +- ...n_analytics_shippers_elastic_v3_common.mdx | 2 +- ...n_analytics_shippers_elastic_v3_server.mdx | 2 +- api_docs/kbn_analytics_shippers_fullstory.mdx | 2 +- api_docs/kbn_analytics_shippers_gainsight.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_synthtrace_client.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_cases_components.mdx | 2 +- api_docs/kbn_cell_actions.mdx | 2 +- api_docs/kbn_chart_expressions_common.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_code_editor.mdx | 2 +- api_docs/kbn_code_editor_mocks.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- .../kbn_content_management_content_editor.mdx | 2 +- ...tent_management_tabbed_table_list_view.mdx | 2 +- ...kbn_content_management_table_list_view.mdx | 2 +- ...ntent_management_table_list_view_table.mdx | 2 +- api_docs/kbn_content_management_utils.mdx | 2 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- api_docs/kbn_core_analytics_server.mdx | 2 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- api_docs/kbn_core_application_browser.mdx | 2 +- .../kbn_core_application_browser_internal.mdx | 2 +- .../kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- api_docs/kbn_core_apps_browser_internal.mdx | 2 +- api_docs/kbn_core_apps_browser_mocks.mdx | 2 +- api_docs/kbn_core_apps_server_internal.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- .../kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- .../kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_custom_branding_browser.mdx | 2 +- ..._core_custom_branding_browser_internal.mdx | 2 +- ...kbn_core_custom_branding_browser_mocks.mdx | 2 +- api_docs/kbn_core_custom_branding_common.mdx | 2 +- api_docs/kbn_core_custom_branding_server.mdx | 2 +- ...n_core_custom_branding_server_internal.mdx | 2 +- .../kbn_core_custom_branding_server_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- ...kbn_core_deprecations_browser_internal.mdx | 2 +- .../kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- .../kbn_core_deprecations_server_internal.mdx | 2 +- .../kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- ...e_elasticsearch_client_server_internal.mdx | 2 +- ...core_elasticsearch_client_server_mocks.mdx | 2 +- ...kbn_core_elasticsearch_server.devdocs.json | 54 +++++ api_docs/kbn_core_elasticsearch_server.mdx | 4 +- ...elasticsearch_server_internal.devdocs.json | 11 + ...kbn_core_elasticsearch_server_internal.mdx | 4 +- ...re_elasticsearch_server_mocks.devdocs.json | 220 ++++++++---------- .../kbn_core_elasticsearch_server_mocks.mdx | 7 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- .../kbn_core_http_context_server_mocks.mdx | 2 +- ...re_http_request_handler_context_server.mdx | 2 +- api_docs/kbn_core_http_resources_server.mdx | 2 +- ...bn_core_http_resources_server_internal.mdx | 2 +- .../kbn_core_http_resources_server_mocks.mdx | 2 +- .../kbn_core_http_router_server_internal.mdx | 2 +- .../kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.devdocs.json | 32 ++- api_docs/kbn_core_http_server.mdx | 2 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- ...kbn_core_integrations_browser_internal.mdx | 2 +- .../kbn_core_integrations_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_browser.mdx | 2 +- api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_server.mdx | 2 +- api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +- api_docs/kbn_core_logging_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_common_internal.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- ...ore_metrics_collectors_server_internal.mdx | 2 +- ...n_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- ...bn_core_notifications_browser_internal.mdx | 2 +- .../kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- .../kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_browser.mdx | 2 +- api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_server.mdx | 2 +- api_docs/kbn_core_plugins_server_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- .../kbn_core_rendering_server_internal.mdx | 2 +- api_docs/kbn_core_rendering_server_mocks.mdx | 2 +- api_docs/kbn_core_root_server_internal.mdx | 2 +- .../kbn_core_saved_objects_api_browser.mdx | 2 +- ...core_saved_objects_api_server.devdocs.json | 119 ++++++---- .../kbn_core_saved_objects_api_server.mdx | 4 +- ...bn_core_saved_objects_api_server_mocks.mdx | 2 +- ...ore_saved_objects_base_server_internal.mdx | 2 +- ...n_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- ...bn_core_saved_objects_browser_internal.mdx | 2 +- .../kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...cts_migration_server_internal.devdocs.json | 30 ++- ...aved_objects_migration_server_internal.mdx | 4 +- ...e_saved_objects_migration_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- ...kbn_core_saved_objects_server_internal.mdx | 2 +- .../kbn_core_saved_objects_server_mocks.mdx | 2 +- .../kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_status_common.mdx | 2 +- api_docs/kbn_core_status_common_internal.mdx | 2 +- api_docs/kbn_core_status_server.mdx | 2 +- api_docs/kbn_core_status_server_internal.mdx | 2 +- api_docs/kbn_core_status_server_mocks.mdx | 2 +- ...core_test_helpers_deprecations_getters.mdx | 2 +- ...n_core_test_helpers_http_setup_browser.mdx | 2 +- ..._core_test_helpers_kbn_server.devdocs.json | 12 +- api_docs/kbn_core_test_helpers_kbn_server.mdx | 2 +- ...n_core_test_helpers_so_type_serializer.mdx | 2 +- api_docs/kbn_core_test_helpers_test_utils.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- .../kbn_core_ui_settings_browser_internal.mdx | 2 +- .../kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_ui_settings_server.mdx | 2 +- .../kbn_core_ui_settings_server_internal.mdx | 2 +- .../kbn_core_ui_settings_server_mocks.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- .../kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_core_user_settings_server.mdx | 2 +- ...kbn_core_user_settings_server_internal.mdx | 2 +- .../kbn_core_user_settings_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_cypress_config.mdx | 2 +- api_docs/kbn_data_service.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_deeplinks_analytics.mdx | 2 +- api_docs/kbn_deeplinks_devtools.mdx | 2 +- api_docs/kbn_deeplinks_management.mdx | 2 +- api_docs/kbn_deeplinks_ml.mdx | 2 +- api_docs/kbn_deeplinks_observability.mdx | 2 +- api_docs/kbn_deeplinks_search.mdx | 2 +- api_docs/kbn_default_nav_analytics.mdx | 2 +- api_docs/kbn_default_nav_devtools.mdx | 2 +- api_docs/kbn_default_nav_management.mdx | 2 +- api_docs/kbn_default_nav_ml.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_discover_utils.mdx | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_dom_drag_drop.mdx | 2 +- api_docs/kbn_ebt_tools.mdx | 2 +- api_docs/kbn_ecs.mdx | 2 +- api_docs/kbn_ecs_data_quality_dashboard.mdx | 2 +- api_docs/kbn_elastic_assistant.devdocs.json | 4 +- api_docs/kbn_elastic_assistant.mdx | 2 +- api_docs/kbn_es.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_es_types.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_event_annotation_common.mdx | 2 +- api_docs/kbn_event_annotation_components.mdx | 2 +- api_docs/kbn_expandable_flyout.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- .../kbn_ftr_common_functional_services.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_generate_console_definitions.mdx | 2 +- api_docs/kbn_generate_csv.mdx | 2 +- api_docs/kbn_generate_csv_types.mdx | 2 +- api_docs/kbn_guided_onboarding.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_health_gateway_server.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_i18n_react.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_infra_forge.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_journeys.mdx | 2 +- api_docs/kbn_json_ast.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- .../kbn_language_documentation_popover.mdx | 2 +- api_docs/kbn_lens_embeddable_utils.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_management_cards_navigation.mdx | 2 +- ...n_management_settings_section_registry.mdx | 2 +- api_docs/kbn_management_storybook_config.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_maps_vector_tile_utils.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_anomaly_utils.mdx | 2 +- api_docs/kbn_ml_category_validator.mdx | 2 +- .../kbn_ml_data_frame_analytics_utils.mdx | 2 +- api_docs/kbn_ml_data_grid.mdx | 2 +- api_docs/kbn_ml_date_picker.mdx | 2 +- api_docs/kbn_ml_date_utils.mdx | 2 +- api_docs/kbn_ml_error_utils.mdx | 2 +- api_docs/kbn_ml_in_memory_table.mdx | 2 +- api_docs/kbn_ml_is_defined.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_kibana_theme.mdx | 2 +- api_docs/kbn_ml_local_storage.mdx | 2 +- api_docs/kbn_ml_nested_property.mdx | 2 +- api_docs/kbn_ml_number_utils.mdx | 2 +- api_docs/kbn_ml_query_utils.mdx | 2 +- api_docs/kbn_ml_random_sampler_utils.mdx | 2 +- api_docs/kbn_ml_route_utils.mdx | 2 +- api_docs/kbn_ml_runtime_field_utils.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_ml_trained_models_utils.mdx | 2 +- api_docs/kbn_ml_url_state.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_object_versioning.mdx | 2 +- api_docs/kbn_observability_alert_details.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- api_docs/kbn_osquery_io_ts_types.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_random_sampling.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_react_kibana_context_common.mdx | 2 +- api_docs/kbn_react_kibana_context_render.mdx | 2 +- api_docs/kbn_react_kibana_context_root.mdx | 2 +- api_docs/kbn_react_kibana_context_styled.mdx | 2 +- api_docs/kbn_react_kibana_context_theme.mdx | 2 +- api_docs/kbn_react_kibana_mount.mdx | 2 +- api_docs/kbn_repo_file_maps.mdx | 2 +- api_docs/kbn_repo_linter.mdx | 2 +- api_docs/kbn_repo_path.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_reporting_common.mdx | 2 +- api_docs/kbn_rison.mdx | 2 +- api_docs/kbn_rrule.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- api_docs/kbn_saved_objects_settings.mdx | 2 +- api_docs/kbn_search_api_panels.devdocs.json | 4 +- api_docs/kbn_search_api_panels.mdx | 4 +- api_docs/kbn_search_response_warnings.mdx | 2 +- api_docs/kbn_security_solution_navigation.mdx | 2 +- api_docs/kbn_security_solution_side_nav.mdx | 2 +- ...kbn_security_solution_storybook_config.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_data_table.mdx | 2 +- api_docs/kbn_securitysolution_ecs.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- ...ritysolution_exception_list_components.mdx | 2 +- api_docs/kbn_securitysolution_grouping.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_serverless_project_switcher.mdx | 2 +- api_docs/kbn_serverless_storybook_config.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- api_docs/kbn_shared_ux_avatar_solution.mdx | 2 +- ...ared_ux_avatar_user_profile_components.mdx | 2 +- .../kbn_shared_ux_button_exit_full_screen.mdx | 2 +- ...hared_ux_button_exit_full_screen_mocks.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- .../kbn_shared_ux_card_no_data.devdocs.json | 182 +-------------- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- ..._shared_ux_card_no_data_mocks.devdocs.json | 4 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_chrome_navigation.mdx | 2 +- api_docs/kbn_shared_ux_file_context.mdx | 2 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_picker.mdx | 2 +- api_docs/kbn_shared_ux_file_types.mdx | 2 +- api_docs/kbn_shared_ux_file_upload.mdx | 2 +- api_docs/kbn_shared_ux_file_util.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_markdown.mdx | 2 +- api_docs/kbn_shared_ux_markdown_mocks.mdx | 2 +- ...red_ux_page_analytics_no_data.devdocs.json | 4 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- ...shared_ux_page_analytics_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- ...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_template.mdx | 2 +- ...n_shared_ux_page_kibana_template_mocks.mdx | 2 +- .../kbn_shared_ux_page_no_data.devdocs.json | 5 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- .../kbn_shared_ux_page_no_data_config.mdx | 2 +- ...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- ...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_prompt_not_found.mdx | 2 +- api_docs/kbn_shared_ux_router.mdx | 2 +- api_docs/kbn_shared_ux_router_mocks.mdx | 2 +- api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_slo_schema.devdocs.json | 20 -- api_docs/kbn_slo_schema.mdx | 4 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_test_subj_selector.mdx | 2 +- api_docs/kbn_text_based_editor.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_ts_projects.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_actions_browser.mdx | 2 +- api_docs/kbn_ui_shared_deps_src.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_unified_field_list.mdx | 2 +- api_docs/kbn_url_state.mdx | 2 +- api_docs/kbn_use_tracked_promise.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_visualization_ui_components.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/logs_shared.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/no_data_page.devdocs.json | 49 ++++ api_docs/no_data_page.mdx | 30 +++ api_docs/notifications.mdx | 2 +- api_docs/observability.devdocs.json | 152 +----------- api_docs/observability.mdx | 2 +- .../observability_a_i_assistant.devdocs.json | 140 +++++++++-- api_docs/observability_a_i_assistant.mdx | 2 +- api_docs/observability_onboarding.mdx | 2 +- api_docs/observability_shared.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/plugin_directory.mdx | 24 +- api_docs/presentation_util.mdx | 2 +- api_docs/profiling.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/security.mdx | 2 +- api_docs/security_solution.devdocs.json | 10 +- api_docs/security_solution.mdx | 2 +- api_docs/security_solution_ess.mdx | 2 +- api_docs/security_solution_serverless.mdx | 2 +- api_docs/serverless.mdx | 2 +- api_docs/serverless_observability.mdx | 2 +- api_docs/serverless_search.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/stack_connectors.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/text_based_languages.mdx | 2 +- api_docs/threat_intelligence.mdx | 2 +- api_docs/timelines.devdocs.json | 70 +++--- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_histogram.mdx | 2 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/uptime.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 591 files changed, 1470 insertions(+), 1193 deletions(-) create mode 100644 api_docs/elastic_assistant.devdocs.json create mode 100644 api_docs/elastic_assistant.mdx create mode 100644 api_docs/no_data_page.devdocs.json create mode 100644 api_docs/no_data_page.mdx diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index e57392132e528..e377ceae177bc 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 15f233cc9b6c3..a3c2ae0b512d6 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 8d05b3d90abda..a8df73deaa4e4 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 9a5b2ab1194ac..dc0e5a6b0c78d 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index 28779a9fc58a8..05aa88a397978 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -408,7 +408,7 @@ "label": "APIEndpoint", "description": [], "signature": [ - "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/title\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics_by_transaction_name\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/samples\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/error/{errorId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/top_erroneous_transactions\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/services/{serviceName}/metrics/nodes\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/charts\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/summary\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/functions_overview\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/active_instances\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/dependency\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search 2023-10-31\" | \"POST /api/apm/services/{serviceName}/annotation 2023-10-31\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/services/{serviceName}/alerts_count\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/service-group/counts\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"POST /internal/apm/traces/aggregated_critical_path\" | \"GET /internal/apm/traces/{traceId}/transactions/{transactionId}\" | \"GET /internal/apm/traces/{traceId}/spans/{spanId}\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/rule_types/transaction_error_rate/chart_preview\" | \"GET /internal/apm/rule_types/error_count/chart_preview\" | \"GET /internal/apm/rule_types/transaction_duration/chart_preview\" | \"GET /api/apm/settings/agent-configuration 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/view 2023-10-31\" | \"DELETE /api/apm/settings/agent-configuration 2023-10-31\" | \"PUT /api/apm/settings/agent-configuration 2023-10-31\" | \"POST /api/apm/settings/agent-configuration/search 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/environments 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/agent_name 2023-10-31\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps 2023-10-31\" | \"POST /api/apm/sourcemaps 2023-10-31\" | \"DELETE /api/apm/sourcemaps/{id} 2023-10-31\" | \"POST /api/apm/androidmaps 2023-10-31\" | \"POST /internal/apm/sourcemaps/migrate_fleet_artifacts\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema 2023-10-31\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/dependencies/top_dependencies\" | \"GET /internal/apm/dependencies/upstream_services\" | \"GET /internal/apm/dependencies/metadata\" | \"GET /internal/apm/dependencies/charts/latency\" | \"GET /internal/apm/dependencies/charts/throughput\" | \"GET /internal/apm/dependencies/charts/error_rate\" | \"GET /internal/apm/dependencies/operations\" | \"GET /internal/apm/dependencies/charts/distribution\" | \"GET /internal/apm/dependencies/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys 2023-10-31\" | \"GET /internal/apm/storage_explorer\" | \"GET /internal/apm/services/{serviceName}/storage_details\" | \"GET /internal/apm/storage_chart\" | \"GET /internal/apm/storage_explorer/privileges\" | \"GET /internal/apm/storage_explorer_summary_stats\" | \"GET /internal/apm/storage_explorer/is_cross_cluster_search\" | \"GET /internal/apm/storage_explorer/get_services\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\" | \"GET /internal/apm/settings/labs\" | \"GET /internal/apm/get_agents_per_service\" | \"GET /internal/apm/get_latest_agent_versions\" | \"GET /internal/apm/services/{serviceName}/agent_instances\" | \"GET /internal/apm/services/{serviceName}/mobile/filters\" | \"GET /internal/apm/mobile-services/{serviceName}/most_used_charts\" | \"GET /internal/apm/mobile-services/{serviceName}/transactions/charts/sessions\" | \"GET /internal/apm/mobile-services/{serviceName}/transactions/charts/http_requests\" | \"GET /internal/apm/mobile-services/{serviceName}/stats\" | \"GET /internal/apm/mobile-services/{serviceName}/location/stats\" | \"GET /internal/apm/mobile-services/{serviceName}/terms\" | \"GET /internal/apm/mobile-services/{serviceName}/main_statistics\" | \"GET /internal/apm/mobile-services/{serviceName}/detailed_statistics\" | \"GET /internal/apm/diagnostics\" | \"POST /internal/apm/assistant/get_apm_timeseries\" | \"GET /internal/apm/assistant/get_service_summary\" | \"GET /internal/apm/assistant/get_error_document\" | \"POST /internal/apm/assistant/get_correlation_values\" | \"GET /internal/apm/assistant/get_downstream_dependencies\"" + "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/title\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics_by_transaction_name\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/samples\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/error/{errorId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/top_erroneous_transactions\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/services/{serviceName}/metrics/nodes\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/charts\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/summary\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/functions_overview\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/active_instances\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/dependency\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search 2023-10-31\" | \"POST /api/apm/services/{serviceName}/annotation 2023-10-31\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/services/{serviceName}/alerts_count\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/service-group/counts\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"POST /internal/apm/traces/aggregated_critical_path\" | \"GET /internal/apm/traces/{traceId}/transactions/{transactionId}\" | \"GET /internal/apm/traces/{traceId}/spans/{spanId}\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/rule_types/transaction_error_rate/chart_preview\" | \"GET /internal/apm/rule_types/error_count/chart_preview\" | \"GET /internal/apm/rule_types/transaction_duration/chart_preview\" | \"GET /api/apm/settings/agent-configuration 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/view 2023-10-31\" | \"DELETE /api/apm/settings/agent-configuration 2023-10-31\" | \"PUT /api/apm/settings/agent-configuration 2023-10-31\" | \"POST /api/apm/settings/agent-configuration/search 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/environments 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/agent_name 2023-10-31\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps 2023-10-31\" | \"POST /api/apm/sourcemaps 2023-10-31\" | \"DELETE /api/apm/sourcemaps/{id} 2023-10-31\" | \"POST /api/apm/androidmaps 2023-10-31\" | \"POST /internal/apm/sourcemaps/migrate_fleet_artifacts\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema 2023-10-31\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/dependencies/top_dependencies\" | \"GET /internal/apm/dependencies/upstream_services\" | \"GET /internal/apm/dependencies/metadata\" | \"GET /internal/apm/dependencies/charts/latency\" | \"GET /internal/apm/dependencies/charts/throughput\" | \"GET /internal/apm/dependencies/charts/error_rate\" | \"GET /internal/apm/dependencies/operations\" | \"GET /internal/apm/dependencies/charts/distribution\" | \"GET /internal/apm/dependencies/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys 2023-10-31\" | \"GET /internal/apm/storage_explorer\" | \"GET /internal/apm/services/{serviceName}/storage_details\" | \"GET /internal/apm/storage_chart\" | \"GET /internal/apm/storage_explorer/privileges\" | \"GET /internal/apm/storage_explorer_summary_stats\" | \"GET /internal/apm/storage_explorer/is_cross_cluster_search\" | \"GET /internal/apm/storage_explorer/get_services\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\" | \"GET /internal/apm/settings/labs\" | \"GET /internal/apm/get_agents_per_service\" | \"GET /internal/apm/get_latest_agent_versions\" | \"GET /internal/apm/services/{serviceName}/agent_instances\" | \"GET /internal/apm/services/{serviceName}/mobile/filters\" | \"GET /internal/apm/mobile-services/{serviceName}/most_used_charts\" | \"GET /internal/apm/mobile-services/{serviceName}/transactions/charts/sessions\" | \"GET /internal/apm/mobile-services/{serviceName}/transactions/charts/http_requests\" | \"GET /internal/apm/mobile-services/{serviceName}/stats\" | \"GET /internal/apm/mobile-services/{serviceName}/location/stats\" | \"GET /internal/apm/mobile-services/{serviceName}/terms\" | \"GET /internal/apm/mobile-services/{serviceName}/main_statistics\" | \"GET /internal/apm/mobile-services/{serviceName}/detailed_statistics\" | \"GET /internal/apm/diagnostics\" | \"POST /internal/apm/assistant/get_apm_timeseries\" | \"GET /internal/apm/assistant/get_service_summary\" | \"GET /internal/apm/assistant/get_error_document\" | \"POST /internal/apm/assistant/get_correlation_values\" | \"GET /internal/apm/assistant/get_downstream_dependencies\" | \"GET /internal/apm/assistant/get_services_list\"" ], "path": "x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts", "deprecated": false, @@ -455,7 +455,51 @@ "label": "APMServerRouteRepository", "description": [], "signature": [ - "{ \"GET /internal/apm/assistant/get_downstream_dependencies\": { endpoint: \"GET /internal/apm/assistant/get_downstream_dependencies\"; params?: ", + "{ \"GET /internal/apm/assistant/get_services_list\": { endpoint: \"GET /internal/apm/assistant/get_services_list\"; params?: ", + "TypeC", + "<{ query: ", + "IntersectionC", + "<[", + "TypeC", + "<{ start: ", + "StringC", + "; end: ", + "StringC", + "; }>, ", + "PartialC", + "<{ 'service.environment': ", + "UnionC", + "<[", + "LiteralC", + "<\"ENVIRONMENT_NOT_DEFINED\">, ", + "LiteralC", + "<\"ENVIRONMENT_ALL\">, ", + "BrandC", + "<", + "StringC", + ", ", + { + "pluginId": "@kbn/io-ts-utils", + "scope": "common", + "docId": "kibKbnIoTsUtilsPluginApi", + "section": "def-common.NonEmptyStringBrand", + "text": "NonEmptyStringBrand" + }, + ">]>; }>]>; }> | undefined; handler: ({}: ", + "APMRouteHandlerResources", + " & { params: { query: { start: string; end: string; } & { 'service.environment'?: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", + "Branded", + "<string, ", + { + "pluginId": "@kbn/io-ts-utils", + "scope": "common", + "docId": "kibKbnIoTsUtilsPluginApi", + "section": "def-common.NonEmptyStringBrand", + "text": "NonEmptyStringBrand" + }, + "> | undefined; }; }; }) => Promise<{ content: ApmServicesListContent; }>; } & ", + "APMRouteCreateOptions", + "; \"GET /internal/apm/assistant/get_downstream_dependencies\": { endpoint: \"GET /internal/apm/assistant/get_downstream_dependencies\"; params?: ", "TypeC", "<{ query: ", "IntersectionC", @@ -807,7 +851,7 @@ "IngestGetPipelineResponse", " | undefined; }; diagnosticsPrivileges: { index: Record<string, ", "SecurityHasPrivilegesPrivileges", - ">; cluster: Record<string, boolean>; hasAllClusterPrivileges: boolean; hasAllIndexPrivileges: boolean; hasAllPrivileges: boolean; }; apmIndices: Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; }>; apmIndexTemplates: { name: string; isNonStandard: boolean; exists: boolean; }[]; fleetPackageInfo: { isInstalled: boolean; version?: string | undefined; }; kibanaVersion: string; elasticsearchVersion: string; apmEvents: ", + ">; cluster: Record<string, boolean>; hasAllClusterPrivileges: boolean; hasAllIndexPrivileges: boolean; hasAllPrivileges: boolean; }; apmIndices: Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; sourcemap: string; }>; apmIndexTemplates: { name: string; isNonStandard: boolean; exists: boolean; }[]; fleetPackageInfo: { isInstalled: boolean; version?: string | undefined; }; kibanaVersion: string; elasticsearchVersion: string; apmEvents: ", "ApmEvent", "[]; invalidIndices?: ", "IndiciesItem", @@ -3329,7 +3373,7 @@ "PartialC", "<SaveApmIndicesBodySchema>; }> | undefined; handler: ({}: ", "APMRouteHandlerResources", - " & { params: { body: { readonly error?: string | undefined; readonly metric?: string | undefined; readonly transaction?: string | undefined; readonly span?: string | undefined; readonly onboarding?: string | undefined; }; }; }) => Promise<", + " & { params: { body: { readonly error?: string | undefined; readonly metric?: string | undefined; readonly transaction?: string | undefined; readonly span?: string | undefined; readonly onboarding?: string | undefined; readonly sourcemap?: string | undefined; }; }; }) => Promise<", { "pluginId": "@kbn/core-saved-objects-common", "scope": "common", @@ -3341,7 +3385,7 @@ "APMRouteCreateOptions", "; \"GET /internal/apm/settings/apm-indices\": { endpoint: \"GET /internal/apm/settings/apm-indices\"; params?: undefined; handler: ({}: ", "APMRouteHandlerResources", - ") => Promise<Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; }>>; } & ", + ") => Promise<Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; sourcemap: string; }>>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/settings/apm-index-settings\": { endpoint: \"GET /internal/apm/settings/apm-index-settings\"; params?: undefined; handler: ({}: ", "APMRouteHandlerResources", diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 310fbc2e88b68..b2bff86331a71 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/apm_data_access.devdocs.json b/api_docs/apm_data_access.devdocs.json index aaab84fef1ef1..57fe58d681f92 100644 --- a/api_docs/apm_data_access.devdocs.json +++ b/api_docs/apm_data_access.devdocs.json @@ -22,7 +22,7 @@ "label": "APMDataAccessConfig", "description": [], "signature": [ - "{ readonly indices: Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; }>; }" + "{ readonly indices: Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; sourcemap: string; }>; }" ], "path": "x-pack/plugins/apm_data_access/server/index.ts", "deprecated": false, @@ -37,7 +37,7 @@ "label": "APMIndices", "description": [], "signature": [ - "{ readonly error: string; readonly metric: string; readonly transaction: string; readonly span: string; readonly onboarding: string; }" + "{ readonly error: string; readonly metric: string; readonly transaction: string; readonly span: string; readonly onboarding: string; readonly sourcemap: string; }" ], "path": "x-pack/plugins/apm_data_access/server/index.ts", "deprecated": false, @@ -65,7 +65,7 @@ "label": "apmIndicesFromConfigFile", "description": [], "signature": [ - "{ readonly error: string; readonly metric: string; readonly transaction: string; readonly span: string; readonly onboarding: string; }" + "{ readonly error: string; readonly metric: string; readonly transaction: string; readonly span: string; readonly onboarding: string; readonly sourcemap: string; }" ], "path": "x-pack/plugins/apm_data_access/server/types.ts", "deprecated": false, @@ -87,7 +87,7 @@ "section": "def-common.SavedObjectsClientContract", "text": "SavedObjectsClientContract" }, - ") => Promise<Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; }>>" + ") => Promise<Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; sourcemap: string; }>>" ], "path": "x-pack/plugins/apm_data_access/server/types.ts", "deprecated": false, diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx index 3aa0167513dc7..7f9d6eb4d6979 100644 --- a/api_docs/apm_data_access.mdx +++ b/api_docs/apm_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apmDataAccess title: "apmDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the apmDataAccess plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] --- import apmDataAccessObj from './apm_data_access.devdocs.json'; diff --git a/api_docs/asset_manager.mdx b/api_docs/asset_manager.mdx index bd66eb290ba60..b3aea5514a082 100644 --- a/api_docs/asset_manager.mdx +++ b/api_docs/asset_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetManager title: "assetManager" image: https://source.unsplash.com/400x175/?github description: API docs for the assetManager plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetManager'] --- import assetManagerObj from './asset_manager.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 1cd3d916be7e3..1e40fdd64b159 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index cd3621bef2e16..83a8cc40306b6 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index 9a2fab273e554..4f65b84fa40f2 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index a0c3e54b744d4..cfaf4b7b3056d 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 8b081708de4b1..613b1af2ac128 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index 01458d8a111a4..c65150369cd92 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_chat.mdx b/api_docs/cloud_chat.mdx index 1eab55e866256..89d22b4cadf85 100644 --- a/api_docs/cloud_chat.mdx +++ b/api_docs/cloud_chat.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChat title: "cloudChat" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChat plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChat'] --- import cloudChatObj from './cloud_chat.devdocs.json'; diff --git a/api_docs/cloud_chat_provider.mdx b/api_docs/cloud_chat_provider.mdx index 0ff6f8f1b8622..497715c6452dc 100644 --- a/api_docs/cloud_chat_provider.mdx +++ b/api_docs/cloud_chat_provider.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChatProvider title: "cloudChatProvider" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChatProvider plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChatProvider'] --- import cloudChatProviderObj from './cloud_chat_provider.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index c6549a2b2dfcc..0220ebe6fce30 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index 1b5a9f56b8ab7..5daa2dc23ed19 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index 49fb366ba59b3..73671acb55813 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index c54377c2c7b01..5f74e4dd1dccb 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index 6a5205f95b8ad..e03f7d1496f1a 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index d8a8087c9dd2a..a9b98bbe50122 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 9e00843c9cd9f..180b52069b3cd 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 110fd493b3f67..883d17498c404 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index ec3769adff5ef..bdd762edacbc5 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 457355f3f47be..7eae636681801 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.devdocs.json b/api_docs/data.devdocs.json index bee45b5ee444a..17cf390695f9e 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -13890,11 +13890,11 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" + "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" }, { "plugin": "transform", @@ -21655,11 +21655,11 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" + "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" }, { "plugin": "transform", diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 80a8e41aa1824..3173f22684c86 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 4af0c115d5164..4610c901d482c 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.devdocs.json b/api_docs/data_search.devdocs.json index 97b33f8d418ea..3b5cd7151721e 100644 --- a/api_docs/data_search.devdocs.json +++ b/api_docs/data_search.devdocs.json @@ -3154,7 +3154,7 @@ "section": "def-common.SavedObjectsFindOptionsReference", "text": "SavedObjectsFindOptionsReference" }, - "[] | undefined; hasNoReferenceOperator?: \"AND\" | \"OR\" | undefined; typeToNamespacesMap?: Map<string, string[] | undefined> | undefined; migrationVersionCompatibility?: \"raw\" | \"compatible\" | undefined; downwardConversion?: \"allow\" | \"forbid\" | undefined; }" + "[] | undefined; hasNoReferenceOperator?: \"AND\" | \"OR\" | undefined; typeToNamespacesMap?: Map<string, string[] | undefined> | undefined; migrationVersionCompatibility?: \"raw\" | \"compatible\" | undefined; }" ], "path": "src/plugins/data/server/search/session/types.ts", "deprecated": false, diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 22e1172947cfd..da269e2ad8258 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 1d42bd4d19fa6..0eadf9e93ada3 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 7d63985712cef..0f3fd5fc08760 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index 587767cffbd5b..15c25492cdafa 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.devdocs.json b/api_docs/data_views.devdocs.json index 3ac18c3d9e79a..4a845a6057727 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -649,11 +649,11 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" + "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" }, { "plugin": "transform", @@ -8613,11 +8613,11 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" + "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" }, { "plugin": "transform", @@ -15687,11 +15687,11 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" + "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" }, { "plugin": "transform", diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index adfb5e2df5f9b..96bf7eb84fd99 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 31a7a8d8a03d3..b67f64a5f94a1 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index e133bf0f0ce6d..e5c6f8f7f98bb 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index b8e4335461b42..d6a24b5788ad9 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index ee53150242ea9..4d9206678e728 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 27bb91fe6cf56..df3eec5b6c75f 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 0037157559554..9251bed21f4e0 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 524afafefe26b..f7f82769628b9 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index 25c602bcc81d9..f7dae10eb09b4 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.devdocs.json b/api_docs/elastic_assistant.devdocs.json new file mode 100644 index 0000000000000..9a3dd4987b4a5 --- /dev/null +++ b/api_docs/elastic_assistant.devdocs.json @@ -0,0 +1,101 @@ +{ + "id": "elasticAssistant", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [], + "setup": { + "parentPluginId": "elasticAssistant", + "id": "def-server.ElasticAssistantPluginSetup", + "type": "Interface", + "tags": [], + "label": "ElasticAssistantPluginSetup", + "description": [ + "The plugin setup interface" + ], + "path": "x-pack/plugins/elastic_assistant/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "elasticAssistant", + "id": "def-server.ElasticAssistantPluginSetup.actions", + "type": "Object", + "tags": [], + "label": "actions", + "description": [], + "signature": [ + { + "pluginId": "actions", + "scope": "server", + "docId": "kibActionsPluginApi", + "section": "def-server.PluginSetupContract", + "text": "PluginSetupContract" + } + ], + "path": "x-pack/plugins/elastic_assistant/server/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "lifecycle": "setup", + "initialIsOpen": true + }, + "start": { + "parentPluginId": "elasticAssistant", + "id": "def-server.ElasticAssistantPluginStart", + "type": "Interface", + "tags": [], + "label": "ElasticAssistantPluginStart", + "description": [ + "The plugin start interface" + ], + "path": "x-pack/plugins/elastic_assistant/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "elasticAssistant", + "id": "def-server.ElasticAssistantPluginStart.actions", + "type": "Object", + "tags": [], + "label": "actions", + "description": [], + "signature": [ + { + "pluginId": "actions", + "scope": "server", + "docId": "kibActionsPluginApi", + "section": "def-server.PluginStartContract", + "text": "PluginStartContract" + } + ], + "path": "x-pack/plugins/elastic_assistant/server/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "lifecycle": "start", + "initialIsOpen": true + } + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx new file mode 100644 index 0000000000000..b54c2cf5e5cac --- /dev/null +++ b/api_docs/elastic_assistant.mdx @@ -0,0 +1,33 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibElasticAssistantPluginApi +slug: /kibana-dev-docs/api/elasticAssistant +title: "elasticAssistant" +image: https://source.unsplash.com/400x175/?github +description: API docs for the elasticAssistant plugin +date: 2023-08-29 +tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] +--- +import elasticAssistantObj from './elastic_assistant.devdocs.json'; + +Server APIs for the Elastic AI Assistant + +Contact [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 4 | 0 | 2 | 0 | + +## Server + +### Setup +<DocDefinitionList data={[elasticAssistantObj.server.setup]}/> + +### Start +<DocDefinitionList data={[elasticAssistantObj.server.start]}/> + diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index c3265dcee0706..3833618281f9c 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 915053c2392bb..a35dd8b2a6f39 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 71b8222b35a9e..4f5b0901138fc 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index e5cb004fb95e4..666593267385b 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 34ad6afa48b70..a623814d2d906 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 194622fbc27a2..e48a46cfcb57a 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 0ddef098dd5b9..09c8d934dfea1 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/exploratory_view.mdx b/api_docs/exploratory_view.mdx index 20529d268a290..2fc551f75db51 100644 --- a/api_docs/exploratory_view.mdx +++ b/api_docs/exploratory_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/exploratoryView title: "exploratoryView" image: https://source.unsplash.com/400x175/?github description: API docs for the exploratoryView plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'exploratoryView'] --- import exploratoryViewObj from './exploratory_view.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index b5dc06cd852ce..ffadc334f7246 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 428938bb6e43b..099b5e151ad5b 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 7d82284b88156..50567fb3c9bd4 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index ab3f91ea6f27a..511647d6a7650 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index 4fe62e71f5ac1..5a8071726a871 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 09341a4b671a8..84d8834f2e1a9 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index 03f7b9f156c9d..bd596eef5f64b 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 5595380a5145f..012b3c8283002 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 9ab0c0b0ef36c..5e5fa0092ce64 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 99d0de37e515c..5a3567bbaa35b 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 719e8466bb47b..d75699a0bc67b 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index 4bf1d7c003789..3a2af466166ea 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index e0242a8e36c00..0b67bdbb64966 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 947074207702c..06f029f56890d 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 3c59782f81b39..4cfb788a38eaa 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index d700e1b5d69aa..a236ab0be0474 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index a61a9bd41640d..23c3684b63bef 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 5585cae642f0c..9c5b048df424c 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index 43b94e5b0c524..74a3b30e990d2 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index b895759be2757..d4770a5393235 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 583e61b08e22c..c8dc6be2ffc7a 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index 7e6223846ca2e..9cf887d5ed9c9 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 57c9d811644ef..2384ea3a83b81 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index 348456e53d1d6..3a4b6ea650395 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 1d371306c95b1..f35561697892e 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.devdocs.json b/api_docs/index_management.devdocs.json index 3da3a9bee799e..6d3b01d5245cf 100644 --- a/api_docs/index_management.devdocs.json +++ b/api_docs/index_management.devdocs.json @@ -201,6 +201,48 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "indexManagement", + "id": "def-public.Index.isRollupIndex", + "type": "CompoundType", + "tags": [], + "label": "isRollupIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-public.Index.ilm", + "type": "Object", + "tags": [], + "label": "ilm", + "description": [], + "signature": [ + "{ index: string; managed: boolean; } | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-public.Index.isFollowerIndex", + "type": "CompoundType", + "tags": [], + "label": "isFollowerIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "indexManagement", "id": "def-public.Index.health", @@ -529,6 +571,48 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "indexManagement", + "id": "def-server.Index.isRollupIndex", + "type": "CompoundType", + "tags": [], + "label": "isRollupIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-server.Index.ilm", + "type": "Object", + "tags": [], + "label": "ilm", + "description": [], + "signature": [ + "{ index: string; managed: boolean; } | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-server.Index.isFollowerIndex", + "type": "CompoundType", + "tags": [], + "label": "isFollowerIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "indexManagement", "id": "def-server.Index.health", @@ -1728,6 +1812,48 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "indexManagement", + "id": "def-common.Index.isRollupIndex", + "type": "CompoundType", + "tags": [], + "label": "isRollupIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-common.Index.ilm", + "type": "Object", + "tags": [], + "label": "ilm", + "description": [], + "signature": [ + "{ index: string; managed: boolean; } | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-common.Index.isFollowerIndex", + "type": "CompoundType", + "tags": [], + "label": "isFollowerIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "indexManagement", "id": "def-common.Index.health", diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 0656f447f754b..61ea64ac08109 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/platform-deployment-management](https://github.com/orgs/elasti | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 182 | 0 | 177 | 4 | +| 191 | 0 | 186 | 4 | ## Client diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 89c1ad1fe9a1a..e9596cddc338c 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index af92b068faab9..e0a6543f30b6f 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 08df446855ac1..72cc862872291 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 82c4099c75850..3c5907d8de45c 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 3275641350d15..53fecfd5a7ddd 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index ff79bf58afb09..c8974ddedaf08 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx index df262c8e51c64..d37c1916e8378 100644 --- a/api_docs/kbn_alerting_api_integration_helpers.mdx +++ b/api_docs/kbn_alerting_api_integration_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-api-integration-helpers title: "@kbn/alerting-api-integration-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-api-integration-helpers plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-api-integration-helpers'] --- import kbnAlertingApiIntegrationHelpersObj from './kbn_alerting_api_integration_helpers.devdocs.json'; diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index 925e234abb67c..364e1880c198f 100644 --- a/api_docs/kbn_alerting_state_types.mdx +++ b/api_docs/kbn_alerting_state_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-state-types title: "@kbn/alerting-state-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-state-types plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index dfe61d9785b2c..d631150c0a90f 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 21bdc8a1031cd..f6099e3a94a3a 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 76110b5e4764f..ecef44beb6612 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 1bddd8dd1dc50..fa2f5ee2548fd 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index 9277893dc5918..992023681a5b7 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index c67b4e148997d..d469e52483593 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 10b68beca9e5e..fe0c82020289a 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index 94b226a5da6f4..29577b4aa6140 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_gainsight.mdx b/api_docs/kbn_analytics_shippers_gainsight.mdx index c44d454379a9e..c495acdb88da5 100644 --- a/api_docs/kbn_analytics_shippers_gainsight.mdx +++ b/api_docs/kbn_analytics_shippers_gainsight.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-gainsight title: "@kbn/analytics-shippers-gainsight" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-gainsight plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-gainsight'] --- import kbnAnalyticsShippersGainsightObj from './kbn_analytics_shippers_gainsight.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 6bf641fba5afc..ddb75b94a1d03 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 97420bab75163..feaecf2c009a5 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index af44e635f73d8..0b1c54700b357 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 0318e42262b74..30662ff02b580 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index 1b6654ef2255c..c8d93573025a8 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 81344b3241e95..03fe88c6c2db0 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index 18628107149c5..a1c1fd44d27b8 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cell-actions'] --- import kbnCellActionsObj from './kbn_cell_actions.devdocs.json'; diff --git a/api_docs/kbn_chart_expressions_common.mdx b/api_docs/kbn_chart_expressions_common.mdx index 83452450ef094..717ee4f9d9bda 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-expressions-common'] --- import kbnChartExpressionsCommonObj from './kbn_chart_expressions_common.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index f664622736c9b..ec7b964886ed3 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index 4d9b4aeb058c3..1fa4cea3f980d 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index bfc6769604c0e..bf0a79fc42361 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index d0dcb11b93ed6..b831fb8a168bf 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 9008611a23d50..5cae7304d6845 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index c0791e49ce425..7b3670e6fde6c 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mocks.mdx b/api_docs/kbn_code_editor_mocks.mdx index f84fc43805710..883e7b41fdf2b 100644 --- a/api_docs/kbn_code_editor_mocks.mdx +++ b/api_docs/kbn_code_editor_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mocks title: "@kbn/code-editor-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mocks'] --- import kbnCodeEditorMocksObj from './kbn_code_editor_mocks.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index b67b695e134ac..e145f92192da3 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 5dcdd592f9b23..49ccc8f40a321 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index c9c53e99ab13d..857ac58bf99a5 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 69e3d3abb49a3..0a55f16979007 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index d03291aaec6a0..6656664fcefff 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_tabbed_table_list_view.mdx b/api_docs/kbn_content_management_tabbed_table_list_view.mdx index fe7b3d1f34b88..ec829c7248be6 100644 --- a/api_docs/kbn_content_management_tabbed_table_list_view.mdx +++ b/api_docs/kbn_content_management_tabbed_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-tabbed-table-list-view title: "@kbn/content-management-tabbed-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-tabbed-table-list-view plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-tabbed-table-list-view'] --- import kbnContentManagementTabbedTableListViewObj from './kbn_content_management_tabbed_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view.mdx b/api_docs/kbn_content_management_table_list_view.mdx index 75f585c7d1a9c..da0372ad77175 100644 --- a/api_docs/kbn_content_management_table_list_view.mdx +++ b/api_docs/kbn_content_management_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view title: "@kbn/content-management-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view'] --- import kbnContentManagementTableListViewObj from './kbn_content_management_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_table.mdx b/api_docs/kbn_content_management_table_list_view_table.mdx index 0e8dd462cf74f..f4f02e0699ed3 100644 --- a/api_docs/kbn_content_management_table_list_view_table.mdx +++ b/api_docs/kbn_content_management_table_list_view_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-table title: "@kbn/content-management-table-list-view-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-table plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-table'] --- import kbnContentManagementTableListViewTableObj from './kbn_content_management_table_list_view_table.devdocs.json'; diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index df3d2815d0275..60e161f3b7873 100644 --- a/api_docs/kbn_content_management_utils.mdx +++ b/api_docs/kbn_content_management_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-utils title: "@kbn/content-management-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-utils'] --- import kbnContentManagementUtilsObj from './kbn_content_management_utils.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index d05bb64cead09..0f19d1757debe 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 8d9d21e7a8059..65ae7d9d5c525 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index 6f42bb3cee9cf..fd06213dc58c4 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 5a532edd942ec..273d35d08fe5b 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index b7f1279e37fb4..50dfec92d8cc8 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index 305d8000439ba..2796d4b9348a5 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 3ff039e7893ce..5343660f95030 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 17ecf4be390b7..514788b96f802 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 8cde1e23fe26e..bb65de3706a63 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index 9ef4e2e08ac09..771ddee3d32b2 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index 66f382df62eb1..f41a779f11ecf 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index ddf50e2177573..877911f915135 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index d8245b2d4e513..02b9fba56b31b 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 61a7c4d3e8db4..f0146e929be94 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index 9a725c0f241a4..df575fdd3c903 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 1d4e79a8d64e1..92f94a60dd217 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index 0d3ae2a2735d1..86b23da543b7b 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index 161063403ce46..e8bfa3479d1dd 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index e8a1e09f1e2b3..51ae5d342d263 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index 3120bbc163d5d..2b977caea7b35 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index a79379b9a8f5a..ea7d5217cbabc 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 590c8a853c9ab..f450451982d27 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index bd49f3041871e..4c0e87652249f 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 36bdb034ca718..08372aed1a78e 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser.mdx b/api_docs/kbn_core_custom_branding_browser.mdx index 8f5315346eeca..58a201eecff11 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser'] --- import kbnCoreCustomBrandingBrowserObj from './kbn_core_custom_branding_browser.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_internal.mdx b/api_docs/kbn_core_custom_branding_browser_internal.mdx index d593b3b438138..fbbfd8d90c3b1 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-internal'] --- import kbnCoreCustomBrandingBrowserInternalObj from './kbn_core_custom_branding_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_mocks.mdx b/api_docs/kbn_core_custom_branding_browser_mocks.mdx index 3e840fcf7af07..563028256c470 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-mocks'] --- import kbnCoreCustomBrandingBrowserMocksObj from './kbn_core_custom_branding_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_common.mdx b/api_docs/kbn_core_custom_branding_common.mdx index 8065eceea0d5d..6f4bd9a5f598e 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-common'] --- import kbnCoreCustomBrandingCommonObj from './kbn_core_custom_branding_common.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server.mdx b/api_docs/kbn_core_custom_branding_server.mdx index 81e6809acd3d6..c8f70dd6eaf64 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server'] --- import kbnCoreCustomBrandingServerObj from './kbn_core_custom_branding_server.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_internal.mdx b/api_docs/kbn_core_custom_branding_server_internal.mdx index 45fe73cefea9e..058a0ff90fb30 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-internal'] --- import kbnCoreCustomBrandingServerInternalObj from './kbn_core_custom_branding_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_mocks.mdx b/api_docs/kbn_core_custom_branding_server_mocks.mdx index 1c62c7ba3bd7f..9dea0bbb5180e 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-mocks'] --- import kbnCoreCustomBrandingServerMocksObj from './kbn_core_custom_branding_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index d79d8a4bd01b0..8bef97501ba14 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 587c030c177e3..86c0fd24d3ef5 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index 66fa8529c1a15..6d63989ec8b28 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index ffbfaa9720b0f..c860d1ad9e33a 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index d794087e2740c..985ade7f9df50 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index eab385738a1ee..7a5b1cd2bc9fe 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index 44260725a5810..3d86a5c005edb 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 4668d955d2110..1bcbe10f847e2 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index 3660d233ad6ab..e6c84e04ff104 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index df6cf8d20c4ce..25a997e9680ed 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 73c334fed71b7..d69c2d624d041 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 67f8319478afa..6ec97363c7ac6 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index aa578123eaee7..7a35b078c5e1f 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.devdocs.json b/api_docs/kbn_core_elasticsearch_server.devdocs.json index 6ddcc2349c5b3..b926e48892b73 100644 --- a/api_docs/kbn_core_elasticsearch_server.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server.devdocs.json @@ -68,6 +68,35 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-elasticsearch-server", + "id": "def-common.ElasticsearchCapabilities", + "type": "Interface", + "tags": [], + "label": "ElasticsearchCapabilities", + "description": [ + "\nRepresent the capabilities supported by a given ES cluster.\n" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-elasticsearch-server", + "id": "def-common.ElasticsearchCapabilities.serverless", + "type": "boolean", + "tags": [], + "label": "serverless", + "description": [ + "\nIndicates whether we're connected to a serverless version of elasticsearch.\nRequired because some options aren't working for serverless and code needs to have the info to react accordingly." + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-elasticsearch-server", "id": "def-common.ElasticsearchClientConfig", @@ -856,6 +885,31 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-elasticsearch-server", + "id": "def-common.ElasticsearchServiceStart.getCapabilities", + "type": "Function", + "tags": [], + "label": "getCapabilities", + "description": [ + "\nReturns the capabilities for the default cluster." + ], + "signature": [ + "() => ", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchCapabilities", + "text": "ElasticsearchCapabilities" + } + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] } ], "initialIsOpen": false diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 1f415fde69839..995420e9c5e99 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 108 | 0 | 54 | 0 | +| 111 | 0 | 54 | 0 | ## Common diff --git a/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json index 02c0c4b3fb2a5..86657554ce3ed 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json @@ -1494,6 +1494,17 @@ "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-elasticsearch-server-internal", + "id": "def-common.ClusterInfo.cluster_build_flavor", + "type": "string", + "tags": [], + "label": "cluster_build_flavor", + "description": [], + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 6d3ba2a4b12d6..b498071c37156 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 37 | 0 | 33 | 3 | +| 38 | 0 | 34 | 3 | ## Common diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.devdocs.json b/api_docs/kbn_core_elasticsearch_server_mocks.devdocs.json index ce0361d169a13..45ce3bb04cd1e 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server_mocks.devdocs.json @@ -19,124 +19,7 @@ "common": { "classes": [], "functions": [], - "interfaces": [ - { - "parentPluginId": "@kbn/core-elasticsearch-server-mocks", - "id": "def-common.MockedElasticSearchServiceStart", - "type": "Interface", - "tags": [], - "label": "MockedElasticSearchServiceStart", - "description": [], - "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/core-elasticsearch-server-mocks", - "id": "def-common.MockedElasticSearchServiceStart.client", - "type": "Object", - "tags": [], - "label": "client", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-elasticsearch-client-server-mocks", - "scope": "common", - "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-common.ClusterClientMock", - "text": "ClusterClientMock" - } - ], - "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/core-elasticsearch-server-mocks", - "id": "def-common.MockedElasticSearchServiceStart.createClient", - "type": "Function", - "tags": [], - "label": "createClient", - "description": [], - "signature": [ - "jest.MockInstance<", - { - "pluginId": "@kbn/core-elasticsearch-client-server-mocks", - "scope": "common", - "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-common.CustomClusterClientMock", - "text": "CustomClusterClientMock" - }, - ", [type: string, config?: Partial<", - { - "pluginId": "@kbn/core-elasticsearch-server", - "scope": "common", - "docId": "kibKbnCoreElasticsearchServerPluginApi", - "section": "def-common.ElasticsearchClientConfig", - "text": "ElasticsearchClientConfig" - }, - "> | undefined], unknown> & ((type: string, config?: Partial<", - { - "pluginId": "@kbn/core-elasticsearch-server", - "scope": "common", - "docId": "kibKbnCoreElasticsearchServerPluginApi", - "section": "def-common.ElasticsearchClientConfig", - "text": "ElasticsearchClientConfig" - }, - "> | undefined) => ", - { - "pluginId": "@kbn/core-elasticsearch-client-server-mocks", - "scope": "common", - "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-common.CustomClusterClientMock", - "text": "CustomClusterClientMock" - }, - ")" - ], - "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/core-elasticsearch-server-mocks", - "id": "def-common.MockedElasticSearchServiceStart.createClient.$1", - "type": "string", - "tags": [], - "label": "type", - "description": [], - "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/core-elasticsearch-server-mocks", - "id": "def-common.MockedElasticSearchServiceStart.createClient.$2", - "type": "Object", - "tags": [], - "label": "config", - "description": [], - "signature": [ - "Partial<", - { - "pluginId": "@kbn/core-elasticsearch-server", - "scope": "common", - "docId": "kibKbnCoreElasticsearchServerPluginApi", - "section": "def-common.ElasticsearchClientConfig", - "text": "ElasticsearchClientConfig" - }, - "> | undefined" - ], - "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "initialIsOpen": false - } - ], + "interfaces": [], "enums": [], "misc": [ { @@ -173,6 +56,61 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-elasticsearch-server-mocks", + "id": "def-common.MockedElasticSearchServiceStart", + "type": "Type", + "tags": [], + "label": "MockedElasticSearchServiceStart", + "description": [], + "signature": [ + "{ getCapabilities: jest.MockInstance<", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchCapabilities", + "text": "ElasticsearchCapabilities" + }, + ", [], unknown>; } & Omit<", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchServiceStart", + "text": "ElasticsearchServiceStart" + }, + ", \"client\" | \"createClient\"> & { client: ", + { + "pluginId": "@kbn/core-elasticsearch-client-server-mocks", + "scope": "common", + "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", + "section": "def-common.ClusterClientMock", + "text": "ClusterClientMock" + }, + "; createClient: jest.MockedFunction<(type: string, config?: Partial<", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchClientConfig", + "text": "ElasticsearchClientConfig" + }, + "> | undefined) => ", + { + "pluginId": "@kbn/core-elasticsearch-client-server-mocks", + "scope": "common", + "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", + "section": "def-common.CustomClusterClientMock", + "text": "CustomClusterClientMock" + }, + ">; }" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ], "objects": [ @@ -320,6 +258,52 @@ "returnComment": [], "children": [] }, + { + "parentPluginId": "@kbn/core-elasticsearch-server-mocks", + "id": "def-common.elasticsearchServiceMock.createCapabilities", + "type": "Function", + "tags": [], + "label": "createCapabilities", + "description": [], + "signature": [ + "(parts?: Partial<", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchCapabilities", + "text": "ElasticsearchCapabilities" + }, + ">) => ", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchCapabilities", + "text": "ElasticsearchCapabilities" + } + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-elasticsearch-server-mocks", + "id": "def-common.elasticsearchServiceMock.createCapabilities.$1", + "type": "Object", + "tags": [], + "label": "parts", + "description": [], + "signature": [ + "{ serverless?: boolean | undefined; }" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, { "parentPluginId": "@kbn/core-elasticsearch-server-mocks", "id": "def-common.elasticsearchServiceMock.Unnamed", diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index d80a5ce1ecc32..66af48d6ebf65 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; @@ -21,16 +21,13 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 15 | 1 | 15 | 0 | +| 13 | 1 | 13 | 0 | ## Common ### Objects <DocDefinitionList data={kbnCoreElasticsearchServerMocksObj.common.objects}/> -### Interfaces -<DocDefinitionList data={kbnCoreElasticsearchServerMocksObj.common.interfaces}/> - ### Consts, variables and types <DocDefinitionList data={kbnCoreElasticsearchServerMocksObj.common.misc}/> diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 45b635efe6884..5f552f25a35b9 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index c682d53842de9..ea588dfe4b628 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 348c4db0922ce..a737d28921aa6 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index 10c7fe0413f46..c595b2bf4aee1 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 29ef2bee4f4c0..e73c5aea252be 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 74078fc2edd0e..536185db025bf 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index 57502724d1cd3..039183d8996a3 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 57a2e8c499247..297c976c40a97 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index 9620c8e1c53d1..b69d9803864b9 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index 2392291ace036..673a4b56a678d 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index 8df9c6550b3c4..67af69942d1d0 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 1eaefe6491d03..82b2d27bb43f7 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index 68e2d489d44f0..e9c22d6a04219 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index 6ba7f1277ea89..ddb19fe2acda8 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 486c5a4d71d90..6e50dfb1e04fc 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index 22ffc84c2abb9..b98cd8e966b79 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index 622b235833656..dac4ffde89734 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index b761cab2f7d22..863aff53a998f 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index d5616e660806b..259b12114cfdf 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index c956b4a83099a..0ee604bd7228d 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 968679c540997..9d0dd58feda1d 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index c95c5e725901d..4cd12d8e150cd 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.devdocs.json b/api_docs/kbn_core_http_server.devdocs.json index efe1548d0c612..c226ad218a529 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -5231,6 +5231,10 @@ "plugin": "ecsDataQualityDashboard", "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/__mocks__/server.ts" + }, { "plugin": "features", "path": "x-pack/plugins/features/server/routes/index.test.ts" @@ -6281,6 +6285,10 @@ "plugin": "encryptedSavedObjects", "path": "x-pack/plugins/encrypted_saved_objects/server/routes/key_rotation.ts" }, + { + "plugin": "serverless", + "path": "x-pack/plugins/serverless/server/plugin.ts" + }, { "plugin": "actions", "path": "x-pack/plugins/actions/server/routes/get_oauth_access_token.ts" @@ -6785,6 +6793,10 @@ "plugin": "ecsDataQualityDashboard", "path": "x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.ts" + }, { "plugin": "globalSearch", "path": "x-pack/plugins/global_search/server/routes/find.ts" @@ -7209,10 +7221,6 @@ "plugin": "searchprofiler", "path": "x-pack/plugins/searchprofiler/server/routes/profile.ts" }, - { - "plugin": "serverless", - "path": "x-pack/plugins/serverless/server/plugin.ts" - }, { "plugin": "snapshotRestore", "path": "x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts" @@ -7817,6 +7825,10 @@ "plugin": "ecsDataQualityDashboard", "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/__mocks__/server.ts" + }, { "plugin": "encryptedSavedObjects", "path": "x-pack/plugins/encrypted_saved_objects/server/routes/key_rotation.test.ts" @@ -8971,6 +8983,10 @@ "plugin": "ecsDataQualityDashboard", "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/__mocks__/server.ts" + }, { "plugin": "globalSearch", "path": "x-pack/plugins/global_search/server/routes/index.test.ts" @@ -9389,6 +9405,10 @@ "plugin": "ecsDataQualityDashboard", "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/__mocks__/server.ts" + }, { "plugin": "ruleRegistry", "path": "x-pack/plugins/rule_registry/server/routes/__mocks__/server.ts" @@ -9999,6 +10019,10 @@ "plugin": "ecsDataQualityDashboard", "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/__mocks__/server.ts" + }, { "plugin": "globalSearch", "path": "x-pack/plugins/global_search/server/routes/index.test.ts" diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 8a9fb45c13eea..79d3d870af63e 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index f346e16f4d91e..f7b2e4cfa3a12 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index b942627f971a3..ae1e34308bd69 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index 1f3504ac14602..cb8e8a6f86d1f 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 5c0adbfe02bd2..100ae9f06a288 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index 1654e0a959b96..167dbaa327158 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index 6d82603d0f92c..ce0a40721a1b1 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index c76b85d117b4f..173477df8cba2 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 2a28d7a9521fd..f5ebcf356933e 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index abe3799d80651..30bd8215d0f93 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index 32dac0764785c..eaf7505c170a0 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index 43df82357efb8..1076d85474f01 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index c22d33d42b5af..45d7b6cd01d36 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index ceec836e88c39..b6a4f8983cc0a 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index a7cdaf3ef18f1..52d3bc6e3141d 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 2d39bd149c2ea..20f895dc34886 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index db5ac2cd1e1cd..dcf3e6e39b6d2 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 2cb148512b9ab..46e71a104d3de 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 376c0e44f681a..60de046e3cc02 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index 070bcbbfc8103..b1f39308253e7 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 13b82b63de789..5e8b3e5a62314 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index 325d56ca40e7a..8a3de8307b1f5 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 3940e0eaa33d0..ed3f47b751106 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index 47b57b8420eca..b1fe1cff8e149 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index c9b55064cca94..612250f053548 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index 0e071dbd81352..60b3d9c3b391b 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index e1091e70c4a2f..8e5ea4c19615e 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 6455066411edd..b79735594ffb8 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 36c5177c6c5f3..4ebc8d71ba5a2 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index 1b943c4619822..2e1cd32fcb249 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index 920a9c6c23a75..37061c402bef7 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index 7c6742cb88562..84ae73ec14b4b 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index 777cecaee74bb..b59bbb842eca9 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index fa88a92022f08..62aec73fc0457 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index 3d478318cf7c4..2b6fa411a1b72 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index 5cdf10f520c37..35eadeade734d 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index 046b38fcf8686..d2c80db9d0da8 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index 4b7c20cd17749..72fa61e3eeab9 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index 2bd4ddc48f676..e97a77130be9d 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index affb98e39522c..b649bec5321c4 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index 3495668eb0191..677715f149a8a 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index bf96641a4a5e7..e8cc53127f6cc 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index b72268e069c1d..688f5fa567503 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index 2048ab81f46da..f1331870c7f73 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index 6f8c09617b104..311ff162c0d0b 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 677b5c3dbb7bc..eb583fc7b7d80 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.devdocs.json b/api_docs/kbn_core_saved_objects_api_server.devdocs.json index 528190aba475a..e529c9e80e178 100644 --- a/api_docs/kbn_core_saved_objects_api_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_server.devdocs.json @@ -861,8 +861,8 @@ "pluginId": "@kbn/core-saved-objects-api-server", "scope": "common", "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", - "section": "def-common.SavedObjectsGetOptions", - "text": "SavedObjectsGetOptions" + "section": "def-common.SavedObjectsResolveOptions", + "text": "SavedObjectsResolveOptions" }, " | undefined) => Promise<", { @@ -909,15 +909,15 @@ "tags": [], "label": "options", "description": [ - "{@link SavedObjectsGetOptions } - options for the bulk resolve operation" + "{@link SavedObjectsResolveOptions } - options for the bulk resolve operation" ], "signature": [ { "pluginId": "@kbn/core-saved-objects-api-server", "scope": "common", "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", - "section": "def-common.SavedObjectsGetOptions", - "text": "SavedObjectsGetOptions" + "section": "def-common.SavedObjectsResolveOptions", + "text": "SavedObjectsResolveOptions" }, " | undefined" ], @@ -1047,8 +1047,8 @@ "pluginId": "@kbn/core-saved-objects-api-server", "scope": "common", "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", - "section": "def-common.SavedObjectsGetOptions", - "text": "SavedObjectsGetOptions" + "section": "def-common.SavedObjectsResolveOptions", + "text": "SavedObjectsResolveOptions" }, " | undefined) => Promise<", { @@ -1105,15 +1105,15 @@ "tags": [], "label": "options", "description": [ - "{@link SavedObjectsGetOptions } - options for the resolve operation" + "{@link SavedObjectsResolveOptions } - options for the resolve operation" ], "signature": [ { "pluginId": "@kbn/core-saved-objects-api-server", "scope": "common", "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", - "section": "def-common.SavedObjectsGetOptions", - "text": "SavedObjectsGetOptions" + "section": "def-common.SavedObjectsResolveOptions", + "text": "SavedObjectsResolveOptions" }, " | undefined" ], @@ -4819,8 +4819,8 @@ "pluginId": "@kbn/core-saved-objects-api-server", "scope": "common", "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", - "section": "def-common.SavedObjectsGetOptions", - "text": "SavedObjectsGetOptions" + "section": "def-common.SavedObjectsResolveOptions", + "text": "SavedObjectsResolveOptions" }, " | undefined) => Promise<", { @@ -4867,15 +4867,15 @@ "tags": [], "label": "options", "description": [ - "{@link SavedObjectsGetOptions } - options for the bulk resolve operation" + "{@link SavedObjectsResolveOptions } - options for the bulk resolve operation" ], "signature": [ { "pluginId": "@kbn/core-saved-objects-api-server", "scope": "common", "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", - "section": "def-common.SavedObjectsGetOptions", - "text": "SavedObjectsGetOptions" + "section": "def-common.SavedObjectsResolveOptions", + "text": "SavedObjectsResolveOptions" }, " | undefined" ], @@ -4904,8 +4904,8 @@ "pluginId": "@kbn/core-saved-objects-api-server", "scope": "common", "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", - "section": "def-common.SavedObjectsGetOptions", - "text": "SavedObjectsGetOptions" + "section": "def-common.SavedObjectsResolveOptions", + "text": "SavedObjectsResolveOptions" }, " | undefined) => Promise<", { @@ -4962,15 +4962,15 @@ "tags": [], "label": "options", "description": [ - "{@link SavedObjectsGetOptions } - options for the resolve operation" + "{@link SavedObjectsResolveOptions } - options for the resolve operation" ], "signature": [ { "pluginId": "@kbn/core-saved-objects-api-server", "scope": "common", "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", - "section": "def-common.SavedObjectsGetOptions", - "text": "SavedObjectsGetOptions" + "section": "def-common.SavedObjectsResolveOptions", + "text": "SavedObjectsResolveOptions" }, " | undefined" ], @@ -6829,20 +6829,6 @@ "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/find.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "@kbn/core-saved-objects-api-server", - "id": "def-common.SavedObjectsFindOptions.downwardConversion", - "type": "CompoundType", - "tags": [], - "label": "downwardConversion", - "description": [], - "signature": [ - "\"allow\" | \"forbid\" | undefined" - ], - "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/find.ts", - "deprecated": false, - "trackAdoption": false } ], "initialIsOpen": false @@ -7118,20 +7104,6 @@ "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/get.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "@kbn/core-saved-objects-api-server", - "id": "def-common.SavedObjectsGetOptions.downwardConversion", - "type": "CompoundType", - "tags": [], - "label": "downwardConversion", - "description": [], - "signature": [ - "\"allow\" | \"forbid\" | undefined" - ], - "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/get.ts", - "deprecated": false, - "trackAdoption": false } ], "initialIsOpen": false @@ -7569,6 +7541,55 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-common.SavedObjectsResolveOptions", + "type": "Interface", + "tags": [], + "label": "SavedObjectsResolveOptions", + "description": [ + "\nOptions for the saved objects get operation\n" + ], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-common.SavedObjectsResolveOptions", + "text": "SavedObjectsResolveOptions" + }, + " extends ", + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-common.SavedObjectsBaseOptions", + "text": "SavedObjectsBaseOptions" + } + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/resolve.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-common.SavedObjectsResolveOptions.migrationVersionCompatibility", + "type": "CompoundType", + "tags": [], + "label": "migrationVersionCompatibility", + "description": [ + "{@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility}" + ], + "signature": [ + "\"raw\" | \"compatible\" | undefined" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/resolve.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-saved-objects-api-server", "id": "def-common.SavedObjectsResolveResponse", @@ -8230,7 +8251,7 @@ "section": "def-common.SavedObjectsFindOptionsReference", "text": "SavedObjectsFindOptionsReference" }, - "[] | undefined; hasNoReferenceOperator?: \"AND\" | \"OR\" | undefined; typeToNamespacesMap?: Map<string, string[] | undefined> | undefined; migrationVersionCompatibility?: \"raw\" | \"compatible\" | undefined; downwardConversion?: \"allow\" | \"forbid\" | undefined; }" + "[] | undefined; hasNoReferenceOperator?: \"AND\" | \"OR\" | undefined; typeToNamespacesMap?: Map<string, string[] | undefined> | undefined; migrationVersionCompatibility?: \"raw\" | \"compatible\" | undefined; }" ], "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/create_point_in_time_finder.ts", "deprecated": false, diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 076e898c16b5d..227d0db50d4b0 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 351 | 1 | 7 | 1 | +| 351 | 1 | 5 | 1 | ## Common diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 5f626e9595f2d..2e5d85dcd548c 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index d7ca06535508b..b183c5413a5a0 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index dc2cc0d340343..dcd89040b2edf 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 08ef3e09374fb..7863ce545e938 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 1c2697e463450..de37144affb42 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index 31d1ffa19b5ef..5c1d1bd8b2fb7 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index a4c541f9d73bb..b254e4c33dd60 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index fce07b5b6a3b5..f085a159d2dd3 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index bd8023a234f67..1ae599546797c 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json b/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json index cbd8b5774457d..4788fa89a6be4 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json @@ -330,7 +330,7 @@ "id": "def-common.KibanaMigrator.Unnamed.$1", "type": "Object", "tags": [], - "label": "{\n client,\n typeRegistry,\n kibanaIndex,\n defaultIndexTypesMap,\n soMigrationsConfig,\n kibanaVersion,\n logger,\n docLinks,\n waitForMigrationCompletion,\n nodeRoles,\n }", + "label": "{\n client,\n typeRegistry,\n kibanaIndex,\n defaultIndexTypesMap,\n soMigrationsConfig,\n kibanaVersion,\n logger,\n docLinks,\n waitForMigrationCompletion,\n nodeRoles,\n esCapabilities,\n }", "description": [], "signature": [ { @@ -831,7 +831,7 @@ "\nMakes a clone of the source index into the target.\n" ], "signature": [ - "({ client, source, target, timeout, }: ", + "({ client, esCapabilities, source, target, timeout, }: ", "CloneIndexParams", ") => ", "TaskEither", @@ -856,7 +856,7 @@ "id": "def-common.cloneIndex.$1", "type": "Object", "tags": [], - "label": "{\n client,\n source,\n target,\n timeout = DEFAULT_TIMEOUT,\n}", + "label": "{\n client,\n esCapabilities,\n source,\n target,\n timeout = DEFAULT_TIMEOUT,\n}", "description": [], "signature": [ "CloneIndexParams" @@ -1020,7 +1020,7 @@ "\nCreates an index with the given mappings\n" ], "signature": [ - "({ client, indexName, mappings, aliases, timeout, }: ", + "({ client, indexName, mappings, esCapabilities, aliases, timeout, }: ", "CreateIndexParams", ") => ", "TaskEither", @@ -1043,7 +1043,7 @@ "id": "def-common.createIndex.$1", "type": "Object", "tags": [], - "label": "{\n client,\n indexName,\n mappings,\n aliases = [],\n timeout = DEFAULT_TIMEOUT,\n}", + "label": "{\n client,\n indexName,\n mappings,\n esCapabilities,\n aliases = [],\n timeout = DEFAULT_TIMEOUT,\n}", "description": [], "signature": [ "CreateIndexParams" @@ -3648,6 +3648,26 @@ "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", + "id": "def-common.KibanaMigratorOptions.esCapabilities", + "type": "Object", + "tags": [], + "label": "esCapabilities", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchCapabilities", + "text": "ElasticsearchCapabilities" + } + ], + "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index 144ddb38bf147..6e2c6c18a2244 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 124 | 0 | 90 | 46 | +| 125 | 0 | 91 | 46 | ## Common diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index 5cdcb5c0b88af..b2596036f146f 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index 02433362bdf92..2a128edbd4123 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index 43b57dd232a11..961ee502dba74 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index f74e8a9ed0bce..1e8fde889c422 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 7eee2af89cf69..b9694e3000853 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index 8fb781db10df4..6f9dfeb432340 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index eb662bba8bf8c..0b254f28a4e39 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index 1e8bb7998f3cc..33b50a3171712 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index 995b05dae97e6..d1618d4918996 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index 83050864ff75e..758aa4c4bc691 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index 4f191c36b23bd..84c94392b87a5 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index b56bc7e9ee221..8ce8eb614334c 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_kbn_server.devdocs.json b/api_docs/kbn_core_test_helpers_kbn_server.devdocs.json index f410d08aa0a63..6631202ad7012 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.devdocs.json +++ b/api_docs/kbn_core_test_helpers_kbn_server.devdocs.json @@ -765,7 +765,17 @@ "label": "TestServerlessESUtils", "description": [], "signature": [ - "{ stop: () => Promise<void>; es: any; }" + "Pick<", + { + "pluginId": "@kbn/core-test-helpers-kbn-server", + "scope": "common", + "docId": "kibKbnCoreTestHelpersKbnServerPluginApi", + "section": "def-common.TestElasticsearchUtils", + "text": "TestElasticsearchUtils" + }, + ", \"stop\" | \"es\"> & { getClient: () => ", + "default", + "; }" ], "path": "packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts", "deprecated": false, diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index fe61d4057e77d..9b09ce92e443b 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index c7e9f12f428fc..7834a214aa798 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index a5a46d51ed6a7..55d2d369ac626 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index 568918e54edcc..9bbbf78c7f64f 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 103d710b3039e..9eea1301252db 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index bd23cb655cf19..8d3a5287f8438 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 5a90e562b0bc2..85f6df26b9788 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index c0274566c0578..03185781325d5 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 7e346176be3a2..d9212725166a6 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index 6a8b1d5c4d767..140be2bd66784 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 1f2281083110e..f77bcf74e7190 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index d2a78950e0d9c..83103ed73dddc 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index e33be649e1953..b1e5842cc38be 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 2b4d5d81c7706..68a5256f3d9ed 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index 49ab6ce0f6cce..6ac2cfa27b5ff 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server.mdx b/api_docs/kbn_core_user_settings_server.mdx index 004ade62a70e0..bcca65011f8e8 100644 --- a/api_docs/kbn_core_user_settings_server.mdx +++ b/api_docs/kbn_core_user_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server title: "@kbn/core-user-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server'] --- import kbnCoreUserSettingsServerObj from './kbn_core_user_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_internal.mdx b/api_docs/kbn_core_user_settings_server_internal.mdx index a471a3de444a0..1a82d2fdfcd13 100644 --- a/api_docs/kbn_core_user_settings_server_internal.mdx +++ b/api_docs/kbn_core_user_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-internal title: "@kbn/core-user-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-internal plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-internal'] --- import kbnCoreUserSettingsServerInternalObj from './kbn_core_user_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_mocks.mdx b/api_docs/kbn_core_user_settings_server_mocks.mdx index 0ff55f98614af..e0bab56d5c1db 100644 --- a/api_docs/kbn_core_user_settings_server_mocks.mdx +++ b/api_docs/kbn_core_user_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-mocks title: "@kbn/core-user-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-mocks'] --- import kbnCoreUserSettingsServerMocksObj from './kbn_core_user_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 3986e0b184454..efd2c9d43c394 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index 192a2eae62295..f030b08f89ade 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index 6573df31cae87..12a99cec6f65f 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_data_service.mdx b/api_docs/kbn_data_service.mdx index 4822b06f83a15..ee54819beba99 100644 --- a/api_docs/kbn_data_service.mdx +++ b/api_docs/kbn_data_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-service title: "@kbn/data-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-service plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-service'] --- import kbnDataServiceObj from './kbn_data_service.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 7c1da975e14b4..4efc8ace6cee1 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_analytics.mdx b/api_docs/kbn_deeplinks_analytics.mdx index a367ab49636d8..4f8ab53a1157d 100644 --- a/api_docs/kbn_deeplinks_analytics.mdx +++ b/api_docs/kbn_deeplinks_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-analytics title: "@kbn/deeplinks-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-analytics plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-analytics'] --- import kbnDeeplinksAnalyticsObj from './kbn_deeplinks_analytics.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_devtools.mdx b/api_docs/kbn_deeplinks_devtools.mdx index 0ef8243192606..a1eeb9eae6a23 100644 --- a/api_docs/kbn_deeplinks_devtools.mdx +++ b/api_docs/kbn_deeplinks_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-devtools title: "@kbn/deeplinks-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-devtools plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-devtools'] --- import kbnDeeplinksDevtoolsObj from './kbn_deeplinks_devtools.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_management.mdx b/api_docs/kbn_deeplinks_management.mdx index dd681b68b9de9..9518e124a176f 100644 --- a/api_docs/kbn_deeplinks_management.mdx +++ b/api_docs/kbn_deeplinks_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-management title: "@kbn/deeplinks-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-management plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-management'] --- import kbnDeeplinksManagementObj from './kbn_deeplinks_management.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_ml.mdx b/api_docs/kbn_deeplinks_ml.mdx index 6aabb6cefd86e..b7650c5c5dd4a 100644 --- a/api_docs/kbn_deeplinks_ml.mdx +++ b/api_docs/kbn_deeplinks_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-ml title: "@kbn/deeplinks-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-ml plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-ml'] --- import kbnDeeplinksMlObj from './kbn_deeplinks_ml.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_observability.mdx b/api_docs/kbn_deeplinks_observability.mdx index d6d9c2b073b13..dddc0b51d2f30 100644 --- a/api_docs/kbn_deeplinks_observability.mdx +++ b/api_docs/kbn_deeplinks_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-observability title: "@kbn/deeplinks-observability" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-observability plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-observability'] --- import kbnDeeplinksObservabilityObj from './kbn_deeplinks_observability.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_search.mdx b/api_docs/kbn_deeplinks_search.mdx index d26e01786fc5c..eeb4a33a08856 100644 --- a/api_docs/kbn_deeplinks_search.mdx +++ b/api_docs/kbn_deeplinks_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-search title: "@kbn/deeplinks-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-search plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index 45629619398b1..26dc3c42e6de3 100644 --- a/api_docs/kbn_default_nav_analytics.mdx +++ b/api_docs/kbn_default_nav_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-analytics title: "@kbn/default-nav-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-analytics plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-analytics'] --- import kbnDefaultNavAnalyticsObj from './kbn_default_nav_analytics.devdocs.json'; diff --git a/api_docs/kbn_default_nav_devtools.mdx b/api_docs/kbn_default_nav_devtools.mdx index 8ac8d0eba5c3a..2944b490bc4b8 100644 --- a/api_docs/kbn_default_nav_devtools.mdx +++ b/api_docs/kbn_default_nav_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-devtools title: "@kbn/default-nav-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-devtools plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-devtools'] --- import kbnDefaultNavDevtoolsObj from './kbn_default_nav_devtools.devdocs.json'; diff --git a/api_docs/kbn_default_nav_management.mdx b/api_docs/kbn_default_nav_management.mdx index c2a57883ee3a0..bfa83cfa31a60 100644 --- a/api_docs/kbn_default_nav_management.mdx +++ b/api_docs/kbn_default_nav_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-management title: "@kbn/default-nav-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-management plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-management'] --- import kbnDefaultNavManagementObj from './kbn_default_nav_management.devdocs.json'; diff --git a/api_docs/kbn_default_nav_ml.mdx b/api_docs/kbn_default_nav_ml.mdx index 416047cecf36f..b2cf182a214a2 100644 --- a/api_docs/kbn_default_nav_ml.mdx +++ b/api_docs/kbn_default_nav_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-ml title: "@kbn/default-nav-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-ml plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-ml'] --- import kbnDefaultNavMlObj from './kbn_default_nav_ml.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 7e6a348446ee5..959b1748c1f23 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index e4a85992d8e58..8b3c4efad36cd 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index 9309d75d11b2c..073bbfa04161e 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 33dda7786d02f..522d693aee8f3 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index f002c66fb7a5d..e273816a2cf47 100644 --- a/api_docs/kbn_discover_utils.mdx +++ b/api_docs/kbn_discover_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-utils title: "@kbn/discover-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 263cba94f29c2..c1eddc858e8b6 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index 1ac93e660a366..3f6406ba9e2ae 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_dom_drag_drop.mdx b/api_docs/kbn_dom_drag_drop.mdx index 0df5f87aaf743..6fdf4e030dd1b 100644 --- a/api_docs/kbn_dom_drag_drop.mdx +++ b/api_docs/kbn_dom_drag_drop.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dom-drag-drop title: "@kbn/dom-drag-drop" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dom-drag-drop plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dom-drag-drop'] --- import kbnDomDragDropObj from './kbn_dom_drag_drop.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 9b3ed90d31062..3c376439a4477 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs.mdx b/api_docs/kbn_ecs.mdx index 21ec97781b2b1..09a939e46aa45 100644 --- a/api_docs/kbn_ecs.mdx +++ b/api_docs/kbn_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs title: "@kbn/ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs'] --- import kbnEcsObj from './kbn_ecs.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index 2c6c0a5d1aab7..9cc7dfefd9678 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant.devdocs.json b/api_docs/kbn_elastic_assistant.devdocs.json index b6c7aa46db706..ba770f780e3fd 100644 --- a/api_docs/kbn_elastic_assistant.devdocs.json +++ b/api_docs/kbn_elastic_assistant.devdocs.json @@ -159,7 +159,7 @@ "label": "AssistantProvider", "description": [], "signature": [ - "({ actionTypeRegistry, assistantAvailability, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, baseAllowReplacement, defaultAllow, defaultAllowReplacement, docLinks, basePromptContexts, baseQuickPrompts, baseSystemPrompts, children, getComments, http, getInitialConversations, nameSpace, setConversations, setDefaultAllow, setDefaultAllowReplacement, title, }: React.PropsWithChildren<", + "({ actionTypeRegistry, assistantAvailability, assistantLangChain, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, baseAllowReplacement, defaultAllow, defaultAllowReplacement, docLinks, basePromptContexts, baseQuickPrompts, baseSystemPrompts, children, getComments, http, getInitialConversations, nameSpace, setConversations, setDefaultAllow, setDefaultAllowReplacement, title, }: React.PropsWithChildren<", "AssistantProviderProps", ">) => JSX.Element" ], @@ -172,7 +172,7 @@ "id": "def-public.AssistantProvider.$1", "type": "CompoundType", "tags": [], - "label": "{\n actionTypeRegistry,\n assistantAvailability,\n assistantTelemetry,\n augmentMessageCodeBlocks,\n baseAllow,\n baseAllowReplacement,\n defaultAllow,\n defaultAllowReplacement,\n docLinks,\n basePromptContexts = [],\n baseQuickPrompts = [],\n baseSystemPrompts = BASE_SYSTEM_PROMPTS,\n children,\n getComments,\n http,\n getInitialConversations,\n nameSpace = DEFAULT_ASSISTANT_NAMESPACE,\n setConversations,\n setDefaultAllow,\n setDefaultAllowReplacement,\n title = DEFAULT_ASSISTANT_TITLE,\n}", + "label": "{\n actionTypeRegistry,\n assistantAvailability,\n assistantLangChain,\n assistantTelemetry,\n augmentMessageCodeBlocks,\n baseAllow,\n baseAllowReplacement,\n defaultAllow,\n defaultAllowReplacement,\n docLinks,\n basePromptContexts = [],\n baseQuickPrompts = [],\n baseSystemPrompts = BASE_SYSTEM_PROMPTS,\n children,\n getComments,\n http,\n getInitialConversations,\n nameSpace = DEFAULT_ASSISTANT_NAMESPACE,\n setConversations,\n setDefaultAllow,\n setDefaultAllowReplacement,\n title = DEFAULT_ASSISTANT_TITLE,\n}", "description": [], "signature": [ "React.PropsWithChildren<", diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index ee2586acf4dfe..700fc56c4a12e 100644 --- a/api_docs/kbn_elastic_assistant.mdx +++ b/api_docs/kbn_elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant title: "@kbn/elastic-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index fe4745e9f9d8e..30955056b2f47 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 507b438e96ad9..6be6d9223e19f 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index a57fcae63f6c4..b46623ecdca94 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index e021414ada3cf..9eeb9eb239d6f 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index 3de1ad088b0a8..c02c0e1b6eb54 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 17245394d55c5..6632351eb3699 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index ba4a96a999de7..8b6adb20854b8 100644 --- a/api_docs/kbn_event_annotation_common.mdx +++ b/api_docs/kbn_event_annotation_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-common title: "@kbn/event-annotation-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-common'] --- import kbnEventAnnotationCommonObj from './kbn_event_annotation_common.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_components.mdx b/api_docs/kbn_event_annotation_components.mdx index 9c3cbb50d3609..acf47db88e44a 100644 --- a/api_docs/kbn_event_annotation_components.mdx +++ b/api_docs/kbn_event_annotation_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-components title: "@kbn/event-annotation-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-components plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index 7ce3c1812c692..f6d5e017e5ece 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] --- import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 38c5d06324e16..f3c5be9d72749 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 8f4bc0685a40f..9b304e48ad970 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index b553a82db6376..6366a800e19ce 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index e0c1caf46cdd6..d9df69c0e3591 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_generate_console_definitions.mdx b/api_docs/kbn_generate_console_definitions.mdx index b569181134c02..4a9a08964a21b 100644 --- a/api_docs/kbn_generate_console_definitions.mdx +++ b/api_docs/kbn_generate_console_definitions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-console-definitions title: "@kbn/generate-console-definitions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-console-definitions plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-console-definitions'] --- import kbnGenerateConsoleDefinitionsObj from './kbn_generate_console_definitions.devdocs.json'; diff --git a/api_docs/kbn_generate_csv.mdx b/api_docs/kbn_generate_csv.mdx index e943f85bc60a7..edb0ef008da43 100644 --- a/api_docs/kbn_generate_csv.mdx +++ b/api_docs/kbn_generate_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv title: "@kbn/generate-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_generate_csv_types.mdx b/api_docs/kbn_generate_csv_types.mdx index d631d48ef8c10..1477071967337 100644 --- a/api_docs/kbn_generate_csv_types.mdx +++ b/api_docs/kbn_generate_csv_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv-types title: "@kbn/generate-csv-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv-types plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv-types'] --- import kbnGenerateCsvTypesObj from './kbn_generate_csv_types.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 745ac02bb4652..8ac44ad4ac395 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index ca5da2e9ab6c6..b5c9b0a4c7905 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index cff27e0e07eca..8c5ee973427fa 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index 322e7222fc25a..2d5301b748a32 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 77b545e3c2a94..0d2035b575cf9 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index a8ef4c315ee91..aa44a7339f2e1 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index f1c2c07026250..37af28638ba5f 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index 4de3e62ab8222..1c4e9645f6cb8 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 4a2fb1374ce93..d7d4ec86c975e 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_infra_forge.mdx b/api_docs/kbn_infra_forge.mdx index c9c3a03be7dd8..141e3bd5f5893 100644 --- a/api_docs/kbn_infra_forge.mdx +++ b/api_docs/kbn_infra_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-infra-forge title: "@kbn/infra-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/infra-forge plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/infra-forge'] --- import kbnInfraForgeObj from './kbn_infra_forge.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 6eb1de41649fb..fc2149869e4ad 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 5eacd3894b8a9..2ef5fad37ec2f 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index b655478312cee..17eb9593f193a 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index 304eedf004302..298d1c91f18ca 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_json_ast.mdx b/api_docs/kbn_json_ast.mdx index bbd52d0396413..f3f26735d6d43 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index 26fa24d84da0e..50dc441905e96 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index cc28ae74312fe..de335a8f1d70d 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_lens_embeddable_utils.mdx b/api_docs/kbn_lens_embeddable_utils.mdx index 491b75fe5c513..c3d3f1dfab9f6 100644 --- a/api_docs/kbn_lens_embeddable_utils.mdx +++ b/api_docs/kbn_lens_embeddable_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-embeddable-utils title: "@kbn/lens-embeddable-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-embeddable-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-embeddable-utils'] --- import kbnLensEmbeddableUtilsObj from './kbn_lens_embeddable_utils.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 43d53e563567f..e10f9f15513ad 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index 824fcf105da85..9659851be9414 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index c3f0b20b0982f..18ed8a93add58 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_management_cards_navigation.mdx b/api_docs/kbn_management_cards_navigation.mdx index 574195bbcf6ba..d4c7f326d8abd 100644 --- a/api_docs/kbn_management_cards_navigation.mdx +++ b/api_docs/kbn_management_cards_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-cards-navigation title: "@kbn/management-cards-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-cards-navigation plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-cards-navigation'] --- import kbnManagementCardsNavigationObj from './kbn_management_cards_navigation.devdocs.json'; diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index 3765faadee51d..072feb8e3d7fc 100644 --- a/api_docs/kbn_management_settings_section_registry.mdx +++ b/api_docs/kbn_management_settings_section_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-section-registry title: "@kbn/management-settings-section-registry" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-section-registry plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-section-registry'] --- import kbnManagementSettingsSectionRegistryObj from './kbn_management_settings_section_registry.devdocs.json'; diff --git a/api_docs/kbn_management_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index 58a3936fcc4a6..df5b2b135f70f 100644 --- a/api_docs/kbn_management_storybook_config.mdx +++ b/api_docs/kbn_management_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-storybook-config title: "@kbn/management-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-storybook-config plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 915b3bd624819..c27e4ee9909f3 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_maps_vector_tile_utils.mdx b/api_docs/kbn_maps_vector_tile_utils.mdx index 9173d46071a59..752deb601de6b 100644 --- a/api_docs/kbn_maps_vector_tile_utils.mdx +++ b/api_docs/kbn_maps_vector_tile_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-maps-vector-tile-utils title: "@kbn/maps-vector-tile-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/maps-vector-tile-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/maps-vector-tile-utils'] --- import kbnMapsVectorTileUtilsObj from './kbn_maps_vector_tile_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 37cd08fc67a22..c72e0421d1744 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_anomaly_utils.mdx b/api_docs/kbn_ml_anomaly_utils.mdx index 5e9e578ae8dd5..0310d80f4f4ee 100644 --- a/api_docs/kbn_ml_anomaly_utils.mdx +++ b/api_docs/kbn_ml_anomaly_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-anomaly-utils title: "@kbn/ml-anomaly-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-anomaly-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-anomaly-utils'] --- import kbnMlAnomalyUtilsObj from './kbn_ml_anomaly_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_category_validator.mdx b/api_docs/kbn_ml_category_validator.mdx index aec6235823d5c..12cea1e4fc52d 100644 --- a/api_docs/kbn_ml_category_validator.mdx +++ b/api_docs/kbn_ml_category_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-category-validator title: "@kbn/ml-category-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-category-validator plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-category-validator'] --- import kbnMlCategoryValidatorObj from './kbn_ml_category_validator.devdocs.json'; diff --git a/api_docs/kbn_ml_data_frame_analytics_utils.mdx b/api_docs/kbn_ml_data_frame_analytics_utils.mdx index bf951e4a23cfa..e08dcf67b5b77 100644 --- a/api_docs/kbn_ml_data_frame_analytics_utils.mdx +++ b/api_docs/kbn_ml_data_frame_analytics_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-frame-analytics-utils title: "@kbn/ml-data-frame-analytics-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-frame-analytics-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-frame-analytics-utils'] --- import kbnMlDataFrameAnalyticsUtilsObj from './kbn_ml_data_frame_analytics_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_data_grid.mdx b/api_docs/kbn_ml_data_grid.mdx index a7b292c5e0d19..7e7eb6c824698 100644 --- a/api_docs/kbn_ml_data_grid.mdx +++ b/api_docs/kbn_ml_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-grid title: "@kbn/ml-data-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-grid plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-grid'] --- import kbnMlDataGridObj from './kbn_ml_data_grid.devdocs.json'; diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 7fb13246ad50d..22be4828a09b4 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_date_utils.mdx b/api_docs/kbn_ml_date_utils.mdx index 54afbaf8bb4c6..2cddfbacbe995 100644 --- a/api_docs/kbn_ml_date_utils.mdx +++ b/api_docs/kbn_ml_date_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-utils title: "@kbn/ml-date-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-utils'] --- import kbnMlDateUtilsObj from './kbn_ml_date_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_error_utils.mdx b/api_docs/kbn_ml_error_utils.mdx index 3abc33688e974..115d7f3f5aebb 100644 --- a/api_docs/kbn_ml_error_utils.mdx +++ b/api_docs/kbn_ml_error_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-error-utils title: "@kbn/ml-error-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-error-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-error-utils'] --- import kbnMlErrorUtilsObj from './kbn_ml_error_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_in_memory_table.mdx b/api_docs/kbn_ml_in_memory_table.mdx index 43c8dccc8f09b..bce3c119c7300 100644 --- a/api_docs/kbn_ml_in_memory_table.mdx +++ b/api_docs/kbn_ml_in_memory_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-in-memory-table title: "@kbn/ml-in-memory-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-in-memory-table plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-in-memory-table'] --- import kbnMlInMemoryTableObj from './kbn_ml_in_memory_table.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index fdf47821ef58a..10e9a37cf2a1d 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] --- import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 90c913bf11ddb..c84cd32d693e5 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_kibana_theme.mdx b/api_docs/kbn_ml_kibana_theme.mdx index fb3edc3daf05b..b6632ced1864f 100644 --- a/api_docs/kbn_ml_kibana_theme.mdx +++ b/api_docs/kbn_ml_kibana_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-kibana-theme title: "@kbn/ml-kibana-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-kibana-theme plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-kibana-theme'] --- import kbnMlKibanaThemeObj from './kbn_ml_kibana_theme.devdocs.json'; diff --git a/api_docs/kbn_ml_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index cfc725540ece3..d2aa2d2e11369 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] --- import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index b5f9d79cf2049..865cb28ba68d7 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_number_utils.mdx b/api_docs/kbn_ml_number_utils.mdx index e36cc3817f56a..0c7c2d69773df 100644 --- a/api_docs/kbn_ml_number_utils.mdx +++ b/api_docs/kbn_ml_number_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-number-utils title: "@kbn/ml-number-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-number-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-number-utils'] --- import kbnMlNumberUtilsObj from './kbn_ml_number_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 2aabe72429f12..c8b5a1f564921 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-query-utils'] --- import kbnMlQueryUtilsObj from './kbn_ml_query_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_random_sampler_utils.mdx b/api_docs/kbn_ml_random_sampler_utils.mdx index c98fd1e08923f..d88fa51624c10 100644 --- a/api_docs/kbn_ml_random_sampler_utils.mdx +++ b/api_docs/kbn_ml_random_sampler_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-random-sampler-utils title: "@kbn/ml-random-sampler-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-random-sampler-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-random-sampler-utils'] --- import kbnMlRandomSamplerUtilsObj from './kbn_ml_random_sampler_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_route_utils.mdx b/api_docs/kbn_ml_route_utils.mdx index bf752bf195060..334b5d977b445 100644 --- a/api_docs/kbn_ml_route_utils.mdx +++ b/api_docs/kbn_ml_route_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-route-utils title: "@kbn/ml-route-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-route-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-route-utils'] --- import kbnMlRouteUtilsObj from './kbn_ml_route_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_runtime_field_utils.mdx b/api_docs/kbn_ml_runtime_field_utils.mdx index f5ee0d61ba730..56bb547e1b02d 100644 --- a/api_docs/kbn_ml_runtime_field_utils.mdx +++ b/api_docs/kbn_ml_runtime_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-runtime-field-utils title: "@kbn/ml-runtime-field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-runtime-field-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-runtime-field-utils'] --- import kbnMlRuntimeFieldUtilsObj from './kbn_ml_runtime_field_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index a1aa76891a753..7f7db30ddc077 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index 0b464612f81a1..fa07e095326b3 100644 --- a/api_docs/kbn_ml_trained_models_utils.mdx +++ b/api_docs/kbn_ml_trained_models_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-trained-models-utils title: "@kbn/ml-trained-models-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-trained-models-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 0ecd9bb6ea36f..a829a05d9e99f 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index d1d7e3632b39c..f2561211fbddb 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index b26b50f40ed01..cee70296ebec6 100644 --- a/api_docs/kbn_object_versioning.mdx +++ b/api_docs/kbn_object_versioning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning title: "@kbn/object-versioning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning'] --- import kbnObjectVersioningObj from './kbn_object_versioning.devdocs.json'; diff --git a/api_docs/kbn_observability_alert_details.mdx b/api_docs/kbn_observability_alert_details.mdx index a750f3434012f..8276e0f455d6d 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alert-details title: "@kbn/observability-alert-details" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alert-details plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 3a15e1a51fd61..5a55501f9467a 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index b01b8c1f65cb1..354fbcba634ad 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index 5a32ff29ce1f5..b163df01ae225 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index f983a944135a5..a11c97784e509 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index fcb8f3f01c4f6..a94e7eb5102da 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 1faca1531ed9c..3a1b036ca3013 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index 3b37e1e56935f..a8949b64310b9 100644 --- a/api_docs/kbn_random_sampling.mdx +++ b/api_docs/kbn_random_sampling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-random-sampling title: "@kbn/random-sampling" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/random-sampling plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/random-sampling'] --- import kbnRandomSamplingObj from './kbn_random_sampling.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 04d218646a71d..7c712164fd8cb 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_common.mdx b/api_docs/kbn_react_kibana_context_common.mdx index 6dbcb3c0ff5c8..2f2893afffa81 100644 --- a/api_docs/kbn_react_kibana_context_common.mdx +++ b/api_docs/kbn_react_kibana_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-common title: "@kbn/react-kibana-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-common'] --- import kbnReactKibanaContextCommonObj from './kbn_react_kibana_context_common.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_render.mdx b/api_docs/kbn_react_kibana_context_render.mdx index 0807075b7caf7..3871fd28dfb72 100644 --- a/api_docs/kbn_react_kibana_context_render.mdx +++ b/api_docs/kbn_react_kibana_context_render.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-render title: "@kbn/react-kibana-context-render" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-render plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-render'] --- import kbnReactKibanaContextRenderObj from './kbn_react_kibana_context_render.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_root.mdx b/api_docs/kbn_react_kibana_context_root.mdx index 6bf44b4f5cb95..a0e9eafcf0b21 100644 --- a/api_docs/kbn_react_kibana_context_root.mdx +++ b/api_docs/kbn_react_kibana_context_root.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-root title: "@kbn/react-kibana-context-root" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-root plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-root'] --- import kbnReactKibanaContextRootObj from './kbn_react_kibana_context_root.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_styled.mdx b/api_docs/kbn_react_kibana_context_styled.mdx index cdaac4b551dee..cca223f50e6a0 100644 --- a/api_docs/kbn_react_kibana_context_styled.mdx +++ b/api_docs/kbn_react_kibana_context_styled.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-styled title: "@kbn/react-kibana-context-styled" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-styled plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-styled'] --- import kbnReactKibanaContextStyledObj from './kbn_react_kibana_context_styled.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_theme.mdx b/api_docs/kbn_react_kibana_context_theme.mdx index 202095f9413f5..e3281ee6b5352 100644 --- a/api_docs/kbn_react_kibana_context_theme.mdx +++ b/api_docs/kbn_react_kibana_context_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-theme title: "@kbn/react-kibana-context-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-theme plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-theme'] --- import kbnReactKibanaContextThemeObj from './kbn_react_kibana_context_theme.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_mount.mdx b/api_docs/kbn_react_kibana_mount.mdx index c2e3b7228c3aa..299d5f22b976d 100644 --- a/api_docs/kbn_react_kibana_mount.mdx +++ b/api_docs/kbn_react_kibana_mount.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-mount title: "@kbn/react-kibana-mount" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-mount plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-mount'] --- import kbnReactKibanaMountObj from './kbn_react_kibana_mount.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index 0cf797ebc817b..ce8158a8183c7 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-file-maps'] --- import kbnRepoFileMapsObj from './kbn_repo_file_maps.devdocs.json'; diff --git a/api_docs/kbn_repo_linter.mdx b/api_docs/kbn_repo_linter.mdx index 8795a2ff87d2b..87efc1001f627 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-linter'] --- import kbnRepoLinterObj from './kbn_repo_linter.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index ba63caf870dc3..ca4a6449f390c 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index c24c5aceb94d6..2e8a262dd0d34 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index 980fd1a39d79a..9d66b484597d9 100644 --- a/api_docs/kbn_reporting_common.mdx +++ b/api_docs/kbn_reporting_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-common title: "@kbn/reporting-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-common plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index 9a1902668d8d8..5c01b7a0b78c6 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index f2fefc4c97da3..cbc74d84905af 100644 --- a/api_docs/kbn_rrule.mdx +++ b/api_docs/kbn_rrule.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rrule title: "@kbn/rrule" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rrule plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 50cffdb0363ce..d5938991671d2 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_saved_objects_settings.mdx b/api_docs/kbn_saved_objects_settings.mdx index e871523c539c7..f82e8f71c8431 100644 --- a/api_docs/kbn_saved_objects_settings.mdx +++ b/api_docs/kbn_saved_objects_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-objects-settings title: "@kbn/saved-objects-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-objects-settings plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.devdocs.json b/api_docs/kbn_search_api_panels.devdocs.json index d477957673f4f..10d786f99db67 100644 --- a/api_docs/kbn_search_api_panels.devdocs.json +++ b/api_docs/kbn_search_api_panels.devdocs.json @@ -583,12 +583,12 @@ { "parentPluginId": "@kbn/search-api-panels", "id": "def-common.IntegrationsPanelProps.docLinks", - "type": "Any", + "type": "Object", "tags": [], "label": "docLinks", "description": [], "signature": [ - "any" + "{ beats: string; connectors: string; logStash: string; }" ], "path": "packages/kbn-search-api-panels/components/integrations_panel.tsx", "deprecated": false, diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index a9d0d9883300f..51ae6d16ef47f 100644 --- a/api_docs/kbn_search_api_panels.mdx +++ b/api_docs/kbn_search_api_panels.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-panels title: "@kbn/search-api-panels" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-panels plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/te | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 64 | 1 | 64 | 0 | +| 64 | 0 | 64 | 0 | ## Common diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index 8dc0aec607d68..d658e52122353 100644 --- a/api_docs/kbn_search_response_warnings.mdx +++ b/api_docs/kbn_search_response_warnings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-response-warnings title: "@kbn/search-response-warnings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-response-warnings plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-response-warnings'] --- import kbnSearchResponseWarningsObj from './kbn_search_response_warnings.devdocs.json'; diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index 3a92db9b0f639..c487ad465c6d7 100644 --- a/api_docs/kbn_security_solution_navigation.mdx +++ b/api_docs/kbn_security_solution_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-navigation title: "@kbn/security-solution-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-navigation plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-navigation'] --- import kbnSecuritySolutionNavigationObj from './kbn_security_solution_navigation.devdocs.json'; diff --git a/api_docs/kbn_security_solution_side_nav.mdx b/api_docs/kbn_security_solution_side_nav.mdx index 95a0b834d2639..2afb39253c2c8 100644 --- a/api_docs/kbn_security_solution_side_nav.mdx +++ b/api_docs/kbn_security_solution_side_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-side-nav title: "@kbn/security-solution-side-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-side-nav plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-side-nav'] --- import kbnSecuritySolutionSideNavObj from './kbn_security_solution_side_nav.devdocs.json'; diff --git a/api_docs/kbn_security_solution_storybook_config.mdx b/api_docs/kbn_security_solution_storybook_config.mdx index 77c3f6a7c1f55..f4d968a9b8ae7 100644 --- a/api_docs/kbn_security_solution_storybook_config.mdx +++ b/api_docs/kbn_security_solution_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-storybook-config title: "@kbn/security-solution-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-storybook-config plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-storybook-config'] --- import kbnSecuritySolutionStorybookConfigObj from './kbn_security_solution_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index b30e35ef27ac7..160e4b33b779a 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_data_table.mdx b/api_docs/kbn_securitysolution_data_table.mdx index 255d1a6618971..3b4edd18420ac 100644 --- a/api_docs/kbn_securitysolution_data_table.mdx +++ b/api_docs/kbn_securitysolution_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-data-table title: "@kbn/securitysolution-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-data-table plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-data-table'] --- import kbnSecuritysolutionDataTableObj from './kbn_securitysolution_data_table.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index 0165ca0b59fc9..5d11cfdca5b7f 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index eed593d43dfdc..8404d230bf212 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index a52e5be544f77..928cafcdeddab 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_grouping.mdx b/api_docs/kbn_securitysolution_grouping.mdx index bdc81d1d250ff..38cc77464c55e 100644 --- a/api_docs/kbn_securitysolution_grouping.mdx +++ b/api_docs/kbn_securitysolution_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-grouping title: "@kbn/securitysolution-grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-grouping plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-grouping'] --- import kbnSecuritysolutionGroupingObj from './kbn_securitysolution_grouping.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 24db83f3e3f7a..23a4d7539f34c 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index 90f75084bb669..096803d5d1dcc 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 698fecee87f4b..517925775389f 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index ae33949a4407d..63f8756358135 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index 076b1b05b227c..3b8453ee7140b 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index 92f8eca6e01af..e1460523bb773 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 516aa9347012f..8352096276e14 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 88e33dd10e14a..f706f8f6f4905 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index c2d7218df7952..df70e22184234 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 69f482223c092..621e624f7b3d0 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 50191d65e3946..6a4b404c44234 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index 3bd1fa2c85bf6..c458c7ab9d639 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 6d9c047cc6dff..d3775e0321552 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index e3a48d88b0e18..95acb3c677003 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_serverless_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index 5ed339bbdc7d6..aa6da93f9c477 100644 --- a/api_docs/kbn_serverless_project_switcher.mdx +++ b/api_docs/kbn_serverless_project_switcher.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-project-switcher title: "@kbn/serverless-project-switcher" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-project-switcher plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-project-switcher'] --- import kbnServerlessProjectSwitcherObj from './kbn_serverless_project_switcher.devdocs.json'; diff --git a/api_docs/kbn_serverless_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index 4e86bdd37dd6d..11f040fbf0ade 100644 --- a/api_docs/kbn_serverless_storybook_config.mdx +++ b/api_docs/kbn_serverless_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-storybook-config title: "@kbn/serverless-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-storybook-config plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-storybook-config'] --- import kbnServerlessStorybookConfigObj from './kbn_serverless_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index 93ff82a9dd673..6b612c9b52e3c 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index 47703e2a78d2f..0f2876009bf6d 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index c8955fc5261f5..7e36237dedc4b 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index b749af49bc262..db9395e88f664 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index f734d39ab043d..b0f90559e6ae0 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 7e0c73aadc6b3..e09d1bb60fb53 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.devdocs.json b/api_docs/kbn_shared_ux_card_no_data.devdocs.json index 796fa77d7c585..30043835cff52 100644 --- a/api_docs/kbn_shared_ux_card_no_data.devdocs.json +++ b/api_docs/kbn_shared_ux_card_no_data.devdocs.json @@ -28,7 +28,7 @@ "description": [], "signature": [ "({ href: srcHref, category, description, ...props }: ", - "NoDataCardProps", + "NoDataCardComponentProps", ") => JSX.Element" ], "path": "packages/shared-ux/card/no_data/impl/src/no_data_card.tsx", @@ -38,12 +38,12 @@ { "parentPluginId": "@kbn/shared-ux-card-no-data", "id": "def-common.NoDataCard.$1", - "type": "Object", + "type": "CompoundType", "tags": [], "label": "{ href: srcHref, category, description, ...props }", "description": [], "signature": [ - "NoDataCardProps" + "NoDataCardComponentProps" ], "path": "packages/shared-ux/card/no_data/impl/src/no_data_card.tsx", "deprecated": false, @@ -184,179 +184,9 @@ "\nProps for the `NoDataCard` sevice-connected component." ], "signature": [ - "{ prefix?: string | undefined; id?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; security?: string | undefined; children?: React.ReactNode; description?: React.ReactNode; category?: string | undefined; onChange?: React.FormEventHandler<HTMLDivElement> | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; className?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; hidden?: boolean | undefined; lang?: string | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; title?: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"search\" | \"none\" | \"text\" | \"url\" | \"email\" | \"tel\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"both\" | \"inline\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"page\" | \"date\" | \"true\" | \"false\" | \"location\" | \"time\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"execute\" | \"link\" | \"none\" | \"copy\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"true\" | \"false\" | \"grid\" | \"menu\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"text\" | \"all\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler<HTMLDivElement> | undefined; onCopyCapture?: React.ClipboardEventHandler<HTMLDivElement> | undefined; onCut?: React.ClipboardEventHandler<HTMLDivElement> | undefined; onCutCapture?: React.ClipboardEventHandler<HTMLDivElement> | undefined; onPaste?: React.ClipboardEventHandler<HTMLDivElement> | undefined; onPasteCapture?: React.ClipboardEventHandler<HTMLDivElement> | undefined; onCompositionEnd?: React.CompositionEventHandler<HTMLDivElement> | undefined; onCompositionEndCapture?: React.CompositionEventHandler<HTMLDivElement> | undefined; onCompositionStart?: React.CompositionEventHandler<HTMLDivElement> | undefined; onCompositionStartCapture?: React.CompositionEventHandler<HTMLDivElement> | undefined; onCompositionUpdate?: React.CompositionEventHandler<HTMLDivElement> | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler<HTMLDivElement> | undefined; onFocus?: React.FocusEventHandler<HTMLDivElement> | undefined; onFocusCapture?: React.FocusEventHandler<HTMLDivElement> | undefined; onBlur?: React.FocusEventHandler<HTMLDivElement> | undefined; onBlurCapture?: React.FocusEventHandler<HTMLDivElement> | undefined; onChangeCapture?: React.FormEventHandler<HTMLDivElement> | undefined; onBeforeInput?: React.FormEventHandler<HTMLDivElement> | undefined; onBeforeInputCapture?: React.FormEventHandler<HTMLDivElement> | undefined; onInput?: React.FormEventHandler<HTMLDivElement> | undefined; onInputCapture?: React.FormEventHandler<HTMLDivElement> | undefined; onReset?: React.FormEventHandler<HTMLDivElement> | undefined; onResetCapture?: React.FormEventHandler<HTMLDivElement> | undefined; onSubmit?: React.FormEventHandler<HTMLDivElement> | undefined; onSubmitCapture?: React.FormEventHandler<HTMLDivElement> | undefined; onInvalid?: React.FormEventHandler<HTMLDivElement> | undefined; onInvalidCapture?: React.FormEventHandler<HTMLDivElement> | undefined; onLoad?: React.ReactEventHandler<HTMLDivElement> | undefined; onLoadCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onError?: React.ReactEventHandler<HTMLDivElement> | undefined; onErrorCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onKeyDown?: React.KeyboardEventHandler<HTMLDivElement> | undefined; onKeyDownCapture?: React.KeyboardEventHandler<HTMLDivElement> | undefined; onKeyPress?: React.KeyboardEventHandler<HTMLDivElement> | undefined; onKeyPressCapture?: React.KeyboardEventHandler<HTMLDivElement> | undefined; onKeyUp?: React.KeyboardEventHandler<HTMLDivElement> | undefined; onKeyUpCapture?: React.KeyboardEventHandler<HTMLDivElement> | undefined; onAbort?: React.ReactEventHandler<HTMLDivElement> | undefined; onAbortCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onCanPlay?: React.ReactEventHandler<HTMLDivElement> | undefined; onCanPlayCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onCanPlayThrough?: React.ReactEventHandler<HTMLDivElement> | undefined; onCanPlayThroughCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onDurationChange?: React.ReactEventHandler<HTMLDivElement> | undefined; onDurationChangeCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onEmptied?: React.ReactEventHandler<HTMLDivElement> | undefined; onEmptiedCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onEncrypted?: React.ReactEventHandler<HTMLDivElement> | undefined; onEncryptedCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onEnded?: React.ReactEventHandler<HTMLDivElement> | undefined; onEndedCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onLoadedData?: React.ReactEventHandler<HTMLDivElement> | undefined; onLoadedDataCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onLoadedMetadata?: React.ReactEventHandler<HTMLDivElement> | undefined; onLoadedMetadataCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onLoadStart?: React.ReactEventHandler<HTMLDivElement> | undefined; onLoadStartCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onPause?: React.ReactEventHandler<HTMLDivElement> | undefined; onPauseCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onPlay?: React.ReactEventHandler<HTMLDivElement> | undefined; onPlayCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onPlaying?: React.ReactEventHandler<HTMLDivElement> | undefined; onPlayingCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onProgress?: React.ReactEventHandler<HTMLDivElement> | undefined; onProgressCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onRateChange?: React.ReactEventHandler<HTMLDivElement> | undefined; onRateChangeCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onSeeked?: React.ReactEventHandler<HTMLDivElement> | undefined; onSeekedCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onSeeking?: React.ReactEventHandler<HTMLDivElement> | undefined; onSeekingCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onStalled?: React.ReactEventHandler<HTMLDivElement> | undefined; onStalledCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onSuspend?: React.ReactEventHandler<HTMLDivElement> | undefined; onSuspendCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onTimeUpdate?: React.ReactEventHandler<HTMLDivElement> | undefined; onTimeUpdateCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onVolumeChange?: React.ReactEventHandler<HTMLDivElement> | undefined; onVolumeChangeCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onWaiting?: React.ReactEventHandler<HTMLDivElement> | undefined; onWaitingCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onAuxClick?: React.MouseEventHandler<HTMLDivElement> | undefined; onAuxClickCapture?: React.MouseEventHandler<HTMLDivElement> | undefined; onClick?: React.MouseEventHandler<HTMLElement> | undefined; onClickCapture?: React.MouseEventHandler<HTMLDivElement> | undefined; onContextMenu?: React.MouseEventHandler<HTMLDivElement> | undefined; onContextMenuCapture?: React.MouseEventHandler<HTMLDivElement> | undefined; onDoubleClick?: React.MouseEventHandler<HTMLDivElement> | undefined; onDoubleClickCapture?: React.MouseEventHandler<HTMLDivElement> | undefined; onDrag?: React.DragEventHandler<HTMLDivElement> | undefined; onDragCapture?: React.DragEventHandler<HTMLDivElement> | undefined; onDragEnd?: React.DragEventHandler<HTMLDivElement> | undefined; onDragEndCapture?: React.DragEventHandler<HTMLDivElement> | undefined; onDragEnter?: React.DragEventHandler<HTMLDivElement> | undefined; onDragEnterCapture?: React.DragEventHandler<HTMLDivElement> | undefined; onDragExit?: React.DragEventHandler<HTMLDivElement> | undefined; onDragExitCapture?: React.DragEventHandler<HTMLDivElement> | undefined; onDragLeave?: React.DragEventHandler<HTMLDivElement> | undefined; onDragLeaveCapture?: React.DragEventHandler<HTMLDivElement> | undefined; onDragOver?: React.DragEventHandler<HTMLDivElement> | undefined; onDragOverCapture?: React.DragEventHandler<HTMLDivElement> | undefined; onDragStart?: React.DragEventHandler<HTMLDivElement> | undefined; onDragStartCapture?: React.DragEventHandler<HTMLDivElement> | undefined; onDrop?: React.DragEventHandler<HTMLDivElement> | undefined; onDropCapture?: React.DragEventHandler<HTMLDivElement> | undefined; onMouseDown?: React.MouseEventHandler<HTMLDivElement> | undefined; onMouseDownCapture?: React.MouseEventHandler<HTMLDivElement> | undefined; onMouseEnter?: React.MouseEventHandler<HTMLDivElement> | undefined; onMouseLeave?: React.MouseEventHandler<HTMLDivElement> | undefined; onMouseMove?: React.MouseEventHandler<HTMLDivElement> | undefined; onMouseMoveCapture?: React.MouseEventHandler<HTMLDivElement> | undefined; onMouseOut?: React.MouseEventHandler<HTMLDivElement> | undefined; onMouseOutCapture?: React.MouseEventHandler<HTMLDivElement> | undefined; onMouseOver?: React.MouseEventHandler<HTMLDivElement> | undefined; onMouseOverCapture?: React.MouseEventHandler<HTMLDivElement> | undefined; onMouseUp?: React.MouseEventHandler<HTMLDivElement> | undefined; onMouseUpCapture?: React.MouseEventHandler<HTMLDivElement> | undefined; onSelect?: React.ReactEventHandler<HTMLDivElement> | undefined; onSelectCapture?: React.ReactEventHandler<HTMLDivElement> | undefined; onTouchCancel?: React.TouchEventHandler<HTMLDivElement> | undefined; onTouchCancelCapture?: React.TouchEventHandler<HTMLDivElement> | undefined; onTouchEnd?: React.TouchEventHandler<HTMLDivElement> | undefined; onTouchEndCapture?: React.TouchEventHandler<HTMLDivElement> | undefined; onTouchMove?: React.TouchEventHandler<HTMLDivElement> | undefined; onTouchMoveCapture?: React.TouchEventHandler<HTMLDivElement> | undefined; onTouchStart?: React.TouchEventHandler<HTMLDivElement> | undefined; onTouchStartCapture?: React.TouchEventHandler<HTMLDivElement> | undefined; onPointerDown?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerDownCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerMove?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerMoveCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerUp?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerUpCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerCancel?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerCancelCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerEnter?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerEnterCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerLeave?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerLeaveCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerOver?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerOverCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerOut?: React.PointerEventHandler<HTMLDivElement> | undefined; onPointerOutCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onGotPointerCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onLostPointerCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler<HTMLDivElement> | undefined; onScroll?: React.UIEventHandler<HTMLDivElement> | undefined; onScrollCapture?: React.UIEventHandler<HTMLDivElement> | undefined; onWheel?: React.WheelEventHandler<HTMLDivElement> | undefined; onWheelCapture?: React.WheelEventHandler<HTMLDivElement> | undefined; onAnimationStart?: React.AnimationEventHandler<HTMLDivElement> | undefined; onAnimationStartCapture?: React.AnimationEventHandler<HTMLDivElement> | undefined; onAnimationEnd?: React.AnimationEventHandler<HTMLDivElement> | undefined; onAnimationEndCapture?: React.AnimationEventHandler<HTMLDivElement> | undefined; onAnimationIteration?: React.AnimationEventHandler<HTMLDivElement> | undefined; onAnimationIterationCapture?: React.AnimationEventHandler<HTMLDivElement> | undefined; onTransitionEnd?: React.TransitionEventHandler<HTMLDivElement> | undefined; onTransitionEndCapture?: React.TransitionEventHandler<HTMLDivElement> | undefined; hasBorder?: boolean | undefined; paddingSize?: \"m\" | \"none\" | \"s\" | \"xs\" | \"l\" | \"xl\" | undefined; 'data-test-subj'?: string | undefined; css?: ", - "Interpolation", - "<", - "Theme", - ">; href?: string | undefined; rel?: string | undefined; target?: string | undefined; icon?: React.ReactElement<", - "EuiIconProps", - ", string | React.JSXElementConstructor<any>> | null | undefined; image?: string | React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined; display?: \"warning\" | \"success\" | \"subdued\" | \"primary\" | \"accent\" | \"danger\" | \"transparent\" | \"plain\" | undefined; button?: React.ReactNode; footer?: React.ReactNode; textAlign?: \"left\" | \"right\" | \"center\" | undefined; titleElement?: \"span\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | undefined; titleSize?: \"s\" | \"xs\" | undefined; betaBadgeProps?: (", - "CommonProps", - " & ", - "DisambiguateSet", - "<(", - "DisambiguateSet", - "<WithButtonProps, WithAnchorProps> & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLAnchorElement>, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - "<WithAnchorProps, WithButtonProps> & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; onClickAriaLabel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLButtonElement>, \"color\" | \"onClick\">), WithSpanProps> & WithSpanProps & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes<HTMLSpanElement>) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - "<LabelAsNode, LabelAsString> & LabelAsString) | (", - "CommonProps", - " & ", - "DisambiguateSet", - "<(", - "DisambiguateSet", - "<WithButtonProps, WithAnchorProps> & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLAnchorElement>, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - "<WithAnchorProps, WithButtonProps> & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; onClickAriaLabel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLButtonElement>, \"color\" | \"onClick\">), WithSpanProps> & WithSpanProps & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes<HTMLSpanElement>) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - "<LabelAsString, LabelAsNode> & ", - "DisambiguateSet", - "<{ title: string; tooltipContent?: React.ReactNode; }, { tooltipContent: React.ReactNode; title?: string | undefined; }> & { tooltipContent: React.ReactNode; title?: string | undefined; } & { label: React.ReactNode; }) | (", - "CommonProps", - " & ", - "DisambiguateSet", - "<WithSpanProps, (", - "DisambiguateSet", - "<WithButtonProps, WithAnchorProps> & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLAnchorElement>, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - "<WithAnchorProps, WithButtonProps> & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; onClickAriaLabel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLButtonElement>, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - "<WithButtonProps, WithAnchorProps> & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLAnchorElement>, \"color\" | \"onClick\" | \"href\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes<HTMLSpanElement>) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - "<LabelAsNode, LabelAsString> & LabelAsString) | (", - "CommonProps", - " & ", - "DisambiguateSet", - "<WithSpanProps, (", - "DisambiguateSet", - "<WithButtonProps, WithAnchorProps> & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLAnchorElement>, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - "<WithAnchorProps, WithButtonProps> & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; onClickAriaLabel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLButtonElement>, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - "<WithButtonProps, WithAnchorProps> & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLAnchorElement>, \"color\" | \"onClick\" | \"href\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes<HTMLSpanElement>) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - "<LabelAsString, LabelAsNode> & ", - "DisambiguateSet", - "<{ title: string; tooltipContent?: React.ReactNode; }, { tooltipContent: React.ReactNode; title?: string | undefined; }> & { tooltipContent: React.ReactNode; title?: string | undefined; } & { label: React.ReactNode; }) | (", - "CommonProps", - " & ", - "DisambiguateSet", - "<WithSpanProps, (", - "DisambiguateSet", - "<WithButtonProps, WithAnchorProps> & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLAnchorElement>, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - "<WithAnchorProps, WithButtonProps> & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; onClickAriaLabel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLButtonElement>, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - "<WithButtonProps, WithAnchorProps> & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLAnchorElement>, \"color\" | \"onClick\" | \"href\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes<HTMLSpanElement>) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - "<LabelAsString, LabelAsNode> & ", - "DisambiguateSet", - "<{ tooltipContent: React.ReactNode; title?: string | undefined; }, { title: string; tooltipContent?: React.ReactNode; }> & { title: string; tooltipContent?: React.ReactNode; } & { label: React.ReactNode; }) | (", - "CommonProps", - " & ", - "DisambiguateSet", - "<WithSpanProps, (", - "DisambiguateSet", - "<WithButtonProps, WithAnchorProps> & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLAnchorElement>, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - "<WithAnchorProps, WithButtonProps> & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; onClickAriaLabel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLButtonElement>, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - "<WithAnchorProps, WithButtonProps> & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; onClickAriaLabel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLButtonElement>, \"color\" | \"onClick\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes<HTMLSpanElement>) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - "<LabelAsNode, LabelAsString> & LabelAsString) | (", - "CommonProps", - " & ", - "DisambiguateSet", - "<WithSpanProps, (", - "DisambiguateSet", - "<WithButtonProps, WithAnchorProps> & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLAnchorElement>, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - "<WithAnchorProps, WithButtonProps> & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; onClickAriaLabel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLButtonElement>, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - "<WithAnchorProps, WithButtonProps> & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; onClickAriaLabel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLButtonElement>, \"color\" | \"onClick\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes<HTMLSpanElement>) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - "<LabelAsString, LabelAsNode> & ", - "DisambiguateSet", - "<{ title: string; tooltipContent?: React.ReactNode; }, { tooltipContent: React.ReactNode; title?: string | undefined; }> & { tooltipContent: React.ReactNode; title?: string | undefined; } & { label: React.ReactNode; }) | (", - "CommonProps", - " & ", - "DisambiguateSet", - "<WithSpanProps, (", - "DisambiguateSet", - "<WithButtonProps, WithAnchorProps> & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLAnchorElement>, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - "<WithAnchorProps, WithButtonProps> & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; onClickAriaLabel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLButtonElement>, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - "<WithAnchorProps, WithButtonProps> & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; onClickAriaLabel?: string | undefined; } & Omit<React.HTMLAttributes<HTMLButtonElement>, \"color\" | \"onClick\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes<HTMLSpanElement>) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - "<LabelAsString, LabelAsNode> & ", - "DisambiguateSet", - "<{ tooltipContent: React.ReactNode; title?: string | undefined; }, { title: string; tooltipContent?: React.ReactNode; }> & { title: string; tooltipContent?: React.ReactNode; } & { label: React.ReactNode; }) | undefined; selectable?: (", - "DisambiguateSet", - "<", - "EuiButtonPropsForAnchor", - ", ", - "EuiButtonPropsForButton", - "> & ", - "EuiButtonProps", - " & { onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined; } & React.ButtonHTMLAttributes<HTMLButtonElement> & { buttonRef?: React.Ref<HTMLButtonElement> | undefined; }) | (", - "DisambiguateSet", - "<", - "EuiButtonPropsForButton", - ", ", - "EuiButtonPropsForAnchor", - "> & ", - "EuiButtonProps", - " & { href?: string | undefined; onClick?: React.MouseEventHandler<HTMLAnchorElement> | undefined; } & React.AnchorHTMLAttributes<HTMLAnchorElement> & { buttonRef?: React.Ref<HTMLAnchorElement> | undefined; }) | undefined; }" + "Partial<Omit<", + "EuiCardProps", + ", \"description\" | \"onClick\" | \"isDisabled\" | \"layout\" | \"button\">> & { button?: React.ReactNode; onClick?: React.MouseEventHandler<HTMLElement> | undefined; description?: React.ReactNode; category?: string | undefined; canAccessFleet?: boolean | undefined; }" ], "path": "packages/shared-ux/card/no_data/types/index.d.ts", "deprecated": false, diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 8dd83e914d6ab..f4e62f597966a 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.devdocs.json b/api_docs/kbn_shared_ux_card_no_data_mocks.devdocs.json index 1aa83630b7156..9283e27a593ff 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.devdocs.json +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.devdocs.json @@ -44,7 +44,7 @@ "text": "AbstractStorybookMock" }, "<", - "NoDataCardProps", + "NoDataCardComponentProps", ", ", "NoDataCardServices", ", PropArguments, ServiceArguments>" @@ -344,7 +344,7 @@ "text": "Params" }, " | undefined) => ", - "NoDataCardProps" + "NoDataCardComponentProps" ], "path": "packages/shared-ux/card/no_data/mocks/src/storybook.ts", "deprecated": false, diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 4673fd2972836..69199b1416456 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_chrome_navigation.mdx b/api_docs/kbn_shared_ux_chrome_navigation.mdx index d9260c5f26437..cf16454368cd0 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.mdx +++ b/api_docs/kbn_shared_ux_chrome_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-chrome-navigation title: "@kbn/shared-ux-chrome-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-chrome-navigation plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-chrome-navigation'] --- import kbnSharedUxChromeNavigationObj from './kbn_shared_ux_chrome_navigation.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index f781d7d70f194..23f9d0a2811e3 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index e4a6df96a1a04..830594a259441 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index afa41697edfdd..5b1ac2d313724 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index 1c5ef9ed1da6f..92f4185ba9485 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index 4ad2618cd9b29..856f141ffb8ed 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx index 167b8c852a805..8b30f58d1014e 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] --- import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 086ecc19f9084..ee118d8d30131 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index c70d57a2252a0..4d209eb741ade 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index de45099694ed2..e6ad6ff96ef6f 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index 5e61e4f9cf607..7a58af1dd23c1 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index 55cd4377dbd63..cb8c346fe03d4 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index cac8433f7fa33..4704d8ff04654 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.devdocs.json b/api_docs/kbn_shared_ux_page_analytics_no_data.devdocs.json index 217e49d5572e4..4b6db494be35b 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.devdocs.json +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.devdocs.json @@ -66,7 +66,7 @@ "\nA pure component of an entire page that can be displayed when Kibana \"has no data\", specifically for Analytics." ], "signature": [ - "({ kibanaGuideDocLink, onDataViewCreated, allowAdHocDataView, showPlainSpinner, }: ", + "({ kibanaGuideDocLink, onDataViewCreated, allowAdHocDataView, showPlainSpinner, prependBasePath, pageFlavor, }: ", "Props", ") => JSX.Element" ], @@ -79,7 +79,7 @@ "id": "def-common.AnalyticsNoDataPage.$1", "type": "Object", "tags": [], - "label": "{\n kibanaGuideDocLink,\n onDataViewCreated,\n allowAdHocDataView,\n showPlainSpinner,\n}", + "label": "{\n kibanaGuideDocLink,\n onDataViewCreated,\n allowAdHocDataView,\n showPlainSpinner,\n prependBasePath,\n pageFlavor = 'kibana',\n}", "description": [], "signature": [ "Props" diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index fdffba1ab9db7..8f137c1b19bae 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index 8f8ffb559f6da..43b35150ca54f 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index a5f6dde801029..76beef22dab87 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index 372b64e714635..7287acc7bf6d6 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index 5d63395058034..7a4c6b9f0ca79 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index 51ddbcf854299..42191d0e64159 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.devdocs.json b/api_docs/kbn_shared_ux_page_no_data.devdocs.json index e6f62668e8f73..9aa9a10503b95 100644 --- a/api_docs/kbn_shared_ux_page_no_data.devdocs.json +++ b/api_docs/kbn_shared_ux_page_no_data.devdocs.json @@ -172,7 +172,10 @@ "tags": [], "label": "docsLink", "description": [ - "\nRequired to set the docs link for the whole solution" + "\nRequired in \"kibana\" flavor to set the docs link for the whole solution, otherwise optional" + ], + "signature": [ + "string | undefined" ], "path": "packages/shared-ux/page/no_data/types/index.d.ts", "deprecated": false, diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 22118ce9b06ed..274d7abec9027 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 2ccd8f078d37b..8ad594e4af757 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index e590c55314f33..17435ce9d3f78 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index 7fc9af83b2b79..875216415544c 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index 9e99c44add2c5..957c1bb26ac28 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index 330f831293846..21228fc56e777 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index 1a431bddf6153..f9d069f8e210f 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index 245c1b7f291df..ce4ddbf658b33 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index a0ef64ac2048e..71e814e3be0d8 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index 32da12d65192a..d37edc70374c6 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index c4f64195fbc60..18e25c6928684 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index 3624d063eb708..a1cd940e9f883 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 7bb41b54d7813..e3ace32ceff37 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.devdocs.json b/api_docs/kbn_slo_schema.devdocs.json index f3d983b94c45e..02eec6e3a39cb 100644 --- a/api_docs/kbn_slo_schema.devdocs.json +++ b/api_docs/kbn_slo_schema.devdocs.json @@ -3591,26 +3591,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "@kbn/slo-schema", - "id": "def-common.getSLODiagnosisParamsSchema", - "type": "Object", - "tags": [], - "label": "getSLODiagnosisParamsSchema", - "description": [], - "signature": [ - "TypeC", - "<{ path: ", - "TypeC", - "<{ id: ", - "StringC", - "; }>; }>" - ], - "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "@kbn/slo-schema", "id": "def-common.getSLOInstancesParamsSchema", diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index f7be00fa3d043..fa014ce11dddb 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/actionable-observability](https://github.com/orgs/elastic/team | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 133 | 0 | 130 | 0 | +| 132 | 0 | 129 | 0 | ## Common diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index b67bb857c65a8..5e91eb8810ae4 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 298e5619bbc34..e5ab024d5bf00 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index 9a2df44429635..257d1a20a394c 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index f0a174578c760..5b1672a76e614 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index cc1df56cc923d..4f3af81ac9d76 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index f9ab7378a610c..12254960a3bcd 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 4aecfe0131933..4d8ddb2f69963 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index 1b55dd7131894..e5fa037280d38 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_text_based_editor.mdx b/api_docs/kbn_text_based_editor.mdx index bb0c65074cc60..d0c71da058945 100644 --- a/api_docs/kbn_text_based_editor.mdx +++ b/api_docs/kbn_text_based_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-text-based-editor title: "@kbn/text-based-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/text-based-editor plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 6e48b6768bf7e..b20f45a9c4058 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index 766cb3f9cb0a8..f5eabeb06ea4c 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 4b2c77303f15e..31ea7d67456a5 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index 17963d781df57..1358a1714994e 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index b05479b849817..f3d423de49ff6 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index ea892279118e6..f22c2c15c35fc 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index 56fdb4e443640..6a265e7eadae2 100644 --- a/api_docs/kbn_unified_field_list.mdx +++ b/api_docs/kbn_unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-field-list title: "@kbn/unified-field-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-field-list plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.devdocs.json'; diff --git a/api_docs/kbn_url_state.mdx b/api_docs/kbn_url_state.mdx index 43efefbcba544..8ff7a1031b7a8 100644 --- a/api_docs/kbn_url_state.mdx +++ b/api_docs/kbn_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-url-state title: "@kbn/url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/url-state plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/url-state'] --- import kbnUrlStateObj from './kbn_url_state.devdocs.json'; diff --git a/api_docs/kbn_use_tracked_promise.mdx b/api_docs/kbn_use_tracked_promise.mdx index 83f6de626fad2..0af4f5d49265e 100644 --- a/api_docs/kbn_use_tracked_promise.mdx +++ b/api_docs/kbn_use_tracked_promise.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-use-tracked-promise title: "@kbn/use-tracked-promise" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/use-tracked-promise plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/use-tracked-promise'] --- import kbnUseTrackedPromiseObj from './kbn_use_tracked_promise.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 6157307403717..9fed54ca5d325 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index e9f5af14d629e..c0e666a3d573c 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index 0157113f06ed6..430e9f209ba18 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index c440db5e6fd00..16987b55706d4 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index 51c3608a82595..5d5a3f2a58c0e 100644 --- a/api_docs/kbn_visualization_ui_components.mdx +++ b/api_docs/kbn_visualization_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-ui-components title: "@kbn/visualization-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-ui-components plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 852a5eab0c5cb..ddee9ca854aa9 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index ed12c1c0988aa..4bd66f17c803d 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index c2027b9045e04..2ee81bd38b33e 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index df62b3e0ef796..2a09443de9b3c 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index 970c9f245c393..e1da6b763fa0d 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index e1bd8dad106b7..595a33dd849bf 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index dbeb3765baf64..d39ec76e6e0b6 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 81a762e5e53c6..181c51f6a7f60 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 4c84d136d33f4..2e7ed075cd6c8 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 13016f736fb69..ff691940dc751 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index e9e23f9745349..8ec3e570acee0 100644 --- a/api_docs/logs_shared.mdx +++ b/api_docs/logs_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsShared title: "logsShared" image: https://source.unsplash.com/400x175/?github description: API docs for the logsShared plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsShared'] --- import logsSharedObj from './logs_shared.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index f8f6b02b958ae..851e89f0450f6 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 21e1d235c2832..c7dd1d3279bc4 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index e25fa6dc8b213..04030f115b578 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 41e335b2fe8a5..a389fc5a3d29e 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 166def6155dde..e955022d97f6f 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index d43e2ebf85923..d679b2cd903c7 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index 29ab5944a4a73..eea6f16c1b1f2 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index e7a38d7160b0f..6b5368717a70c 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/no_data_page.devdocs.json b/api_docs/no_data_page.devdocs.json new file mode 100644 index 0000000000000..0bbeb2e20defc --- /dev/null +++ b/api_docs/no_data_page.devdocs.json @@ -0,0 +1,49 @@ +{ + "id": "noDataPage", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [], + "setup": { + "parentPluginId": "noDataPage", + "id": "def-public.NoDataPagePluginStart", + "type": "Type", + "tags": [], + "label": "NoDataPagePluginStart", + "description": [], + "signature": [ + { + "pluginId": "noDataPage", + "scope": "public", + "docId": "kibNoDataPagePluginApi", + "section": "def-public.NoDataPagePluginSetup", + "text": "NoDataPagePluginSetup" + } + ], + "path": "src/plugins/no_data_page/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "lifecycle": "setup", + "initialIsOpen": true + } + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/no_data_page.mdx b/api_docs/no_data_page.mdx new file mode 100644 index 0000000000000..6014be6b3ae9f --- /dev/null +++ b/api_docs/no_data_page.mdx @@ -0,0 +1,30 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibNoDataPagePluginApi +slug: /kibana-dev-docs/api/noDataPage +title: "noDataPage" +image: https://source.unsplash.com/400x175/?github +description: API docs for the noDataPage plugin +date: 2023-08-29 +tags: ['contributor', 'dev', 'apidocs', 'kibana', 'noDataPage'] +--- +import noDataPageObj from './no_data_page.devdocs.json'; + + + +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 3 | 0 | 3 | 0 | + +## Client + +### Setup +<DocDefinitionList data={[noDataPageObj.client.setup]}/> + diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index a4c686845e407..864910d8ef2c5 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index 3816bbd3603fd..e910e74323d61 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -8627,72 +8627,6 @@ "section": "def-server.ObservabilityRouteCreateOptions", "text": "ObservabilityRouteCreateOptions" }, - "; \"GET /internal/observability/slos/{id}/_diagnosis\": { endpoint: \"GET /internal/observability/slos/{id}/_diagnosis\"; params?: ", - "TypeC", - "<{ path: ", - "TypeC", - "<{ id: ", - "StringC", - "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "observability", - "scope": "server", - "docId": "kibObservabilityPluginApi", - "section": "def-server.ObservabilityRouteHandlerResources", - "text": "ObservabilityRouteHandlerResources" - }, - " & { params: { path: { id: string; }; }; }) => Promise<{ sloResources: { \".slo-observability.sli\": string; \".slo-observability.sli-mappings\": string; \".slo-observability.sli-settings\": string; \".slo-observability.sli.pipeline\": string; } | undefined; sloSummaryResources: { \".slo-observability.summary\": string; \".slo-observability.summary-mappings\": string; \".slo-observability.summary-settings\": string; } | undefined; slo: string | { id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; equation: string; }; total: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; type: \"rolling\"; } | { duration: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - " | undefined; }; settings: { syncDelay: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; frequency: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; }; revision: number; enabled: boolean; tags: string[]; createdAt: Date; updatedAt: Date; groupBy: string; }; sloTransformStats: ", - "TransformGetTransformStatsResponse", - "; sloSummaryTransformsStats: ", - "TransformGetTransformStatsResponse", - "; }>; } & ", - { - "pluginId": "observability", - "scope": "server", - "docId": "kibObservabilityPluginApi", - "section": "def-server.ObservabilityRouteCreateOptions", - "text": "ObservabilityRouteCreateOptions" - }, "; \"GET /internal/observability/slos/_diagnosis\": { endpoint: \"GET /internal/observability/slos/_diagnosis\"; params?: undefined; handler: ({}: ", { "pluginId": "observability", @@ -8703,11 +8637,11 @@ }, ") => Promise<{ licenseAndFeatures: ", "PublicLicenseJSON", - "; userPrivileges: ", - "SecurityGetUserPrivilegesResponse", - "; sloResources: { \".slo-observability.sli\": string; \".slo-observability.sli-mappings\": string; \".slo-observability.sli-settings\": string; \".slo-observability.sli.pipeline\": string; } | undefined; sloSummaryResources: { \".slo-observability.summary\": string; \".slo-observability.summary-mappings\": string; \".slo-observability.summary-settings\": string; } | undefined; sloSummaryTransformsStats: ", - "TransformGetTransformStatsResponse", - "; }>; } & ", + "; userPrivileges: { write: ", + "SecurityHasPrivilegesResponse", + "; read: ", + "SecurityHasPrivilegesResponse", + "; }; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -10399,72 +10333,6 @@ "section": "def-server.ObservabilityRouteCreateOptions", "text": "ObservabilityRouteCreateOptions" }, - "; \"GET /internal/observability/slos/{id}/_diagnosis\": { endpoint: \"GET /internal/observability/slos/{id}/_diagnosis\"; params?: ", - "TypeC", - "<{ path: ", - "TypeC", - "<{ id: ", - "StringC", - "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "observability", - "scope": "server", - "docId": "kibObservabilityPluginApi", - "section": "def-server.ObservabilityRouteHandlerResources", - "text": "ObservabilityRouteHandlerResources" - }, - " & { params: { path: { id: string; }; }; }) => Promise<{ sloResources: { \".slo-observability.sli\": string; \".slo-observability.sli-mappings\": string; \".slo-observability.sli-settings\": string; \".slo-observability.sli.pipeline\": string; } | undefined; sloSummaryResources: { \".slo-observability.summary\": string; \".slo-observability.summary-mappings\": string; \".slo-observability.summary-settings\": string; } | undefined; slo: string | { id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; equation: string; }; total: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; type: \"rolling\"; } | { duration: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - " | undefined; }; settings: { syncDelay: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; frequency: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; }; revision: number; enabled: boolean; tags: string[]; createdAt: Date; updatedAt: Date; groupBy: string; }; sloTransformStats: ", - "TransformGetTransformStatsResponse", - "; sloSummaryTransformsStats: ", - "TransformGetTransformStatsResponse", - "; }>; } & ", - { - "pluginId": "observability", - "scope": "server", - "docId": "kibObservabilityPluginApi", - "section": "def-server.ObservabilityRouteCreateOptions", - "text": "ObservabilityRouteCreateOptions" - }, "; \"GET /internal/observability/slos/_diagnosis\": { endpoint: \"GET /internal/observability/slos/_diagnosis\"; params?: undefined; handler: ({}: ", { "pluginId": "observability", @@ -10475,11 +10343,11 @@ }, ") => Promise<{ licenseAndFeatures: ", "PublicLicenseJSON", - "; userPrivileges: ", - "SecurityGetUserPrivilegesResponse", - "; sloResources: { \".slo-observability.sli\": string; \".slo-observability.sli-mappings\": string; \".slo-observability.sli-settings\": string; \".slo-observability.sli.pipeline\": string; } | undefined; sloSummaryResources: { \".slo-observability.summary\": string; \".slo-observability.summary-mappings\": string; \".slo-observability.summary-settings\": string; } | undefined; sloSummaryTransformsStats: ", - "TransformGetTransformStatsResponse", - "; }>; } & ", + "; userPrivileges: { write: ", + "SecurityHasPrivilegesResponse", + "; read: ", + "SecurityHasPrivilegesResponse", + "; }; }>; } & ", { "pluginId": "observability", "scope": "server", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 701c96c075b3d..e08e73da6a8f1 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.devdocs.json b/api_docs/observability_a_i_assistant.devdocs.json index add55aaff694a..f1202bffd58d1 100644 --- a/api_docs/observability_a_i_assistant.devdocs.json +++ b/api_docs/observability_a_i_assistant.devdocs.json @@ -367,7 +367,29 @@ "label": "APIReturnType", "description": [], "signature": [ - "{ \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", + "{ \"POST /internal/observability_ai_assistant/functions/alerts\": { endpoint: \"POST /internal/observability_ai_assistant/functions/alerts\"; params?: ", + "TypeC", + "<{ body: ", + "IntersectionC", + "<[", + "TypeC", + "<{ featureIds: ", + "ArrayC", + "<", + "StringC", + ">; start: ", + "StringC", + "; end: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }> | undefined; handler: ({}: ", + "ObservabilityAIAssistantRouteHandlerResources", + " & { params: { body: { featureIds: string[]; start: string; end: string; } & { filter?: string | undefined; }; }; }) => Promise<{ content: { total: number; alerts: OutputOf<SetOptional<{ readonly \"kibana.alert.risk_score\": { readonly type: \"float\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.author\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.created_at\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.created_by\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.description\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.enabled\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.from\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.interval\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.license\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.note\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.references\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.rule_id\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.rule_name_override\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.to\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.type\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.updated_at\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.updated_by\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.version\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.severity\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.docs_count\": { readonly type: \"long\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.end\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.terms.field\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.suppression.start\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.terms.value\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.system_status\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_reason\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_user\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"ecs.version\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"@timestamp\": { readonly type: \"date\"; readonly required: true; readonly array: false; }; readonly \"event.action\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly tags: { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.rule_type_id\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.consumer\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.execution.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.action_group\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.case_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.duration.us\": { readonly type: \"long\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.end\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.flapping\": { readonly type: \"boolean\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.flapping_history\": { readonly type: \"boolean\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.maintenance_window_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.instance.id\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.last_detected\": { readonly type: \"date\"; readonly required: false; readonly array: false; }; readonly \"kibana.alert.reason\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.category\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.name\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.parameters\": { readonly array: false; readonly type: \"flattened\"; readonly ignore_above: 4096; readonly required: false; }; readonly \"kibana.alert.rule.producer\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.revision\": { readonly type: \"long\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.tags\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.start\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.status\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.time_range\": { readonly type: \"date_range\"; readonly format: \"epoch_millis||strict_date_optional_time\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.url\": { readonly type: \"keyword\"; readonly array: false; readonly index: false; readonly required: false; readonly ignore_above: 2048; }; readonly \"kibana.alert.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.workflow_status\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_tags\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"event.kind\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.space_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: true; }; readonly \"kibana.version\": { readonly type: \"version\"; readonly array: false; readonly required: false; }; }>>[]; }; }>; } & ", + "ObservabilityAIAssistantRouteCreateOptions", + "; \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", ") => Promise<{ ready: boolean; error?: any; deployment_state?: string | undefined; allocation_state?: string | undefined; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -405,7 +427,13 @@ "Type", "<boolean, boolean, unknown>; public: ", "Type", - "<boolean, boolean, unknown>; }>; }> | undefined; handler: ({}: ", + "<boolean, boolean, unknown>; labels: ", + "RecordC", + "<", + "StringC", + ", ", + "StringC", + ">; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", " & { params: { body: { id: string; text: ", "Branded", @@ -417,13 +445,15 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; }; }; }) => Promise<void>; } & ", + ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; labels: { [x: string]: string; }; }; }; }) => Promise<void>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/recall\": { endpoint: \"POST /internal/observability_ai_assistant/functions/recall\"; params?: ", "TypeC", "<{ body: ", "TypeC", - "<{ query: ", + "<{ queries: ", + "ArrayC", + "<", "BrandC", "<", "StringC", @@ -435,9 +465,9 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; }>; }> | undefined; handler: ({}: ", + ">>; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", - " & { params: { body: { query: ", + " & { params: { body: { queries: ", "Branded", "<string, ", { @@ -447,9 +477,9 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; }; }; }) => Promise<{ entries: ", + ">[]; }; }; }) => Promise<{ entries: Pick<", "KnowledgeBaseEntry", - "[]; }>; } & ", + ", \"id\" | \"text\">[]; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/elasticsearch\": { endpoint: \"POST /internal/observability_ai_assistant/functions/elasticsearch\"; params?: ", "TypeC", @@ -700,7 +730,29 @@ "label": "ObservabilityAIAssistantAPIClientRequestParamsOf", "description": [], "signature": [ - "{ \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", + "{ \"POST /internal/observability_ai_assistant/functions/alerts\": { endpoint: \"POST /internal/observability_ai_assistant/functions/alerts\"; params?: ", + "TypeC", + "<{ body: ", + "IntersectionC", + "<[", + "TypeC", + "<{ featureIds: ", + "ArrayC", + "<", + "StringC", + ">; start: ", + "StringC", + "; end: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }> | undefined; handler: ({}: ", + "ObservabilityAIAssistantRouteHandlerResources", + " & { params: { body: { featureIds: string[]; start: string; end: string; } & { filter?: string | undefined; }; }; }) => Promise<{ content: { total: number; alerts: OutputOf<SetOptional<{ readonly \"kibana.alert.risk_score\": { readonly type: \"float\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.author\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.created_at\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.created_by\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.description\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.enabled\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.from\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.interval\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.license\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.note\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.references\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.rule_id\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.rule_name_override\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.to\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.type\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.updated_at\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.updated_by\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.version\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.severity\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.docs_count\": { readonly type: \"long\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.end\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.terms.field\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.suppression.start\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.terms.value\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.system_status\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_reason\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_user\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"ecs.version\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"@timestamp\": { readonly type: \"date\"; readonly required: true; readonly array: false; }; readonly \"event.action\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly tags: { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.rule_type_id\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.consumer\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.execution.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.action_group\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.case_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.duration.us\": { readonly type: \"long\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.end\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.flapping\": { readonly type: \"boolean\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.flapping_history\": { readonly type: \"boolean\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.maintenance_window_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.instance.id\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.last_detected\": { readonly type: \"date\"; readonly required: false; readonly array: false; }; readonly \"kibana.alert.reason\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.category\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.name\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.parameters\": { readonly array: false; readonly type: \"flattened\"; readonly ignore_above: 4096; readonly required: false; }; readonly \"kibana.alert.rule.producer\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.revision\": { readonly type: \"long\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.tags\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.start\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.status\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.time_range\": { readonly type: \"date_range\"; readonly format: \"epoch_millis||strict_date_optional_time\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.url\": { readonly type: \"keyword\"; readonly array: false; readonly index: false; readonly required: false; readonly ignore_above: 2048; }; readonly \"kibana.alert.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.workflow_status\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_tags\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"event.kind\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.space_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: true; }; readonly \"kibana.version\": { readonly type: \"version\"; readonly array: false; readonly required: false; }; }>>[]; }; }>; } & ", + "ObservabilityAIAssistantRouteCreateOptions", + "; \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", ") => Promise<{ ready: boolean; error?: any; deployment_state?: string | undefined; allocation_state?: string | undefined; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -738,7 +790,13 @@ "Type", "<boolean, boolean, unknown>; public: ", "Type", - "<boolean, boolean, unknown>; }>; }> | undefined; handler: ({}: ", + "<boolean, boolean, unknown>; labels: ", + "RecordC", + "<", + "StringC", + ", ", + "StringC", + ">; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", " & { params: { body: { id: string; text: ", "Branded", @@ -750,13 +808,15 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; }; }; }) => Promise<void>; } & ", + ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; labels: { [x: string]: string; }; }; }; }) => Promise<void>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/recall\": { endpoint: \"POST /internal/observability_ai_assistant/functions/recall\"; params?: ", "TypeC", "<{ body: ", "TypeC", - "<{ query: ", + "<{ queries: ", + "ArrayC", + "<", "BrandC", "<", "StringC", @@ -768,9 +828,9 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; }>; }> | undefined; handler: ({}: ", + ">>; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", - " & { params: { body: { query: ", + " & { params: { body: { queries: ", "Branded", "<string, ", { @@ -780,9 +840,9 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; }; }; }) => Promise<{ entries: ", + ">[]; }; }; }) => Promise<{ entries: Pick<", "KnowledgeBaseEntry", - "[]; }>; } & ", + ", \"id\" | \"text\">[]; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/elasticsearch\": { endpoint: \"POST /internal/observability_ai_assistant/functions/elasticsearch\"; params?: ", "TypeC", @@ -1041,7 +1101,7 @@ "label": "ObservabilityAIAssistantAPIEndpoint", "description": [], "signature": [ - "\"POST /internal/observability_ai_assistant/chat\" | \"GET /internal/observability_ai_assistant/conversation/{conversationId}\" | \"POST /internal/observability_ai_assistant/conversations\" | \"POST /internal/observability_ai_assistant/conversation\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}/auto_title\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}/title\" | \"DELETE /internal/observability_ai_assistant/conversation/{conversationId}\" | \"GET /internal/observability_ai_assistant/connectors\" | \"POST /internal/observability_ai_assistant/functions/elasticsearch\" | \"POST /internal/observability_ai_assistant/functions/recall\" | \"POST /internal/observability_ai_assistant/functions/summarise\" | \"POST /internal/observability_ai_assistant/functions/setup_kb\" | \"GET /internal/observability_ai_assistant/functions/kb_status\"" + "\"POST /internal/observability_ai_assistant/chat\" | \"GET /internal/observability_ai_assistant/conversation/{conversationId}\" | \"POST /internal/observability_ai_assistant/conversations\" | \"POST /internal/observability_ai_assistant/conversation\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}/auto_title\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}/title\" | \"DELETE /internal/observability_ai_assistant/conversation/{conversationId}\" | \"GET /internal/observability_ai_assistant/connectors\" | \"POST /internal/observability_ai_assistant/functions/elasticsearch\" | \"POST /internal/observability_ai_assistant/functions/recall\" | \"POST /internal/observability_ai_assistant/functions/summarise\" | \"POST /internal/observability_ai_assistant/functions/setup_kb\" | \"GET /internal/observability_ai_assistant/functions/kb_status\" | \"POST /internal/observability_ai_assistant/functions/alerts\"" ], "path": "x-pack/plugins/observability_ai_assistant/public/api/index.ts", "deprecated": false, @@ -1139,7 +1199,29 @@ "label": "ObservabilityAIAssistantServerRouteRepository", "description": [], "signature": [ - "{ \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", + "{ \"POST /internal/observability_ai_assistant/functions/alerts\": { endpoint: \"POST /internal/observability_ai_assistant/functions/alerts\"; params?: ", + "TypeC", + "<{ body: ", + "IntersectionC", + "<[", + "TypeC", + "<{ featureIds: ", + "ArrayC", + "<", + "StringC", + ">; start: ", + "StringC", + "; end: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }> | undefined; handler: ({}: ", + "ObservabilityAIAssistantRouteHandlerResources", + " & { params: { body: { featureIds: string[]; start: string; end: string; } & { filter?: string | undefined; }; }; }) => Promise<{ content: { total: number; alerts: OutputOf<SetOptional<{ readonly \"kibana.alert.risk_score\": { readonly type: \"float\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.author\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.created_at\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.created_by\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.description\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.enabled\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.from\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.interval\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.license\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.note\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.references\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.rule_id\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.rule_name_override\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.to\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.type\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.updated_at\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.updated_by\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.version\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.severity\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.docs_count\": { readonly type: \"long\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.end\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.terms.field\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.suppression.start\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.terms.value\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.system_status\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_reason\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_user\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"ecs.version\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"@timestamp\": { readonly type: \"date\"; readonly required: true; readonly array: false; }; readonly \"event.action\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly tags: { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.rule_type_id\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.consumer\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.execution.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.action_group\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.case_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.duration.us\": { readonly type: \"long\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.end\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.flapping\": { readonly type: \"boolean\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.flapping_history\": { readonly type: \"boolean\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.maintenance_window_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.instance.id\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.last_detected\": { readonly type: \"date\"; readonly required: false; readonly array: false; }; readonly \"kibana.alert.reason\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.category\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.name\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.parameters\": { readonly array: false; readonly type: \"flattened\"; readonly ignore_above: 4096; readonly required: false; }; readonly \"kibana.alert.rule.producer\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.revision\": { readonly type: \"long\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.tags\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.start\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.status\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.time_range\": { readonly type: \"date_range\"; readonly format: \"epoch_millis||strict_date_optional_time\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.url\": { readonly type: \"keyword\"; readonly array: false; readonly index: false; readonly required: false; readonly ignore_above: 2048; }; readonly \"kibana.alert.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.workflow_status\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_tags\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"event.kind\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.space_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: true; }; readonly \"kibana.version\": { readonly type: \"version\"; readonly array: false; readonly required: false; }; }>>[]; }; }>; } & ", + "ObservabilityAIAssistantRouteCreateOptions", + "; \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", ") => Promise<{ ready: boolean; error?: any; deployment_state?: string | undefined; allocation_state?: string | undefined; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -1177,7 +1259,13 @@ "Type", "<boolean, boolean, unknown>; public: ", "Type", - "<boolean, boolean, unknown>; }>; }> | undefined; handler: ({}: ", + "<boolean, boolean, unknown>; labels: ", + "RecordC", + "<", + "StringC", + ", ", + "StringC", + ">; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", " & { params: { body: { id: string; text: ", "Branded", @@ -1189,13 +1277,15 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; }; }; }) => Promise<void>; } & ", + ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; labels: { [x: string]: string; }; }; }; }) => Promise<void>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/recall\": { endpoint: \"POST /internal/observability_ai_assistant/functions/recall\"; params?: ", "TypeC", "<{ body: ", "TypeC", - "<{ query: ", + "<{ queries: ", + "ArrayC", + "<", "BrandC", "<", "StringC", @@ -1207,9 +1297,9 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; }>; }> | undefined; handler: ({}: ", + ">>; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", - " & { params: { body: { query: ", + " & { params: { body: { queries: ", "Branded", "<string, ", { @@ -1219,9 +1309,9 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; }; }; }) => Promise<{ entries: ", + ">[]; }; }; }) => Promise<{ entries: Pick<", "KnowledgeBaseEntry", - "[]; }>; } & ", + ", \"id\" | \"text\">[]; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/elasticsearch\": { endpoint: \"POST /internal/observability_ai_assistant/functions/elasticsearch\"; params?: ", "TypeC", diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 9b7af89b606e3..f2c1ad4099954 100644 --- a/api_docs/observability_a_i_assistant.mdx +++ b/api_docs/observability_a_i_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistant title: "observabilityAIAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistant plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index 5c1c30f656ff8..35299f4069006 100644 --- a/api_docs/observability_onboarding.mdx +++ b/api_docs/observability_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityOnboarding title: "observabilityOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityOnboarding plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityOnboarding'] --- import observabilityOnboardingObj from './observability_onboarding.devdocs.json'; diff --git a/api_docs/observability_shared.mdx b/api_docs/observability_shared.mdx index 383ed4d08c903..bde051c6aef8c 100644 --- a/api_docs/observability_shared.mdx +++ b/api_docs/observability_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityShared title: "observabilityShared" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityShared plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityShared'] --- import observabilitySharedObj from './observability_shared.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 679268d0a085d..8833f6a1ca67b 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index ec5de1385c7d1..9bfdfb272f12a 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,13 +15,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a <br /> public API | Number of teams | |--------------|----------|------------------------| -| 666 | 556 | 39 | +| 668 | 558 | 39 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 72265 | 227 | 61729 | 1491 | +| 72283 | 226 | 61740 | 1491 | ## Plugin Directory @@ -68,6 +68,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibDiscoverEnhancedPluginApi" text="discoverEnhanced"/> | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 35 | 2 | | discoverLogExplorer | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | This plugin exposes and registers Logs+ features. | 0 | 0 | 0 | 0 | | <DocLink id="kibEcsDataQualityDashboardPluginApi" text="ecsDataQualityDashboard"/> | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | APIs used to assess the quality of data in Elasticsearch indexes | 2 | 0 | 0 | 0 | +| <DocLink id="kibElasticAssistantPluginApi" text="elasticAssistant"/> | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | Server APIs for the Elastic AI Assistant | 4 | 0 | 2 | 0 | | <DocLink id="kibEmbeddablePluginApi" text="embeddable"/> | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds embeddables service to Kibana | 542 | 1 | 442 | 7 | | <DocLink id="kibEmbeddableEnhancedPluginApi" text="embeddableEnhanced"/> | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Extends embeddable plugin with more functionality | 14 | 0 | 14 | 0 | | <DocLink id="kibEncryptedSavedObjectsPluginApi" text="encryptedSavedObjects"/> | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides encryption and decryption utilities for saved objects containing sensitive information. | 51 | 0 | 44 | 0 | @@ -106,7 +107,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibHomePluginApi" text="home"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 147 | 0 | 108 | 0 | | <DocLink id="kibImageEmbeddablePluginApi" text="imageEmbeddable"/> | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Image embeddable | 3 | 0 | 3 | 1 | | <DocLink id="kibIndexLifecycleManagementPluginApi" text="indexLifecycleManagement"/> | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 4 | 0 | 4 | 0 | -| <DocLink id="kibIndexManagementPluginApi" text="indexManagement"/> | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 182 | 0 | 177 | 4 | +| <DocLink id="kibIndexManagementPluginApi" text="indexManagement"/> | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 191 | 0 | 186 | 4 | | <DocLink id="kibInfraPluginApi" text="infra"/> | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | This plugin visualizes data from Filebeat and Metricbeat, and integrates with other Observability solutions | 45 | 0 | 42 | 11 | | ingestPipelines | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 0 | 0 | 0 | 0 | | inputControlVis | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds Input Control visualization to Kibana | 0 | 0 | 0 | 0 | @@ -132,6 +133,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibMonitoringCollectionPluginApi" text="monitoringCollection"/> | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | - | 9 | 0 | 9 | 0 | | <DocLink id="kibNavigationPluginApi" text="navigation"/> | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 34 | 0 | 34 | 2 | | <DocLink id="kibNewsfeedPluginApi" text="newsfeed"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 17 | 0 | 17 | 0 | +| <DocLink id="kibNoDataPagePluginApi" text="noDataPage"/> | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 3 | 0 | 3 | 0 | | <DocLink id="kibNotificationsPluginApi" text="notifications"/> | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 1 | | <DocLink id="kibObservabilityPluginApi" text="observability"/> | [@elastic/actionable-observability](https://github.com/orgs/elastic/teams/actionable-observability) | - | 541 | 2 | 532 | 16 | | <DocLink id="kibObservabilityAIAssistantPluginApi" text="observabilityAIAssistant"/> | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 42 | 0 | 39 | 7 | @@ -292,9 +294,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibKbnCoreDocLinksServerMocksPluginApi" text="@kbn/core-doc-links-server-mocks"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 0 | | <DocLink id="kibKbnCoreElasticsearchClientServerInternalPluginApi" text="@kbn/core-elasticsearch-client-server-internal"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 22 | 0 | 13 | 1 | | <DocLink id="kibKbnCoreElasticsearchClientServerMocksPluginApi" text="@kbn/core-elasticsearch-client-server-mocks"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 37 | 1 | 33 | 0 | -| <DocLink id="kibKbnCoreElasticsearchServerPluginApi" text="@kbn/core-elasticsearch-server"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 108 | 0 | 54 | 0 | -| <DocLink id="kibKbnCoreElasticsearchServerInternalPluginApi" text="@kbn/core-elasticsearch-server-internal"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 37 | 0 | 33 | 3 | -| <DocLink id="kibKbnCoreElasticsearchServerMocksPluginApi" text="@kbn/core-elasticsearch-server-mocks"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 15 | 1 | 15 | 0 | +| <DocLink id="kibKbnCoreElasticsearchServerPluginApi" text="@kbn/core-elasticsearch-server"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 111 | 0 | 54 | 0 | +| <DocLink id="kibKbnCoreElasticsearchServerInternalPluginApi" text="@kbn/core-elasticsearch-server-internal"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 38 | 0 | 34 | 3 | +| <DocLink id="kibKbnCoreElasticsearchServerMocksPluginApi" text="@kbn/core-elasticsearch-server-mocks"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 13 | 1 | 13 | 0 | | <DocLink id="kibKbnCoreEnvironmentServerInternalPluginApi" text="@kbn/core-environment-server-internal"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 1 | | <DocLink id="kibKbnCoreEnvironmentServerMocksPluginApi" text="@kbn/core-environment-server-mocks"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 0 | | <DocLink id="kibKbnCoreExecutionContextBrowserPluginApi" text="@kbn/core-execution-context-browser"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 10 | 0 | 2 | 1 | @@ -363,7 +365,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibKbnCoreRenderingServerMocksPluginApi" text="@kbn/core-rendering-server-mocks"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 1 | | <DocLink id="kibKbnCoreRootServerInternalPluginApi" text="@kbn/core-root-server-internal"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 25 | 1 | 24 | 0 | | <DocLink id="kibKbnCoreSavedObjectsApiBrowserPluginApi" text="@kbn/core-saved-objects-api-browser"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 111 | 1 | 0 | 0 | -| <DocLink id="kibKbnCoreSavedObjectsApiServerPluginApi" text="@kbn/core-saved-objects-api-server"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 351 | 1 | 7 | 1 | +| <DocLink id="kibKbnCoreSavedObjectsApiServerPluginApi" text="@kbn/core-saved-objects-api-server"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 351 | 1 | 5 | 1 | | <DocLink id="kibKbnCoreSavedObjectsApiServerMocksPluginApi" text="@kbn/core-saved-objects-api-server-mocks"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 11 | 0 | 11 | 0 | | <DocLink id="kibKbnCoreSavedObjectsBaseServerInternalPluginApi" text="@kbn/core-saved-objects-base-server-internal"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 89 | 0 | 61 | 10 | | <DocLink id="kibKbnCoreSavedObjectsBaseServerMocksPluginApi" text="@kbn/core-saved-objects-base-server-mocks"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 0 | @@ -373,7 +375,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibKbnCoreSavedObjectsCommonPluginApi" text="@kbn/core-saved-objects-common"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 73 | 0 | 40 | 0 | | <DocLink id="kibKbnCoreSavedObjectsImportExportServerInternalPluginApi" text="@kbn/core-saved-objects-import-export-server-internal"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 26 | 0 | 23 | 0 | | <DocLink id="kibKbnCoreSavedObjectsImportExportServerMocksPluginApi" text="@kbn/core-saved-objects-import-export-server-mocks"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 0 | -| <DocLink id="kibKbnCoreSavedObjectsMigrationServerInternalPluginApi" text="@kbn/core-saved-objects-migration-server-internal"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 124 | 0 | 90 | 46 | +| <DocLink id="kibKbnCoreSavedObjectsMigrationServerInternalPluginApi" text="@kbn/core-saved-objects-migration-server-internal"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 125 | 0 | 91 | 46 | | <DocLink id="kibKbnCoreSavedObjectsMigrationServerMocksPluginApi" text="@kbn/core-saved-objects-migration-server-mocks"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 12 | 0 | 12 | 0 | | <DocLink id="kibKbnCoreSavedObjectsServerPluginApi" text="@kbn/core-saved-objects-server"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 548 | 1 | 122 | 4 | | <DocLink id="kibKbnCoreSavedObjectsServerInternalPluginApi" text="@kbn/core-saved-objects-server-internal"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 69 | 0 | 69 | 4 | @@ -521,7 +523,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibKbnRrulePluginApi" text="@kbn/rrule"/> | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 16 | 0 | 16 | 1 | | <DocLink id="kibKbnRuleDataUtilsPluginApi" text="@kbn/rule-data-utils"/> | [@elastic/security-detections-response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 107 | 0 | 104 | 0 | | <DocLink id="kibKbnSavedObjectsSettingsPluginApi" text="@kbn/saved-objects-settings"/> | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 0 | -| <DocLink id="kibKbnSearchApiPanelsPluginApi" text="@kbn/search-api-panels"/> | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 64 | 1 | 64 | 0 | +| <DocLink id="kibKbnSearchApiPanelsPluginApi" text="@kbn/search-api-panels"/> | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 64 | 0 | 64 | 0 | | <DocLink id="kibKbnSearchResponseWarningsPluginApi" text="@kbn/search-response-warnings"/> | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 16 | 0 | 8 | 0 | | <DocLink id="kibKbnSecuritySolutionNavigationPluginApi" text="@kbn/security-solution-navigation"/> | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 50 | 0 | 47 | 0 | | <DocLink id="kibKbnSecuritySolutionSideNavPluginApi" text="@kbn/security-solution-side-nav"/> | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 29 | 0 | 23 | 0 | @@ -588,7 +590,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibKbnSharedUxStorybookConfigPluginApi" text="@kbn/shared-ux-storybook-config"/> | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 0 | 0 | | <DocLink id="kibKbnSharedUxStorybookMockPluginApi" text="@kbn/shared-ux-storybook-mock"/> | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 15 | 0 | 4 | 0 | | <DocLink id="kibKbnSharedUxUtilityPluginApi" text="@kbn/shared-ux-utility"/> | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 9 | 0 | 3 | 0 | -| <DocLink id="kibKbnSloSchemaPluginApi" text="@kbn/slo-schema"/> | [@elastic/actionable-observability](https://github.com/orgs/elastic/teams/actionable-observability) | - | 133 | 0 | 130 | 0 | +| <DocLink id="kibKbnSloSchemaPluginApi" text="@kbn/slo-schema"/> | [@elastic/actionable-observability](https://github.com/orgs/elastic/teams/actionable-observability) | - | 132 | 0 | 129 | 0 | | <DocLink id="kibKbnSomeDevLogPluginApi" text="@kbn/some-dev-log"/> | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 20 | 0 | 12 | 0 | | <DocLink id="kibKbnStdPluginApi" text="@kbn/std"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 102 | 2 | 65 | 1 | | <DocLink id="kibKbnStdioDevHelpersPluginApi" text="@kbn/stdio-dev-helpers"/> | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 4 | 0 | 2 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 9e9d187e99f0c..cdc6fdb4be051 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index 3661f0be02f85..b9e7c8fa13d56 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 79a18388225f3..a1f6c7a297e1a 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index a53247a25e951..8b4a86aeeb456 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 22fd762ce0d5d..0b3598ae263ed 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index c4646d2838f4e..5922688ec3d5f 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index ad6badd31b87f..eafa39a8b1ec8 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 96c0e4200229c..1ba7eadf0ef98 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index 62e42d48bb637..e23535dc14647 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index a5294ce5dc851..98c2613f77c9a 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index cd9f852e66e04..a063eb533b714 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 935d782e0a290..fade576fdfed1 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index 17a5ac41bbb33..15e49ecd643ca 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index d1a17c8e99667..8e3054654149e 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 50e788fdbf4d8..a56afa3ea5eab 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 0cf9f8f2a49c7..436d9fc2a62b3 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index e9b4ad63731a2..5ebed17999232 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -101,7 +101,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly detectionsCoverageOverview: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; readonly protectionUpdatesEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/plugin.tsx", "deprecated": false, @@ -480,7 +480,7 @@ "\nExperimental flag needed to enable the link" ], "signature": [ - "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"alertDetailsPageEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"alertsPageFiltersEnabled\" | \"newUserDetailsFlyout\" | \"detectionsCoverageOverview\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"discoverInTimeline\" | undefined" + "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"alertDetailsPageEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"alertsPageFiltersEnabled\" | \"newUserDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"discoverInTimeline\" | \"protectionUpdatesEnabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -560,7 +560,7 @@ "\nExperimental flag needed to disable the link. Opposite of experimentalKey" ], "signature": [ - "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"alertDetailsPageEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"alertsPageFiltersEnabled\" | \"newUserDetailsFlyout\" | \"detectionsCoverageOverview\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"discoverInTimeline\" | undefined" + "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"alertDetailsPageEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"alertsPageFiltersEnabled\" | \"newUserDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"discoverInTimeline\" | \"protectionUpdatesEnabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -3019,7 +3019,7 @@ "label": "ExperimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly detectionsCoverageOverview: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; readonly protectionUpdatesEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, @@ -3089,7 +3089,7 @@ "\nA list of allowed values that can be used in `xpack.securitySolution.enableExperimental`.\nThis object is then used to validate and parse the value entered." ], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly detectionsCoverageOverview: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; readonly protectionUpdatesEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 07327a83ece61..41c7553e1292c 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index 4611939fe8167..34e38e14067dd 100644 --- a/api_docs/security_solution_ess.mdx +++ b/api_docs/security_solution_ess.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionEss title: "securitySolutionEss" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionEss plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionEss'] --- import securitySolutionEssObj from './security_solution_ess.devdocs.json'; diff --git a/api_docs/security_solution_serverless.mdx b/api_docs/security_solution_serverless.mdx index b48883227f8e6..e5e61401fc375 100644 --- a/api_docs/security_solution_serverless.mdx +++ b/api_docs/security_solution_serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionServerless title: "securitySolutionServerless" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionServerless plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionServerless'] --- import securitySolutionServerlessObj from './security_solution_serverless.devdocs.json'; diff --git a/api_docs/serverless.mdx b/api_docs/serverless.mdx index 8b33bc3230e99..cd2b74a76fdf9 100644 --- a/api_docs/serverless.mdx +++ b/api_docs/serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverless title: "serverless" image: https://source.unsplash.com/400x175/?github description: API docs for the serverless plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverless'] --- import serverlessObj from './serverless.devdocs.json'; diff --git a/api_docs/serverless_observability.mdx b/api_docs/serverless_observability.mdx index d7daf23a20a6f..651a305fafd4c 100644 --- a/api_docs/serverless_observability.mdx +++ b/api_docs/serverless_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessObservability title: "serverlessObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessObservability plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessObservability'] --- import serverlessObservabilityObj from './serverless_observability.devdocs.json'; diff --git a/api_docs/serverless_search.mdx b/api_docs/serverless_search.mdx index 9a3d8b1b2ab14..f02a9caaafbe1 100644 --- a/api_docs/serverless_search.mdx +++ b/api_docs/serverless_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessSearch title: "serverlessSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessSearch plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessSearch'] --- import serverlessSearchObj from './serverless_search.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index aa8fb52c9d3b0..b9480241e7352 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index ac0cccd2adfce..1ee73c2a226e6 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index a481bc695f2ad..c8ca4eca7cce4 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 0ebfed1192228..deb0f1803fa38 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index 8dfc7a76db728..6f64356d89cea 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 167c3f2ae6129..b9dcc1d398047 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 688089acc6d5f..892313b66db13 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index da7dcbe2546ec..9026cd46b9b65 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index a171af464f0e4..d73c7d6246bbd 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 8898b48a648fe..5e0a86eb22bfb 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 72bd0937044b8..000818037c4e2 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/text_based_languages.mdx b/api_docs/text_based_languages.mdx index 59807b0f6bfa6..d59e94ecd47ed 100644 --- a/api_docs/text_based_languages.mdx +++ b/api_docs/text_based_languages.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/textBasedLanguages title: "textBasedLanguages" image: https://source.unsplash.com/400x175/?github description: API docs for the textBasedLanguages plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'textBasedLanguages'] --- import textBasedLanguagesObj from './text_based_languages.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 97fbd6d87a35d..f94df2ae0551f 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.devdocs.json b/api_docs/timelines.devdocs.json index bca1001561f09..a6c77777588d2 100644 --- a/api_docs/timelines.devdocs.json +++ b/api_docs/timelines.devdocs.json @@ -4591,119 +4591,119 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/empty.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/overview/index.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/empty.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/overview/index.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_source_event.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_source_event.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_session.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_session.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/insights.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/insights.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/overview/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/overview/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_source_event.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_source_event.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_session.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_session.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/insights.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/insights.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/empty.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/empty.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/index.tsx" }, { "plugin": "securitySolution", @@ -4727,27 +4727,27 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" + "path": "x-pack/plugins/security_solution/public/flyout/right/context.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" + "path": "x-pack/plugins/security_solution/public/flyout/right/context.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/flyout/right/context.tsx" + "path": "x-pack/plugins/security_solution/public/flyout/left/context.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/flyout/right/context.tsx" + "path": "x-pack/plugins/security_solution/public/flyout/left/context.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/flyout/left/context.tsx" + "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/flyout/left/context.tsx" + "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" }, { "plugin": "@kbn/securitysolution-data-table", diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index c8dcc87ed8e56..db9408698ada4 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index a8a64b67f98cf..c5c72936b736f 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 7d45856119d21..a87bb62ead45a 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 829f7ce6cb4e9..2918437a402fa 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index a4bcd288b21ae..e3f159118cf9c 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 4c27a5fd878ea..50929095b7b86 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index c7f9c3fc72779..2af9c4d1aee5a 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index 126d2216474a3..abbd20438c48c 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/uptime.mdx b/api_docs/uptime.mdx index cd213fb77faef..2c463d45f48b3 100644 --- a/api_docs/uptime.mdx +++ b/api_docs/uptime.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uptime title: "uptime" image: https://source.unsplash.com/400x175/?github description: API docs for the uptime plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uptime'] --- import uptimeObj from './uptime.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index ab1ac62bd115b..595e139f1e17c 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 34bda30635762..91bde275ef5b2 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index 5387d08ff66fa..bc82604a8e09d 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index af898492cb68e..d789cfa9d6ddd 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index 846b481b72a60..b7fbc17a2559b 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 48552ad33a02a..e58463315b9c5 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index 7d75a8bea6854..6501a0fb4648e 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 887c7162168bf..d4313e88fa7ac 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 18b79e475f91e..f59755691b08d 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index 568224480bbf6..05e3730a4d31a 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 17df71793f6a8..b103c87abbb3c 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index 4d3ba5f0554cc..0b3e8fc1048ed 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index ee2f8ed47c901..420f95794b21e 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 7459f49a6d2ff..2f2b9042c4947 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2023-08-28 +date: 2023-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 299407da6aec9a1c92eba09304393dd4c6349e21 Mon Sep 17 00:00:00 2001 From: Thom Heymann <190132+thomheymann@users.noreply.github.com> Date: Tue, 29 Aug 2023 08:08:08 +0100 Subject: [PATCH 43/49] Add functional tests for serverless security management UIs (#164886) --- .../functional/page_objects/api_keys_page.ts | 2 +- .../test_suites/common/management.ts | 12 + .../test_suites/common/security/api_keys.ts | 457 ++++++++++++++++++ 3 files changed, 470 insertions(+), 1 deletion(-) create mode 100644 x-pack/test_serverless/functional/test_suites/common/security/api_keys.ts 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 23f63c87107fa..0875774470018 100644 --- a/x-pack/test/functional/page_objects/api_keys_page.ts +++ b/x-pack/test/functional/page_objects/api_keys_page.ts @@ -66,7 +66,7 @@ export function ApiKeysPageProvider({ getService }: FtrProviderContext) { }, async isApiKeyModalExists() { - return await find.existsByCssSelector('[role="dialog"]'); + return await find.existsByCssSelector('.euiFlyoutHeader'); }, async getNewApiKeyCreation() { diff --git a/x-pack/test_serverless/functional/test_suites/common/management.ts b/x-pack/test_serverless/functional/test_suites/common/management.ts index 504325ff363b1..fe2561854c49a 100644 --- a/x-pack/test_serverless/functional/test_suites/common/management.ts +++ b/x-pack/test_serverless/functional/test_suites/common/management.ts @@ -54,6 +54,18 @@ export default function ({ getPageObject, getService }: FtrProviderContext) { appName: 'Watcher', url: 'insightsAndAlerting/watcher', }, + { + appName: 'Users', + url: 'security/users', + }, + { + appName: 'Roles', + url: 'security/roles', + }, + { + appName: 'Role Mappings', + url: 'security/role_mappings', + }, ]; DISABLED_PLUGINS.forEach(({ appName, url }) => { diff --git a/x-pack/test_serverless/functional/test_suites/common/security/api_keys.ts b/x-pack/test_serverless/functional/test_suites/common/security/api_keys.ts new file mode 100644 index 0000000000000..ab650c4c43a25 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/common/security/api_keys.ts @@ -0,0 +1,457 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { Client } from '@elastic/elasticsearch'; +import { ToolingLog } from '@kbn/tooling-log'; +import type { estypes } from '@elastic/elasticsearch'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +async function clearAllApiKeys(esClient: Client, logger: ToolingLog) { + const existingKeys = await esClient.security.queryApiKeys(); + if (existingKeys.count > 0) { + await Promise.all( + existingKeys.api_keys.map(async (key) => { + esClient.security.invalidateApiKey({ ids: [key.id] }); + }) + ); + } else { + logger.debug('No API keys to delete.'); + } +} + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const es = getService('es'); + const pageObjects = getPageObjects(['common', 'apiKeys']); + const log = getService('log'); + const security = getService('security'); + const testSubjects = getService('testSubjects'); + const find = getService('find'); + const browser = getService('browser'); + const retry = getService('retry'); + + const testRoles: Record<string, any> = { + viewer: { + cluster: ['all'], + indices: [ + { + names: ['*'], + privileges: ['all'], + allow_restricted_indices: false, + }, + { + names: ['*'], + privileges: ['monitor', 'read', 'view_index_metadata', 'read_cross_cluster'], + allow_restricted_indices: true, + }, + ], + run_as: ['*'], + }, + }; + + const otherUser: estypes.SecurityPutUserRequest = { + username: 'other_user', + password: 'changeme', + roles: ['superuser'], + }; + + async function ensureApiKeysExist(apiKeysNames: string[]) { + await retry.try(async () => { + for (const apiKeyName of apiKeysNames) { + log.debug(`Checking if API key ("${apiKeyName}") exists.`); + await pageObjects.apiKeys.ensureApiKeyExists(apiKeyName); + log.debug(`API key ("${apiKeyName}") exists.`); + } + }); + } + + describe('Home page', function () { + before(async () => { + await clearAllApiKeys(es, log); + await security.testUser.setRoles(['kibana_admin']); + await es.security.putUser(otherUser); + + await pageObjects.common.navigateToUrl('management', 'security/api_keys', { + shouldUseHashForSubUrl: false, + }); + }); + + after(async () => { + await es.security.deleteUser({ username: otherUser.username }); + await security.testUser.restoreDefaults(); + }); + + // https://www.elastic.co/guide/en/kibana/7.6/api-keys.html#api-keys-security-privileges + it('Hides management link if user is not authorized', async () => { + await testSubjects.missingOrFail('apiKeys'); + }); + + it('Loads the app', async () => { + await security.testUser.setRoles(['test_api_keys']); + log.debug('Checking for Create API key call to action'); + await find.existsByLinkText('Create API key'); + }); + + describe('creates API key', function () { + before(async () => { + await security.testUser.setRoles(['kibana_admin', 'test_api_keys']); + await pageObjects.common.navigateToUrl('management', 'security/api_keys', { + shouldUseHashForSubUrl: false, + }); + + // Delete any API keys created outside of these tests + await pageObjects.apiKeys.bulkDeleteApiKeys(); + }); + + afterEach(async () => { + await pageObjects.apiKeys.deleteAllApiKeyOneByOne(); + }); + + after(async () => { + await clearAllApiKeys(es, log); + }); + + it('when submitting form, close dialog and displays new api key', async () => { + const apiKeyName = 'Happy API Key'; + await pageObjects.apiKeys.clickOnPromptCreateApiKey(); + expect(await browser.getCurrentUrl()).to.contain('app/management/security/api_keys/create'); + expect(await pageObjects.apiKeys.getFlyoutTitleText()).to.be('Create API key'); + + await pageObjects.apiKeys.setApiKeyName(apiKeyName); + await pageObjects.apiKeys.clickSubmitButtonOnApiKeyFlyout(); + const newApiKeyCreation = await pageObjects.apiKeys.getNewApiKeyCreation(); + + expect(await browser.getCurrentUrl()).to.not.contain( + 'app/management/security/api_keys/flyout' + ); + expect(await browser.getCurrentUrl()).to.contain('app/management/security/api_keys'); + expect(await pageObjects.apiKeys.isApiKeyModalExists()).to.be(false); + expect(newApiKeyCreation).to.be(`Created API key '${apiKeyName}'`); + }); + + it('with optional expiration, redirects back and displays base64', async () => { + const apiKeyName = 'Happy expiration API key'; + await pageObjects.apiKeys.clickOnPromptCreateApiKey(); + expect(await browser.getCurrentUrl()).to.contain('app/management/security/api_keys/create'); + + await pageObjects.apiKeys.setApiKeyName(apiKeyName); + await pageObjects.apiKeys.toggleCustomExpiration(); + await pageObjects.apiKeys.setApiKeyCustomExpiration('12'); + await pageObjects.apiKeys.clickSubmitButtonOnApiKeyFlyout(); + const newApiKeyCreation = await pageObjects.apiKeys.getNewApiKeyCreation(); + + expect(await browser.getCurrentUrl()).to.not.contain( + 'app/management/security/api_keys/create' + ); + expect(await browser.getCurrentUrl()).to.contain('app/management/security/api_keys'); + expect(await pageObjects.apiKeys.isApiKeyModalExists()).to.be(false); + expect(newApiKeyCreation).to.be(`Created API key '${apiKeyName}'`); + }); + }); + + describe('Update API key', function () { + before(async () => { + await security.testUser.setRoles(['kibana_admin', 'test_api_keys']); + await pageObjects.common.navigateToUrl('management', 'security/api_keys', { + shouldUseHashForSubUrl: false, + }); + + // Delete any API keys created outside these tests + await pageObjects.apiKeys.bulkDeleteApiKeys(); + }); + + afterEach(async () => { + await pageObjects.apiKeys.deleteAllApiKeyOneByOne(); + }); + + after(async () => { + await clearAllApiKeys(es, log); + }); + + it('should create a new API key, click the name of the new row, fill out and submit form, and display success message', async () => { + // Create a key to updated + const apiKeyName = 'Happy API Key to Update'; + + await es.security.grantApiKey({ + api_key: { + name: apiKeyName, + expiration: '1d', + }, + grant_type: 'password', + run_as: 'elastic', + username: 'elastic', + password: 'changeme', + }); + + await browser.refresh(); + + log.debug('API key created, moving on to update'); + + // Update newly created API Key + await pageObjects.apiKeys.clickExistingApiKeyToOpenFlyout(apiKeyName); + + expect(await browser.getCurrentUrl()).to.contain('app/management/security/api_keys'); + + await pageObjects.apiKeys.waitForSubmitButtonOnApiKeyFlyoutEnabled(); + + expect(await pageObjects.apiKeys.getFlyoutTitleText()).to.be('Update API key'); + + // Verify name input box are disabled + const apiKeyNameInput = await pageObjects.apiKeys.getApiKeyName(); + expect(await apiKeyNameInput.isEnabled()).to.be(false); + + // Status should be displayed + const apiKeyStatus = await pageObjects.apiKeys.getFlyoutApiKeyStatus(); + expect(await apiKeyStatus).to.be('Expires in a day'); + + // Verify metadata is editable + const apiKeyMetadataSwitch = await pageObjects.apiKeys.getMetadataSwitch(); + expect(await apiKeyMetadataSwitch.isEnabled()).to.be(true); + + // Verify restrict privileges is editable + const apiKeyRestrictPrivilegesSwitch = + await pageObjects.apiKeys.getRestrictPrivilegesSwitch(); + expect(await apiKeyRestrictPrivilegesSwitch.isEnabled()).to.be(true); + + // Toggle restrict privileges so the code editor shows up + await apiKeyRestrictPrivilegesSwitch.click(); + + // Toggle metadata switch so the code editor shows up + await apiKeyMetadataSwitch.click(); + + // Check default value of metadata and set value + const restrictPrivilegesCodeEditorValue = + await pageObjects.apiKeys.getCodeEditorValueByIndex(0); + expect(restrictPrivilegesCodeEditorValue).to.be('{}'); + + // Check default value of metadata and set value + const metadataCodeEditorValue = await pageObjects.apiKeys.getCodeEditorValueByIndex(1); + expect(metadataCodeEditorValue).to.be('{}'); + + await pageObjects.apiKeys.setCodeEditorValueByIndex(0, JSON.stringify(testRoles)); + + await pageObjects.apiKeys.setCodeEditorValueByIndex(1, '{"name":"metadataTest"}'); + + // Submit values to update API key + await pageObjects.apiKeys.clickSubmitButtonOnApiKeyFlyout(); + + // Get success message + const updatedApiKeyToastText = await pageObjects.apiKeys.getApiKeyUpdateSuccessToast(); + expect(updatedApiKeyToastText).to.be(`Updated API key '${apiKeyName}'`); + + expect(await browser.getCurrentUrl()).to.contain('app/management/security/api_keys'); + expect(await pageObjects.apiKeys.isApiKeyModalExists()).to.be(false); + }); + }); + + describe('Readonly API key', function () { + before(async () => { + await security.role.create('read_security_role', { + elasticsearch: { + cluster: ['read_security'], + }, + kibana: [ + { + feature: { + infrastructure: ['read'], + }, + spaces: ['*'], + }, + ], + }); + + await security.testUser.setRoles(['kibana_admin', 'test_api_keys']); + await pageObjects.common.navigateToUrl('management', 'security/api_keys', { + shouldUseHashForSubUrl: false, + }); + + // Delete any API keys created outside these tests + await pageObjects.apiKeys.bulkDeleteApiKeys(); + }); + + afterEach(async () => { + await pageObjects.apiKeys.deleteAllApiKeyOneByOne(); + }); + + after(async () => { + await clearAllApiKeys(es, log); + }); + + // Serverless tests run as elastic (superuser) so unable to test `read_security` permissions + it.skip('should see readonly form elements', async () => { + // Create a key to updated + const apiKeyName = 'Happy API Key to View'; + + await es.security.grantApiKey({ + api_key: { + name: apiKeyName, + expiration: '1d', + metadata: { name: 'metadatatest' }, + role_descriptors: { ...testRoles }, + }, + grant_type: 'password', + run_as: 'elastic', + username: 'elastic', + password: 'changeme', + }); + + await browser.refresh(); + + log.debug('API key created, moving on to view'); + + // Set testUsers roles to have the `read_security` cluster privilege + await security.testUser.setRoles(['read_security_role']); + + // View newly created API Key + await pageObjects.apiKeys.clickExistingApiKeyToOpenFlyout(apiKeyName); + expect(await browser.getCurrentUrl()).to.contain('app/management/security/api_keys'); + expect(await pageObjects.apiKeys.getFlyoutTitleText()).to.be('API key details'); + + // Verify name input box are disabled + const apiKeyNameInput = await pageObjects.apiKeys.getApiKeyName(); + expect(await apiKeyNameInput.isEnabled()).to.be(false); + + // Status should be displayed + const apiKeyStatus = await pageObjects.apiKeys.getFlyoutApiKeyStatus(); + expect(await apiKeyStatus).to.be('Expires in a day'); + + const apiKeyMetadataSwitch = await pageObjects.apiKeys.getMetadataSwitch(); + const apiKeyRestrictPrivilegesSwitch = + await pageObjects.apiKeys.getRestrictPrivilegesSwitch(); + + // Verify metadata and restrict privileges switches are now disabled + expect(await apiKeyMetadataSwitch.isEnabled()).to.be(false); + expect(await apiKeyRestrictPrivilegesSwitch.isEnabled()).to.be(false); + + // Close flyout with cancel + await pageObjects.apiKeys.clickCancelButtonOnApiKeyFlyout(); + + // Undo `read_security_role` + await security.testUser.setRoles(['kibana_admin', 'test_api_keys']); + }); + + it('should show the `API key details` flyout if the expiration date is passed', async () => { + const apiKeyName = 'expired-key'; + + await es.security.grantApiKey({ + api_key: { + name: apiKeyName, + expiration: '1ms', + }, + grant_type: 'password', + run_as: 'elastic', + username: 'elastic', + password: 'changeme', + }); + + await browser.refresh(); + + log.debug('API key created, moving on to view'); + + await pageObjects.apiKeys.clickExistingApiKeyToOpenFlyout(apiKeyName); + + expect(await browser.getCurrentUrl()).to.contain('app/management/security/api_keys'); + expect(await pageObjects.apiKeys.getFlyoutTitleText()).to.be('API key details'); + + // Verify name input box are disabled + const apiKeyNameInput = await pageObjects.apiKeys.getApiKeyName(); + expect(await apiKeyNameInput.isEnabled()).to.be(false); + + // Status should be displayed + const apiKeyStatus = await pageObjects.apiKeys.getFlyoutApiKeyStatus(); + expect(await apiKeyStatus).to.be('Expired'); + + const apiKeyMetadataSwitch = await pageObjects.apiKeys.getMetadataSwitch(); + const apiKeyRestrictPrivilegesSwitch = + await pageObjects.apiKeys.getRestrictPrivilegesSwitch(); + + // Verify metadata and restrict privileges switches are now disabled + expect(await apiKeyMetadataSwitch.isEnabled()).to.be(false); + expect(await apiKeyRestrictPrivilegesSwitch.isEnabled()).to.be(false); + + await pageObjects.apiKeys.clickCancelButtonOnApiKeyFlyout(); + }); + + it('should show the `API key details flyout` if the API key does not belong to the user', async () => { + const apiKeyName = 'other-key'; + + await es.security.grantApiKey({ + api_key: { + name: apiKeyName, + }, + grant_type: 'password', + run_as: otherUser.username, + username: 'elastic', + password: 'changeme', + }); + + await browser.refresh(); + + log.debug('API key created, moving on to view'); + + await pageObjects.apiKeys.clickExistingApiKeyToOpenFlyout(apiKeyName); + expect(await browser.getCurrentUrl()).to.contain('app/management/security/api_keys'); + expect(await pageObjects.apiKeys.getFlyoutTitleText()).to.be('API key details'); + + // Verify name input box are disabled + const apiKeyNameInput = await pageObjects.apiKeys.getApiKeyName(); + expect(await apiKeyNameInput.isEnabled()).to.be(false); + + // Status should be displayed + const apiKeyStatus = await pageObjects.apiKeys.getFlyoutApiKeyStatus(); + expect(await apiKeyStatus).to.be('Active'); + + const apiKeyMetadataSwitch = await pageObjects.apiKeys.getMetadataSwitch(); + const apiKeyRestrictPrivilegesSwitch = + await pageObjects.apiKeys.getRestrictPrivilegesSwitch(); + + // Verify metadata and restrict privileges switches are now disabled + expect(await apiKeyMetadataSwitch.isEnabled()).to.be(false); + expect(await apiKeyRestrictPrivilegesSwitch.isEnabled()).to.be(false); + + await pageObjects.apiKeys.clickCancelButtonOnApiKeyFlyout(); + }); + }); + + describe('deletes API key(s)', function () { + before(async () => { + await security.testUser.setRoles(['kibana_admin', 'test_api_keys']); + await pageObjects.common.navigateToUrl('management', 'security/api_keys', { + shouldUseHashForSubUrl: false, + }); + }); + + beforeEach(async () => { + await pageObjects.apiKeys.clickOnPromptCreateApiKey(); + await pageObjects.apiKeys.setApiKeyName('api key 1'); + await pageObjects.apiKeys.clickSubmitButtonOnApiKeyFlyout(); + await ensureApiKeysExist(['api key 1']); + }); + + it('one by one', async () => { + await pageObjects.apiKeys.deleteAllApiKeyOneByOne(); + expect(await pageObjects.apiKeys.getApiKeysFirstPromptTitle()).to.be( + 'Create your first API key' + ); + }); + + it('by bulk', async () => { + await pageObjects.apiKeys.clickOnTableCreateApiKey(); + await pageObjects.apiKeys.setApiKeyName('api key 2'); + await pageObjects.apiKeys.clickSubmitButtonOnApiKeyFlyout(); + + // Make sure all API keys we want to delete are created and rendered. + await ensureApiKeysExist(['api key 1', 'api key 2']); + + await pageObjects.apiKeys.bulkDeleteApiKeys(); + expect(await pageObjects.apiKeys.getApiKeysFirstPromptTitle()).to.be( + 'Create your first API key' + ); + }); + }); + }); +}; From 34c7a03016138cc1bae8296e1bb25bf4e73a8f4d Mon Sep 17 00:00:00 2001 From: Philippe Oberti <philippe.oberti@elastic.co> Date: Tue, 29 Aug 2023 09:54:40 +0200 Subject: [PATCH 44/49] [Security Solution] expandable flyout - add no data message in entities details and entities overview components (#164955) --- .../left/components/entities_details.test.tsx | 15 ++-- .../left/components/entities_details.tsx | 35 ++++++---- .../public/flyout/left/components/test_ids.ts | 1 + .../flyout/left/components/translations.ts | 7 ++ .../components/entities_overview.test.tsx | 70 ++++++++++++++----- .../right/components/entities_overview.tsx | 36 +++++----- .../flyout/right/components/test_ids.ts | 1 + .../flyout/right/components/translations.ts | 7 ++ 8 files changed, 121 insertions(+), 51 deletions(-) diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.test.tsx index d02f84207ecde..eb56069bb7646 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.test.tsx @@ -11,7 +11,12 @@ import '@testing-library/jest-dom'; import { LeftPanelContext } from '../context'; import { TestProviders } from '../../../common/mock'; import { EntitiesDetails } from './entities_details'; -import { ENTITIES_DETAILS_TEST_ID, HOST_DETAILS_TEST_ID, USER_DETAILS_TEST_ID } from './test_ids'; +import { + ENTITIES_DETAILS_NO_DATA_TEST_ID, + ENTITIES_DETAILS_TEST_ID, + HOST_DETAILS_TEST_ID, + USER_DETAILS_TEST_ID, +} from './test_ids'; import { mockContextValue } from '../mocks/mock_context'; import { EXPANDABLE_PANEL_CONTENT_TEST_ID } from '../../shared/components/test_ids'; @@ -49,8 +54,8 @@ describe('<EntitiesDetails />', () => { expect(getByTestId(HOST_TEST_ID)).toBeInTheDocument(); }); - it('does not render user and host details if user name and host name are not available', () => { - const { queryByTestId } = render( + it('should render no data message if user name and host name are not available', () => { + const { getByTestId, queryByTestId } = render( <TestProviders> <LeftPanelContext.Provider value={{ @@ -63,12 +68,13 @@ describe('<EntitiesDetails />', () => { </LeftPanelContext.Provider> </TestProviders> ); + expect(getByTestId(ENTITIES_DETAILS_NO_DATA_TEST_ID)).toBeInTheDocument(); expect(queryByTestId(USER_TEST_ID)).not.toBeInTheDocument(); expect(queryByTestId(HOST_TEST_ID)).not.toBeInTheDocument(); }); it('does not render user and host details if @timestamp is not available', () => { - const { queryByTestId } = render( + const { getByTestId, queryByTestId } = render( <TestProviders> <LeftPanelContext.Provider value={{ @@ -89,6 +95,7 @@ describe('<EntitiesDetails />', () => { </LeftPanelContext.Provider> </TestProviders> ); + expect(getByTestId(ENTITIES_DETAILS_NO_DATA_TEST_ID)).toBeInTheDocument(); expect(queryByTestId(USER_TEST_ID)).not.toBeInTheDocument(); expect(queryByTestId(HOST_TEST_ID)).not.toBeInTheDocument(); }); diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx b/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx index 29e748dd70eae..ff3678a06e428 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx @@ -7,11 +7,12 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { ENTITIES_NO_DATA_MESSAGE } from './translations'; import { useLeftPanelContext } from '../context'; import { getField } from '../../shared/utils'; import { UserDetails } from './user_details'; import { HostDetails } from './host_details'; -import { ENTITIES_DETAILS_TEST_ID } from './test_ids'; +import { ENTITIES_DETAILS_NO_DATA_TEST_ID, ENTITIES_DETAILS_TEST_ID } from './test_ids'; export const ENTITIES_TAB_ID = 'entities-details'; @@ -24,19 +25,29 @@ export const EntitiesDetails: React.FC = () => { const userName = getField(getFieldsData('user.name')); const timestamp = getField(getFieldsData('@timestamp')); + const showDetails = timestamp && (hostName || userName); + const showUserDetails = userName && timestamp; + const showHostDetails = hostName && timestamp; + return ( - <EuiFlexGroup direction="column" gutterSize="m" data-test-subj={ENTITIES_DETAILS_TEST_ID}> - {userName && timestamp && ( - <EuiFlexItem> - <UserDetails userName={userName} timestamp={timestamp} scopeId={scopeId} /> - </EuiFlexItem> - )} - {hostName && timestamp && ( - <EuiFlexItem> - <HostDetails hostName={hostName} timestamp={timestamp} scopeId={scopeId} /> - </EuiFlexItem> + <> + {showDetails ? ( + <EuiFlexGroup direction="column" gutterSize="m" data-test-subj={ENTITIES_DETAILS_TEST_ID}> + {showUserDetails && ( + <EuiFlexItem> + <UserDetails userName={userName} timestamp={timestamp} scopeId={scopeId} /> + </EuiFlexItem> + )} + {showHostDetails && ( + <EuiFlexItem> + <HostDetails hostName={hostName} timestamp={timestamp} scopeId={scopeId} /> + </EuiFlexItem> + )} + </EuiFlexGroup> + ) : ( + <div data-test-subj={ENTITIES_DETAILS_NO_DATA_TEST_ID}>{ENTITIES_NO_DATA_MESSAGE}</div> )} - </EuiFlexGroup> + </> ); }; diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/left/components/test_ids.ts index 6c736770544bd..03b768607c20c 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/components/test_ids.ts +++ b/x-pack/plugins/security_solution/public/flyout/left/components/test_ids.ts @@ -42,6 +42,7 @@ export const PREVALENCE_DETAILS_TABLE_NO_DATA_TEST_ID = /* Entities */ export const ENTITIES_DETAILS_TEST_ID = `${PREFIX}EntitiesDetails` as const; +export const ENTITIES_DETAILS_NO_DATA_TEST_ID = `${ENTITIES_DETAILS_TEST_ID}NoData` as const; export const USER_DETAILS_TEST_ID = `${PREFIX}UsersDetails` as const; export const USER_DETAILS_INFO_TEST_ID = 'user-overview'; export const USER_DETAILS_RELATED_HOSTS_TABLE_TEST_ID = diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/translations.ts b/x-pack/plugins/security_solution/public/flyout/left/components/translations.ts index dbd0cd21e129c..9e7cf56db7c05 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/components/translations.ts +++ b/x-pack/plugins/security_solution/public/flyout/left/components/translations.ts @@ -7,6 +7,13 @@ import { i18n } from '@kbn/i18n'; +export const ENTITIES_NO_DATA_MESSAGE = i18n.translate( + 'xpack.securitySolution.flyout.entitiesNoDataMessage', + { + defaultMessage: 'No user or host data available', + } +); + export const ANALYZER_ERROR_MESSAGE = i18n.translate( 'xpack.securitySolution.flyout.analyzerErrorMessage', { diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.test.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.test.tsx index d26a93262fa31..528b839bb218c 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.test.tsx @@ -11,6 +11,7 @@ import { RightPanelContext } from '../context'; import { ENTITIES_HOST_OVERVIEW_TEST_ID, ENTITIES_USER_OVERVIEW_TEST_ID, + INSIGHTS_ENTITIES_NO_DATA_TEST_ID, INSIGHTS_ENTITIES_TEST_ID, } from './test_ids'; import { EntitiesOverview } from './entities_overview'; @@ -28,16 +29,18 @@ const TITLE_LINK_TEST_ID = EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID(INSIGHTS_E const TITLE_ICON_TEST_ID = EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID(INSIGHTS_ENTITIES_TEST_ID); const TITLE_TEXT_TEST_ID = EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID(INSIGHTS_ENTITIES_TEST_ID); +const mockContextValue = { + eventId: 'event id', + indexName: 'index', + scopeId: 'scopeId', + getFieldsData: mockGetFieldsData, +} as unknown as RightPanelContext; + describe('<EntitiesOverview />', () => { it('should render wrapper component', () => { - const contextValue = { - eventId: 'event id', - getFieldsData: mockGetFieldsData, - } as unknown as RightPanelContext; - const { getByTestId, queryByTestId } = render( <TestProviders> - <RightPanelContext.Provider value={contextValue}> + <RightPanelContext.Provider value={mockContextValue}> <EntitiesOverview /> </RightPanelContext.Provider> </TestProviders> @@ -51,14 +54,9 @@ describe('<EntitiesOverview />', () => { }); it('should render user and host', () => { - const contextValue = { - eventId: 'event id', - getFieldsData: mockGetFieldsData, - } as unknown as RightPanelContext; - const { getByTestId } = render( <TestProviders> - <RightPanelContext.Provider value={contextValue}> + <RightPanelContext.Provider value={mockContextValue}> <EntitiesOverview /> </RightPanelContext.Provider> </TestProviders> @@ -69,7 +67,7 @@ describe('<EntitiesOverview />', () => { it('should only render user when host name is null', () => { const contextValue = { - eventId: 'event id', + ...mockContextValue, getFieldsData: (field: string) => (field === 'user.name' ? 'user1' : null), } as unknown as RightPanelContext; @@ -87,7 +85,7 @@ describe('<EntitiesOverview />', () => { it('should only render host when user name is null', () => { const contextValue = { - eventId: 'event id', + ...mockContextValue, getFieldsData: (field: string) => (field === 'host.name' ? 'host1' : null), } as unknown as RightPanelContext; @@ -103,13 +101,13 @@ describe('<EntitiesOverview />', () => { expect(queryByTestId(ENTITIES_USER_OVERVIEW_TEST_ID)).not.toBeInTheDocument(); }); - it('should not render if both host name and user name are null/blank', () => { + it('should render no data message if both host name and user name are null/blank', () => { const contextValue = { - eventId: 'event id', + ...mockContextValue, getFieldsData: (field: string) => {}, } as unknown as RightPanelContext; - const { container } = render( + const { queryByTestId } = render( <TestProviders> <RightPanelContext.Provider value={contextValue}> <EntitiesOverview /> @@ -117,13 +115,47 @@ describe('<EntitiesOverview />', () => { </TestProviders> ); - expect(container).toBeEmptyDOMElement(); + expect(queryByTestId(INSIGHTS_ENTITIES_NO_DATA_TEST_ID)).toBeInTheDocument(); }); it('should not render if eventId is null', () => { const contextValue = { + ...mockContextValue, eventId: null, - getFieldsData: (field: string) => {}, + } as unknown as RightPanelContext; + + const { container } = render( + <TestProviders> + <RightPanelContext.Provider value={contextValue}> + <EntitiesOverview /> + </RightPanelContext.Provider> + </TestProviders> + ); + + expect(container).toBeEmptyDOMElement(); + }); + + it('should not render if indexName is null', () => { + const contextValue = { + ...mockContextValue, + indexName: null, + } as unknown as RightPanelContext; + + const { container } = render( + <TestProviders> + <RightPanelContext.Provider value={contextValue}> + <EntitiesOverview /> + </RightPanelContext.Provider> + </TestProviders> + ); + + expect(container).toBeEmptyDOMElement(); + }); + + it('should not render if scopeId is null', () => { + const contextValue = { + ...mockContextValue, + scopeId: null, } as unknown as RightPanelContext; const { container } = render( diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.tsx index d74fd844ea4a9..efab7fa9f6d03 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.tsx @@ -8,10 +8,10 @@ import React, { useCallback } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { useExpandableFlyoutContext } from '@kbn/expandable-flyout'; +import { INSIGHTS_ENTITIES_NO_DATA_TEST_ID, INSIGHTS_ENTITIES_TEST_ID } from './test_ids'; import { ExpandablePanel } from '../../shared/components/expandable_panel'; import { useRightPanelContext } from '../context'; -import { INSIGHTS_ENTITIES_TEST_ID } from './test_ids'; -import { ENTITIES_TITLE } from './translations'; +import { ENTITIES_NO_DATA_MESSAGE, ENTITIES_TITLE } from './translations'; import { getField } from '../../shared/utils'; import { HostEntityOverview } from './host_entity_overview'; import { UserEntityOverview } from './user_entity_overview'; @@ -42,7 +42,7 @@ export const EntitiesOverview: React.FC = () => { }); }, [eventId, openLeftPanel, indexName, scopeId]); - if (!eventId || (!userName && !hostName)) { + if (!eventId || !indexName || !scopeId) { return null; } @@ -56,19 +56,23 @@ export const EntitiesOverview: React.FC = () => { }} data-test-subj={INSIGHTS_ENTITIES_TEST_ID} > - <EuiFlexGroup direction="column" gutterSize="s"> - {userName && ( - <EuiFlexItem> - <UserEntityOverview userName={userName} /> - </EuiFlexItem> - )} - <EuiSpacer size="s" /> - {hostName && ( - <EuiFlexItem> - <HostEntityOverview hostName={hostName} /> - </EuiFlexItem> - )} - </EuiFlexGroup> + {userName || hostName ? ( + <EuiFlexGroup direction="column" gutterSize="s"> + {userName && ( + <EuiFlexItem> + <UserEntityOverview userName={userName} /> + </EuiFlexItem> + )} + <EuiSpacer size="s" /> + {hostName && ( + <EuiFlexItem> + <HostEntityOverview hostName={hostName} /> + </EuiFlexItem> + )} + </EuiFlexGroup> + ) : ( + <div data-test-subj={INSIGHTS_ENTITIES_NO_DATA_TEST_ID}>{ENTITIES_NO_DATA_MESSAGE}</div> + )} </ExpandablePanel> </> ); diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts index c4eb67f5ddba9..9c810f7bfc696 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts +++ b/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts @@ -83,6 +83,7 @@ export const SUMMARY_ROW_VALUE_TEST_ID = (dataTestSubj: string) => `${dataTestSu /* Insights Entities */ export const INSIGHTS_ENTITIES_TEST_ID = 'securitySolutionDocumentDetailsFlyoutInsightsEntities'; +export const INSIGHTS_ENTITIES_NO_DATA_TEST_ID = `${INSIGHTS_ENTITIES_TEST_ID}NoData` as const; export const ENTITIES_USER_OVERVIEW_TEST_ID = 'securitySolutionDocumentDetailsFlyoutEntitiesUserOverview'; export const ENTITIES_USER_OVERVIEW_LINK_TEST_ID = `${ENTITIES_USER_OVERVIEW_TEST_ID}Link`; diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts b/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts index 3a04a68ac0ebf..4d1390701ad10 100644 --- a/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts +++ b/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts @@ -130,6 +130,13 @@ export const ENTITIES_TITLE = i18n.translate( { defaultMessage: 'Entities' } ); +export const ENTITIES_NO_DATA_MESSAGE = i18n.translate( + 'xpack.securitySolution.flyout.documentDetails.entitiesNoDataMessage', + { + defaultMessage: 'No user or host data available', + } +); + export const THREAT_INTELLIGENCE_TITLE = i18n.translate( 'xpack.securitySolution.flyout.documentDetails.threatIntelligenceTitle', { defaultMessage: 'Threat Intelligence' } From aa274256630715da00594219a11caa7188b4678b Mon Sep 17 00:00:00 2001 From: Daniel Mitterdorfer <danielmitterdorfer@users.noreply.github.com> Date: Tue, 29 Aug 2023 10:15:18 +0200 Subject: [PATCH 45/49] Construct HTTP log message only if needed (#165057) ## Summary Previously we have unconditionally created a debug log message that potentially involved serializing a large response object only to ignore it if the the log level 'debug' is disabled for that logger. With this commit we add a check if the respective level is enabled on the logger before we proceed to construct the log message. ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../core/http/core-http-server-internal/src/http_server.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/core/http/core-http-server-internal/src/http_server.ts b/packages/core/http/core-http-server-internal/src/http_server.ts index 78cab6c6ea076..f12367419341f 100644 --- a/packages/core/http/core-http-server-internal/src/http_server.ts +++ b/packages/core/http/core-http-server-internal/src/http_server.ts @@ -399,8 +399,10 @@ export class HttpServer { const log = this.logger.get('http', 'server', 'response'); this.handleServerResponseEvent = (request) => { - const { message, meta } = getEcsResponseLog(request, this.log); - log.debug(message!, meta); + if (log.isLevelEnabled('debug')) { + const { message, meta } = getEcsResponseLog(request, this.log); + log.debug(message!, meta); + } }; this.server.events.on('response', this.handleServerResponseEvent); From d63dd9df2deebab9a4e425e8446ed3ffdc8eebb9 Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Tue, 29 Aug 2023 09:18:00 +0100 Subject: [PATCH 46/49] [SecuritySolution] Hide create dashboard button from listing (#164476) ## Summary original issue: https://github.com/elastic/kibana/issues/163459 **Before** - Two Create Dashboard buttons on Security Dashboard ![image](https://github.com/elastic/kibana/assets/59917825/d82e7056-0df3-44b1-abeb-10da67510247) **After** - Create dashboard button from listing is removed. <img width="2542" alt="Screenshot 2023-08-22 at 16 45 56" src="https://github.com/elastic/kibana/assets/6295984/ff9bc785-de2a-40b7-b414-829c8913d997"> ### Checklist Delete any items that are not applicable to this PR. - [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 --- .../dashboard_listing_table.tsx | 2 ++ .../hooks/use_dashboard_listing_table.test.tsx | 16 ++++++++++++++++ .../hooks/use_dashboard_listing_table.tsx | 5 ++++- .../dashboard/public/dashboard_listing/types.ts | 1 + .../dashboards/pages/landing_page/index.tsx | 1 + .../security/ftr/cases/attachment_framework.ts | 2 +- 6 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/plugins/dashboard/public/dashboard_listing/dashboard_listing_table.tsx b/src/plugins/dashboard/public/dashboard_listing/dashboard_listing_table.tsx index 196fd04cddf6c..2386b414c3209 100644 --- a/src/plugins/dashboard/public/dashboard_listing/dashboard_listing_table.tsx +++ b/src/plugins/dashboard/public/dashboard_listing/dashboard_listing_table.tsx @@ -34,6 +34,7 @@ export const DashboardListingTable = ({ getDashboardUrl, useSessionStorageIntegration, urlStateEnabled, + showCreateDashboardButton = true, }: DashboardListingProps) => { const { application, @@ -61,6 +62,7 @@ export const DashboardListingTable = ({ urlStateEnabled, useSessionStorageIntegration, initialFilter, + showCreateDashboardButton, }); const savedObjectsTaggingFakePlugin = useMemo( diff --git a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx index 7716981e34942..602ac6a1f4a3c 100644 --- a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx +++ b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx @@ -105,6 +105,22 @@ describe('useDashboardListingTable', () => { expect(result.current.unsavedDashboardIds).toEqual([]); }); + test('should not render the create dashboard button when showCreateDashboardButton is false', () => { + const initialFilter = 'myFilter'; + const { result } = renderHook(() => + useDashboardListingTable({ + getDashboardUrl, + goToDashboard, + initialFilter, + urlStateEnabled: false, + showCreateDashboardButton: false, + }) + ); + + const tableListViewTableProps = result.current.tableListViewTableProps; + expect(tableListViewTableProps.createItem).toBeUndefined(); + }); + test('should return the correct tableListViewTableProps', () => { const initialFilter = 'myFilter'; const { result } = renderHook(() => diff --git a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx index aefa45500b450..8f2fb7ac76cc9 100644 --- a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx +++ b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx @@ -70,6 +70,7 @@ export const useDashboardListingTable = ({ initialFilter, urlStateEnabled, useSessionStorageIntegration, + showCreateDashboardButton = true, }: { dashboardListingId?: string; disableCreateDashboardButton?: boolean; @@ -79,6 +80,7 @@ export const useDashboardListingTable = ({ initialFilter?: string; urlStateEnabled?: boolean; useSessionStorageIntegration?: boolean; + showCreateDashboardButton?: boolean; }): UseDashboardListingTableReturnType => { const { dashboardSessionStorage, @@ -274,7 +276,7 @@ export const useDashboardListingTable = ({ onSave: updateItemMeta, customValidators: contentEditorValidators, }, - createItem: !showWriteControls ? undefined : createItem, + createItem: !showWriteControls || !showCreateDashboardButton ? undefined : createItem, deleteItems: !showWriteControls ? undefined : deleteItems, editItem: !showWriteControls ? undefined : editItem, emptyPrompt, @@ -308,6 +310,7 @@ export const useDashboardListingTable = ({ initialPageSize, listingLimit, onFetchSuccess, + showCreateDashboardButton, showWriteControls, title, updateItemMeta, diff --git a/src/plugins/dashboard/public/dashboard_listing/types.ts b/src/plugins/dashboard/public/dashboard_listing/types.ts index c92344d4e778a..18767c1c75c32 100644 --- a/src/plugins/dashboard/public/dashboard_listing/types.ts +++ b/src/plugins/dashboard/public/dashboard_listing/types.ts @@ -17,6 +17,7 @@ export type DashboardListingProps = PropsWithChildren<{ goToDashboard: (dashboardId?: string, viewMode?: ViewMode) => void; getDashboardUrl: (dashboardId: string, usesTimeRestore: boolean) => string; urlStateEnabled?: boolean; + showCreateDashboardButton?: boolean; }>; // because the type of `application.capabilities.advancedSettings` is so generic, the provider diff --git a/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.tsx b/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.tsx index e72e38429f35d..7d579c66e8191 100644 --- a/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.tsx +++ b/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.tsx @@ -146,6 +146,7 @@ export const DashboardsLandingPage = () => { goToDashboard={goToDashboard} initialFilter={initialFilter} urlStateEnabled={false} + showCreateDashboardButton={false} /> </> )} diff --git a/x-pack/test_serverless/functional/test_suites/security/ftr/cases/attachment_framework.ts b/x-pack/test_serverless/functional/test_suites/security/ftr/cases/attachment_framework.ts index a35787cff6aad..6b76503531d3c 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ftr/cases/attachment_framework.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ftr/cases/attachment_framework.ts @@ -30,7 +30,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await testSubjects.click('solutionSideNavItemLink-dashboards'); - await dashboard.clickNewDashboard(); + await testSubjects.click('createDashboardButton'); await lens.createAndAddLensFromDashboard({}); From 1a006a98f6eae85612baeb7e323341a2f8be3e87 Mon Sep 17 00:00:00 2001 From: Philippe Oberti <philippe.oberti@elastic.co> Date: Tue, 29 Aug 2023 10:18:40 +0200 Subject: [PATCH 47/49] =?UTF-8?q?[Security=20Solution]=20expandable=20flyo?= =?UTF-8?q?ut=20-=20add=20investigate=20in=20timeline=20f=E2=80=A6=20(#165?= =?UTF-8?q?025)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../table/use_action_cell_data_provider.ts | 10 ++-- .../components/prevalence_details.test.tsx | 18 +++++- .../left/components/prevalence_details.tsx | 57 ++++++++++++++++++- ...rt_details_left_panel_prevalence_tab.cy.ts | 2 +- 4 files changed, 77 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/table/use_action_cell_data_provider.ts b/x-pack/plugins/security_solution/public/common/components/event_details/table/use_action_cell_data_provider.ts index 7ee53ae5d4bee..c9d8162af8f0c 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/table/use_action_cell_data_provider.ts +++ b/x-pack/plugins/security_solution/public/common/components/event_details/table/use_action_cell_data_provider.ts @@ -55,13 +55,14 @@ export const getDataProvider = ( field: string, id: string, value: string | string[], - operator: QueryOperator = IS_OPERATOR + operator: QueryOperator = IS_OPERATOR, + excluded: boolean = false ): DataProvider => ({ and: [], enabled: true, id: escapeDataProviderId(id), name: field, - excluded: false, + excluded, kqlQuery: '', queryMatch: { field, @@ -75,9 +76,10 @@ export const getDataProviderAnd = ( field: string, id: string, value: string | string[], - operator: QueryOperator = IS_OPERATOR + operator: QueryOperator = IS_OPERATOR, + excluded: boolean = false ): DataProvidersAnd => { - const { and, ...dataProvider } = getDataProvider(field, id, value, operator); + const { and, ...dataProvider } = getDataProvider(field, id, value, operator, excluded); return dataProvider; }; diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/prevalence_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/left/components/prevalence_details.test.tsx index a5f2883b676af..e1512b8b7ada1 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/components/prevalence_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/left/components/prevalence_details.test.tsx @@ -15,9 +15,19 @@ import { PREVALENCE_DETAILS_TABLE_TEST_ID, } from './test_ids'; import { usePrevalence } from '../../shared/hooks/use_prevalence'; +import { TestProviders } from '../../../common/mock'; jest.mock('../../shared/hooks/use_prevalence'); +const mockDispatch = jest.fn(); +jest.mock('react-redux', () => { + const original = jest.requireActual('react-redux'); + return { + ...original, + useDispatch: () => mockDispatch, + }; +}); + const panelContextValue = { eventId: 'event id', indexName: 'indexName', @@ -53,9 +63,11 @@ describe('PrevalenceDetails', () => { }); const { getByTestId } = render( - <LeftPanelContext.Provider value={panelContextValue}> - <PrevalenceDetails /> - </LeftPanelContext.Provider> + <TestProviders> + <LeftPanelContext.Provider value={panelContextValue}> + <PrevalenceDetails /> + </LeftPanelContext.Provider> + </TestProviders> ); expect(getByTestId(PREVALENCE_DETAILS_TABLE_TEST_ID)).toBeInTheDocument(); diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/prevalence_details.tsx b/x-pack/plugins/security_solution/public/flyout/left/components/prevalence_details.tsx index eeadf1362c71e..a5e7907c13c8c 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/components/prevalence_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/left/components/prevalence_details.tsx @@ -17,6 +17,7 @@ import { EuiSpacer, EuiSuperDatePicker, } from '@elastic/eui'; +import { InvestigateInTimelineButton } from '../../../common/components/event_details/table/investigate_in_timeline_button'; import type { PrevalenceData } from '../../shared/hooks/use_prevalence'; import { usePrevalence } from '../../shared/hooks/use_prevalence'; import { ERROR_MESSAGE, ERROR_TITLE } from '../../shared/translations'; @@ -46,6 +47,12 @@ import { PREVALENCE_DETAILS_TABLE_TEST_ID, } from './test_ids'; import { useLeftPanelContext } from '../context'; +import { + getDataProvider, + getDataProviderAnd, +} from '../../../common/components/event_details/table/use_action_cell_data_provider'; +import { getEmptyTagValue } from '../../../common/components/empty_value'; +import { IS_OPERATOR } from '../../../../common/types'; export const PREVALENCE_TAB_ID = 'prevalence-details'; const DEFAULT_FROM = 'now-30d'; @@ -63,7 +70,6 @@ const columns: Array<EuiBasicTableColumn<PrevalenceData>> = [ 'data-test-subj': PREVALENCE_DETAILS_TABLE_VALUE_CELL_TEST_ID, }, { - field: 'alertCount', name: ( <EuiFlexGroup direction="column" gutterSize="none"> <EuiFlexItem>{PREVALENCE_TABLE_ALERT_COUNT_COLUMN_TITLE}</EuiFlexItem> @@ -71,10 +77,25 @@ const columns: Array<EuiBasicTableColumn<PrevalenceData>> = [ </EuiFlexGroup> ), 'data-test-subj': PREVALENCE_DETAILS_TABLE_ALERT_COUNT_CELL_TEST_ID, + render: (data: PrevalenceData) => { + const dataProviders = [ + getDataProvider(data.field, `timeline-indicator-${data.field}-${data.value}`, data.value), + ]; + return data.alertCount > 0 ? ( + <InvestigateInTimelineButton + asEmptyButton={true} + dataProviders={dataProviders} + filters={[]} + > + <>{data.alertCount}</> + </InvestigateInTimelineButton> + ) : ( + getEmptyTagValue() + ); + }, width: '10%', }, { - field: 'docCount', name: ( <EuiFlexGroup direction="column" gutterSize="none"> <EuiFlexItem>{PREVALENCE_TABLE_DOC_COUNT_COLUMN_TITLE}</EuiFlexItem> @@ -82,6 +103,38 @@ const columns: Array<EuiBasicTableColumn<PrevalenceData>> = [ </EuiFlexGroup> ), 'data-test-subj': PREVALENCE_DETAILS_TABLE_DOC_COUNT_CELL_TEST_ID, + render: (data: PrevalenceData) => { + const dataProviders = [ + { + ...getDataProvider( + data.field, + `timeline-indicator-${data.field}-${data.value}`, + data.value + ), + and: [ + getDataProviderAnd( + 'event.kind', + `timeline-indicator-event.kind-not-signal`, + 'signal', + IS_OPERATOR, + true + ), + ], + }, + ]; + return data.docCount > 0 ? ( + <InvestigateInTimelineButton + asEmptyButton={true} + dataProviders={dataProviders} + filters={[]} + keepDataView // changing dataview from only detections to include non-alerts docs + > + <>{data.docCount}</> + </InvestigateInTimelineButton> + ) : ( + getEmptyTagValue() + ); + }, width: '10%', }, { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_prevalence_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_prevalence_tab.cy.ts index baff17ce85d03..97645c3df5490 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_prevalence_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_prevalence_tab.cy.ts @@ -68,7 +68,7 @@ describe('Alert details expandable flyout left panel prevalence', () => { ); cy.get(DOCUMENT_DETAILS_FLYOUT_INSIGHTS_TAB_PREVALENCE_TABLE_DOC_COUNT_CELL).should( 'contain.text', - 0 + '—' ); cy.get(DOCUMENT_DETAILS_FLYOUT_INSIGHTS_TAB_PREVALENCE_TABLE_HOST_PREVALENCE_CELL).should( 'contain.text', From d6db6b7b4a96a77c8d6afdeb5ab0216c2bc24393 Mon Sep 17 00:00:00 2001 From: Luke Elmers <luke.elmers@elastic.co> Date: Tue, 29 Aug 2023 02:25:51 -0600 Subject: [PATCH 48/49] Adjust migrations and elasticsearch service settings for serverless. (#165050) --- config/serverless.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config/serverless.yml b/config/serverless.yml index e18049e8517c6..c76e622d67547 100644 --- a/config/serverless.yml +++ b/config/serverless.yml @@ -13,6 +13,10 @@ xpack.cloud.base_url: "https://cloud.elastic.co" # Enable ZDT migration algorithm migrations.algorithm: zdt +# Limit batch size to reduce possibility of failures. +# A longer migration time is acceptable due to the ZDT algorithm. +migrations.batchSize: 250 + # temporarily allow to run the migration on UI nodes # until the controller is able to spawn the migrator job/pod migrations.zdt: @@ -86,6 +90,9 @@ console.autocompleteDefinitions.endpointsAvailability: serverless # Allow authentication via the Elasticsearch JWT realm with the `shared_secret` client authentication type. elasticsearch.requestHeadersWhitelist: ["authorization", "es-client-authentication"] +# Limit maxSockets to 800 as we do in ESS, which improves reliability under high loads. +elasticsearch.maxSockets: 800 + # Visualizations editors readonly settings vis_type_gauge.readOnly: true vis_type_heatmap.readOnly: true From a5428c05970026cde5a4c99df98514cb022096a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Tue, 29 Aug 2023 10:37:13 +0100 Subject: [PATCH 49/49] [Profiling] display delete instruction page when old data is found (#164855) - **Upgrading from 8.8 -> 8.9** Shows the Set up page because of missing Collector and Symbolizer integrations - **Upgrading from 8.9 -> 8.10** Shows the Set up page because Profiling was installed with APM integration --- <img width="719" alt="Screenshot 2023-08-25 at 16 01 53" src="https://github.com/elastic/kibana/assets/55978943/15fee345-868e-4fe1-add9-b9a8e41cfd20"> Users with `Viewer` privileges will open the Profiling UI, as they don't have permission to call the profiling status API and display a callout. <img width="950" alt="Screenshot 2023-08-25 at 20 46 28" src="https://github.com/elastic/kibana/assets/55978943/f398ac30-41df-410e-9447-7469b97d46db"> --- x-pack/plugins/profiling/common/setup.test.ts | 294 ++++++++---------- x-pack/plugins/profiling/common/setup.ts | 12 +- .../plugins/profiling/common/stack_traces.ts | 1 + .../e2e/cypress/e2e/empty_state/home.cy.ts | 57 +++- .../cypress/e2e/profiling_views/home.cy.ts | 15 + .../fixtures/es_resources_data_false.json | 4 - .../fixtures/es_resources_setup_false.json | 4 - x-pack/plugins/profiling/public/app.tsx | 33 +- .../public/components/check_setup.tsx | 29 +- .../profiling_setup_status_context.tsx | 35 +++ .../use_profiling_setup_status.tsx | 17 + .../profiling_app_page_template/index.tsx | 35 +++ .../public/hooks/use_local_storage.ts | 57 ++++ .../profiling/public/routing/index.tsx | 4 + x-pack/plugins/profiling/public/services.ts | 16 +- .../public/views/delete_data_view/index.tsx | 42 +++ .../server/lib/setup/cluster_settings.ts | 1 + .../plugins/profiling/server/routes/setup.ts | 80 +++-- 18 files changed, 472 insertions(+), 264 deletions(-) delete mode 100644 x-pack/plugins/profiling/e2e/cypress/fixtures/es_resources_data_false.json delete mode 100644 x-pack/plugins/profiling/e2e/cypress/fixtures/es_resources_setup_false.json create mode 100644 x-pack/plugins/profiling/public/components/contexts/profiling_setup_status/profiling_setup_status_context.tsx create mode 100644 x-pack/plugins/profiling/public/components/contexts/profiling_setup_status/use_profiling_setup_status.tsx create mode 100644 x-pack/plugins/profiling/public/hooks/use_local_storage.ts create mode 100644 x-pack/plugins/profiling/public/views/delete_data_view/index.tsx diff --git a/x-pack/plugins/profiling/common/setup.test.ts b/x-pack/plugins/profiling/common/setup.test.ts index 100c0efa5cace..48b8136e39020 100644 --- a/x-pack/plugins/profiling/common/setup.test.ts +++ b/x-pack/plugins/profiling/common/setup.test.ts @@ -6,8 +6,7 @@ */ import { - areResourcesSetupForAdmin, - areResourcesSetupForViewer, + areResourcesSetup, createDefaultSetupState, mergePartialSetupStates, PartialSetupState, @@ -54,178 +53,129 @@ function createSettingsState(configured: boolean): PartialSetupState { } describe('Merging partial state operations', () => { - describe('Merge states', () => { - const defaultSetupState = createDefaultSetupState(); - - it('returns partial states with missing key', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCloudState(true), - createDataState(true), - ]); - - expect(mergedState.cloud.available).toEqual(true); - expect(mergedState.cloud.required).toEqual(true); - expect(mergedState.data.available).toEqual(true); - }); - - it('should deeply nested partial states with overlap', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(true), - createSymbolizerPolicyState(true), - ]); - - expect(mergedState.policies.collector.installed).toEqual(true); - expect(mergedState.policies.symbolizer.installed).toEqual(true); - }); + const defaultSetupState = createDefaultSetupState(); + + it('returns partial states with missing key', () => { + const mergedState = mergePartialSetupStates(defaultSetupState, [ + createCloudState(true), + createDataState(true), + ]); + + expect(mergedState.cloud.available).toEqual(true); + expect(mergedState.cloud.required).toEqual(true); + expect(mergedState.data.available).toEqual(true); + }); + + it('should deeply nested partial states with overlap', () => { + const mergedState = mergePartialSetupStates(defaultSetupState, [ + createCollectorPolicyState(true), + createSymbolizerPolicyState(true), + ]); + + expect(mergedState.policies.collector.installed).toEqual(true); + expect(mergedState.policies.symbolizer.installed).toEqual(true); }); - describe('For admin users', () => { - const defaultSetupState = createDefaultSetupState(); - it('returns false when permission is not configured', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(true), - createSymbolizerPolicyState(true), - createProfilingInApmPolicyState(true), - createResourceState({ enabled: true, created: true }), - createSettingsState(true), - createPermissionState(false), - ]); - - expect(areResourcesSetupForAdmin(mergedState)).toBeFalsy(); - }); - - it('returns false when resource management is not enabled', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(true), - createSymbolizerPolicyState(true), - createProfilingInApmPolicyState(true), - createResourceState({ enabled: false, created: true }), - createSettingsState(true), - createPermissionState(true), - ]); - - expect(areResourcesSetupForAdmin(mergedState)).toBeFalsy(); - }); - - it('returns false when resources are not created', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(true), - createSymbolizerPolicyState(true), - createProfilingInApmPolicyState(true), - createResourceState({ enabled: true, created: false }), - createSettingsState(true), - createPermissionState(true), - ]); - - expect(areResourcesSetupForAdmin(mergedState)).toBeFalsy(); - }); - - it('returns false when settings are not configured', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(true), - createSymbolizerPolicyState(true), - createProfilingInApmPolicyState(true), - createResourceState({ enabled: true, created: true }), - createSettingsState(false), - createPermissionState(true), - ]); - - expect(areResourcesSetupForAdmin(mergedState)).toBeFalsy(); - }); - - it('returns true when all checks are valid', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(true), - createSymbolizerPolicyState(true), - createProfilingInApmPolicyState(false), - createResourceState({ enabled: true, created: true }), - createSettingsState(true), - createPermissionState(true), - ]); - - expect(areResourcesSetupForAdmin(mergedState)).toBeTruthy(); - }); - - it('returns false when collector is not found', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(false), - createSymbolizerPolicyState(true), - createProfilingInApmPolicyState(false), - createResourceState({ enabled: true, created: true }), - createSettingsState(true), - createPermissionState(true), - ]); - - expect(areResourcesSetupForAdmin(mergedState)).toBeFalsy(); - }); - - it('returns false when symbolizer is not found', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(true), - createSymbolizerPolicyState(false), - createProfilingInApmPolicyState(false), - createResourceState({ enabled: true, created: true }), - createSettingsState(true), - createPermissionState(true), - ]); - - expect(areResourcesSetupForAdmin(mergedState)).toBeFalsy(); - }); - - it('returns false when profiling is in APM server', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(true), - createSymbolizerPolicyState(true), - createProfilingInApmPolicyState(true), - createResourceState({ enabled: true, created: true }), - createSettingsState(true), - createPermissionState(true), - ]); - - expect(areResourcesSetupForAdmin(mergedState)).toBeFalsy(); - }); + it('returns false when permission is not configured', () => { + const mergedState = mergePartialSetupStates(defaultSetupState, [ + createCollectorPolicyState(true), + createSymbolizerPolicyState(true), + createProfilingInApmPolicyState(true), + createResourceState({ enabled: true, created: true }), + createSettingsState(true), + createPermissionState(false), + ]); + + expect(areResourcesSetup(mergedState)).toBeFalsy(); + }); + + it('returns false when resource management is not enabled', () => { + const mergedState = mergePartialSetupStates(defaultSetupState, [ + createCollectorPolicyState(true), + createSymbolizerPolicyState(true), + createProfilingInApmPolicyState(true), + createResourceState({ enabled: false, created: true }), + createSettingsState(true), + createPermissionState(true), + ]); + + expect(areResourcesSetup(mergedState)).toBeFalsy(); + }); + + it('returns false when resources are not created', () => { + const mergedState = mergePartialSetupStates(defaultSetupState, [ + createCollectorPolicyState(true), + createSymbolizerPolicyState(true), + createProfilingInApmPolicyState(true), + createResourceState({ enabled: true, created: false }), + createSettingsState(true), + createPermissionState(true), + ]); + + expect(areResourcesSetup(mergedState)).toBeFalsy(); + }); + + it('returns false when settings are not configured', () => { + const mergedState = mergePartialSetupStates(defaultSetupState, [ + createCollectorPolicyState(true), + createSymbolizerPolicyState(true), + createProfilingInApmPolicyState(true), + createResourceState({ enabled: true, created: true }), + createSettingsState(false), + createPermissionState(true), + ]); + + expect(areResourcesSetup(mergedState)).toBeFalsy(); + }); + + it('returns true when all checks are valid', () => { + const mergedState = mergePartialSetupStates(defaultSetupState, [ + createCollectorPolicyState(true), + createSymbolizerPolicyState(true), + createProfilingInApmPolicyState(false), + createResourceState({ enabled: true, created: true }), + createSettingsState(true), + createPermissionState(true), + ]); + + expect(areResourcesSetup(mergedState)).toBeTruthy(); + }); + + it('returns false when collector is not found', () => { + const mergedState = mergePartialSetupStates(defaultSetupState, [ + createCollectorPolicyState(false), + createSymbolizerPolicyState(true), + createProfilingInApmPolicyState(false), + createResourceState({ enabled: true, created: true }), + createSettingsState(true), + createPermissionState(true), + ]); + + expect(areResourcesSetup(mergedState)).toBeFalsy(); + }); + + it('returns false when symbolizer is not found', () => { + const mergedState = mergePartialSetupStates(defaultSetupState, [ + createCollectorPolicyState(true), + createSymbolizerPolicyState(false), + createProfilingInApmPolicyState(false), + createResourceState({ enabled: true, created: true }), + createSettingsState(true), + createPermissionState(true), + ]); + + expect(areResourcesSetup(mergedState)).toBeFalsy(); }); - describe('For viewer users', () => { - const defaultSetupState = createDefaultSetupState(); - - it('returns false when collector is not installed', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(false), - createSymbolizerPolicyState(true), - createProfilingInApmPolicyState(false), - ]); - - expect(areResourcesSetupForViewer(mergedState)).toBeFalsy(); - }); - - it('returns false when symbolizer is not installed', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(true), - createSymbolizerPolicyState(false), - createProfilingInApmPolicyState(false), - ]); - - expect(areResourcesSetupForViewer(mergedState)).toBeFalsy(); - }); - - it('returns false when profiling is configured in APM policy', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(true), - createSymbolizerPolicyState(true), - createProfilingInApmPolicyState(true), - ]); - - expect(areResourcesSetupForViewer(mergedState)).toBeFalsy(); - }); - - it('returns true when all checks are valid', () => { - const mergedState = mergePartialSetupStates(defaultSetupState, [ - createCollectorPolicyState(true), - createSymbolizerPolicyState(true), - createProfilingInApmPolicyState(false), - ]); - - expect(areResourcesSetupForViewer(mergedState)).toBeTruthy(); - }); + it('returns false when profiling is in APM server', () => { + const mergedState = mergePartialSetupStates(defaultSetupState, [ + createCollectorPolicyState(true), + createSymbolizerPolicyState(true), + createProfilingInApmPolicyState(true), + createResourceState({ enabled: true, created: true }), + createSettingsState(true), + createPermissionState(true), + ]); + + expect(areResourcesSetup(mergedState)).toBeFalsy(); }); }); diff --git a/x-pack/plugins/profiling/common/setup.ts b/x-pack/plugins/profiling/common/setup.ts index e1ee768d9d3d0..facae98f25012 100644 --- a/x-pack/plugins/profiling/common/setup.ts +++ b/x-pack/plugins/profiling/common/setup.ts @@ -35,6 +35,7 @@ export interface SetupState { }; resources: { created: boolean; + pre_8_9_1_data: boolean; }; settings: { configured: boolean; @@ -71,6 +72,7 @@ export function createDefaultSetupState(): SetupState { }, resources: { created: false, + pre_8_9_1_data: false, }, settings: { configured: false, @@ -78,17 +80,11 @@ export function createDefaultSetupState(): SetupState { }; } -export function areResourcesSetupForViewer(state: SetupState): boolean { +export function areResourcesSetup(state: SetupState): boolean { return ( state.policies.collector.installed && state.policies.symbolizer.installed && - !state.policies.apm.profilingEnabled - ); -} - -export function areResourcesSetupForAdmin(state: SetupState): boolean { - return ( - areResourcesSetupForViewer(state) && + !state.policies.apm.profilingEnabled && state.resource_management.enabled && state.resources.created && state.permissions.configured && diff --git a/x-pack/plugins/profiling/common/stack_traces.ts b/x-pack/plugins/profiling/common/stack_traces.ts index 8266f32a19f1e..97a18d09ed389 100644 --- a/x-pack/plugins/profiling/common/stack_traces.ts +++ b/x-pack/plugins/profiling/common/stack_traces.ts @@ -24,6 +24,7 @@ export interface ProfilingStatusResponse { }; resources: { created: boolean; + pre_8_9_1_data: boolean; }; } diff --git a/x-pack/plugins/profiling/e2e/cypress/e2e/empty_state/home.cy.ts b/x-pack/plugins/profiling/e2e/cypress/e2e/empty_state/home.cy.ts index 26f2347a62340..bba7a3c014c41 100644 --- a/x-pack/plugins/profiling/e2e/cypress/e2e/empty_state/home.cy.ts +++ b/x-pack/plugins/profiling/e2e/cypress/e2e/empty_state/home.cy.ts @@ -10,9 +10,13 @@ describe('Home page with empty state', () => { cy.loginAsElastic(); }); - it('shows the empty state when Profiling has not been set up', () => { + it('shows Set up page when Profiling has not been set up', () => { cy.intercept('GET', '/internal/profiling/setup/es_resources', { - fixture: 'es_resources_setup_false.json', + body: { + has_setup: false, + has_data: false, + pre_8_9_1_data: false, + }, }).as('getEsResources'); cy.visitKibana('/app/profiling'); cy.wait('@getEsResources'); @@ -20,9 +24,13 @@ describe('Home page with empty state', () => { cy.contains('Set up Universal Profiling'); }); - it('shows the tutorial after Profiling has been set up', () => { + it('shows Add data page after Profiling has been set up', () => { cy.intercept('GET', '/internal/profiling/setup/es_resources', { - fixture: 'es_resources_data_false.json', + body: { + has_setup: true, + has_data: false, + pre_8_9_1_data: false, + }, }).as('getEsResources'); cy.visitKibana('/app/profiling'); cy.wait('@getEsResources'); @@ -34,4 +42,45 @@ describe('Home page with empty state', () => { cy.contains('RPM Package'); cy.contains('Upload Symbols'); }); + + describe('Delete Data View', () => { + it('shows Delete page when setup is false', () => { + cy.intercept('GET', '/internal/profiling/setup/es_resources', { + body: { + has_setup: false, + has_data: true, + pre_8_9_1_data: true, + }, + }).as('getEsResources'); + cy.visitKibana('/app/profiling'); + cy.wait('@getEsResources'); + cy.contains('Delete existing profiling data'); + }); + + it('shows Delete page when data pre 8.9.1 is still available and data is found', () => { + cy.intercept('GET', '/internal/profiling/setup/es_resources', { + body: { + has_setup: true, + has_data: true, + pre_8_9_1_data: true, + }, + }).as('getEsResources'); + cy.visitKibana('/app/profiling'); + cy.wait('@getEsResources'); + cy.contains('Delete existing profiling data'); + }); + + it('shows Delete page when data pre 8.9.1 is still available and data is not found', () => { + cy.intercept('GET', '/internal/profiling/setup/es_resources', { + body: { + has_setup: true, + has_data: false, + pre_8_9_1_data: true, + }, + }).as('getEsResources'); + cy.visitKibana('/app/profiling'); + cy.wait('@getEsResources'); + cy.contains('Delete existing profiling data'); + }); + }); }); diff --git a/x-pack/plugins/profiling/e2e/cypress/e2e/profiling_views/home.cy.ts b/x-pack/plugins/profiling/e2e/cypress/e2e/profiling_views/home.cy.ts index 1f4f91156f797..215738872c7d5 100644 --- a/x-pack/plugins/profiling/e2e/cypress/e2e/profiling_views/home.cy.ts +++ b/x-pack/plugins/profiling/e2e/cypress/e2e/profiling_views/home.cy.ts @@ -19,6 +19,21 @@ describe('Home page', () => { cy.loginAsElastic(); }); + it('opens Profiling UI when user does not have privileges', () => { + cy.intercept('GET', '/internal/profiling/setup/es_resources', { + body: { + has_setup: true, + pre_8_9_1_data: false, + has_data: true, + unauthorized: true, + }, + }).as('getEsResources'); + cy.visitKibana('/app/profiling', { rangeFrom, rangeTo }); + cy.wait('@getEsResources'); + cy.contains('Top 46'); + cy.contains('User privilege limitation'); + }); + it('navigates through the tabs', () => { cy.visitKibana('/app/profiling', { rangeFrom, rangeTo }); cy.url().should('include', '/app/profiling/stacktraces/threads'); diff --git a/x-pack/plugins/profiling/e2e/cypress/fixtures/es_resources_data_false.json b/x-pack/plugins/profiling/e2e/cypress/fixtures/es_resources_data_false.json deleted file mode 100644 index ee5725bcf460d..0000000000000 --- a/x-pack/plugins/profiling/e2e/cypress/fixtures/es_resources_data_false.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "has_setup": true, - "has_data": false -} diff --git a/x-pack/plugins/profiling/e2e/cypress/fixtures/es_resources_setup_false.json b/x-pack/plugins/profiling/e2e/cypress/fixtures/es_resources_setup_false.json deleted file mode 100644 index e86b5b846d908..0000000000000 --- a/x-pack/plugins/profiling/e2e/cypress/fixtures/es_resources_setup_false.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "has_setup": false, - "has_data": false -} diff --git a/x-pack/plugins/profiling/public/app.tsx b/x-pack/plugins/profiling/public/app.tsx index 01bd240dd4028..8ffc064359e3d 100644 --- a/x-pack/plugins/profiling/public/app.tsx +++ b/x-pack/plugins/profiling/public/app.tsx @@ -25,6 +25,7 @@ import { ProfilingPluginPublicSetupDeps, ProfilingPluginPublicStartDeps } from ' import { ProfilingHeaderActionMenu } from './components/profiling_header_action_menu'; import { RouterErrorBoundary } from './routing/router_error_boundary'; import { LicenseProvider } from './components/contexts/license/license_context'; +import { ProfilingSetupStatusContextProvider } from './components/contexts/profiling_setup_status/profiling_setup_status_context'; interface Props { profilingFetchServices: Services; @@ -89,21 +90,23 @@ function App({ <RouterErrorBoundary> <TimeRangeContextProvider> <ProfilingDependenciesContextProvider value={profilingDependencies}> - <LicenseProvider> - <> - <CheckSetup> - <RedirectWithDefaultDateRange> - <RouteBreadcrumbsContextProvider> - <RouteRenderer /> - </RouteBreadcrumbsContextProvider> - </RedirectWithDefaultDateRange> - </CheckSetup> - <MountProfilingActionMenu - setHeaderActionMenu={setHeaderActionMenu} - theme$={theme$} - /> - </> - </LicenseProvider> + <ProfilingSetupStatusContextProvider> + <LicenseProvider> + <> + <CheckSetup> + <RedirectWithDefaultDateRange> + <RouteBreadcrumbsContextProvider> + <RouteRenderer /> + </RouteBreadcrumbsContextProvider> + </RedirectWithDefaultDateRange> + </CheckSetup> + <MountProfilingActionMenu + setHeaderActionMenu={setHeaderActionMenu} + theme$={theme$} + /> + </> + </LicenseProvider> + </ProfilingSetupStatusContextProvider> </ProfilingDependenciesContextProvider> </TimeRangeContextProvider> </RouterErrorBoundary> diff --git a/x-pack/plugins/profiling/public/components/check_setup.tsx b/x-pack/plugins/profiling/public/components/check_setup.tsx index e5b7993845323..cec2cc6f81c96 100644 --- a/x-pack/plugins/profiling/public/components/check_setup.tsx +++ b/x-pack/plugins/profiling/public/components/check_setup.tsx @@ -26,12 +26,14 @@ import { useLicenseContext } from './contexts/license/use_license_context'; import { useProfilingDependencies } from './contexts/profiling_dependencies/use_profiling_dependencies'; import { LicensePrompt } from './license_prompt'; import { ProfilingAppPageTemplate } from './profiling_app_page_template'; +import { useProfilingSetupStatus } from './contexts/profiling_setup_status/use_profiling_setup_status'; export function CheckSetup({ children }: { children: React.ReactElement }) { const { start: { core }, services: { fetchHasSetup, postSetupResources }, } = useProfilingDependencies(); + const { setProfilingSetupStatus } = useProfilingSetupStatus(); const license = useLicenseContext(); const router = useProfilingRouter(); const history = useHistory(); @@ -47,6 +49,10 @@ export function CheckSetup({ children }: { children: React.ReactElement }) { [fetchHasSetup] ); + if (status === AsyncStatus.Settled) { + setProfilingSetupStatus(data); + } + const http = useAutoAbortedHttpClient([]); if (!license?.hasAtLeast('enterprise')) { @@ -79,7 +85,10 @@ export function CheckSetup({ children }: { children: React.ReactElement }) { } const displaySetupScreen = - (status === AsyncStatus.Settled && data?.has_setup !== true) || !!error; + (status === AsyncStatus.Settled && + data?.has_setup !== true && + data?.pre_8_9_1_data === false) || + !!error; if (displaySetupScreen) { return ( @@ -193,19 +202,27 @@ export function CheckSetup({ children }: { children: React.ReactElement }) { ); } - const displayAddDataInstructions = - status === AsyncStatus.Settled && data?.has_setup === true && data?.has_data === false; - const displayUi = // Display UI if there's data or if the user is opening the add data instruction page. // does not use profiling router because that breaks as at this point the route might not have all required params - data?.has_data === true || history.location.pathname === '/add-data-instructions'; + (data?.has_data === true && data?.pre_8_9_1_data === false) || + history.location.pathname === '/add-data-instructions' || + history.location.pathname === '/delete_data_instructions'; if (displayUi) { return children; } - if (displayAddDataInstructions) { + if (data?.pre_8_9_1_data === true) { + // If the cluster still has data pre 8.9.1 version, redirect to deleting instructions + router.push('/delete_data_instructions', { + path: {}, + query: {}, + }); + return null; + } + + if (status === AsyncStatus.Settled && data?.has_setup === true && data?.has_data === false) { // when there's no data redirect the user to the add data instructions page router.push('/add-data-instructions', { path: {}, diff --git a/x-pack/plugins/profiling/public/components/contexts/profiling_setup_status/profiling_setup_status_context.tsx b/x-pack/plugins/profiling/public/components/contexts/profiling_setup_status/profiling_setup_status_context.tsx new file mode 100644 index 0000000000000..5f02a0886f7c2 --- /dev/null +++ b/x-pack/plugins/profiling/public/components/contexts/profiling_setup_status/profiling_setup_status_context.tsx @@ -0,0 +1,35 @@ +/* + * 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, { useState } from 'react'; +import { ProfilingSetupStatus } from '../../../services'; + +export const ProfilingSetupStatusContext = React.createContext< + | { + profilingSetupStatus: ProfilingSetupStatus | undefined; + setProfilingSetupStatus: React.Dispatch< + React.SetStateAction<ProfilingSetupStatus | undefined> + >; + } + | undefined +>(undefined); + +export function ProfilingSetupStatusContextProvider({ + children, +}: { + children: React.ReactElement; +}) { + const [profilingSetupStatus, setProfilingSetupStatus] = useState< + ProfilingSetupStatus | undefined + >(); + + return ( + <ProfilingSetupStatusContext.Provider value={{ profilingSetupStatus, setProfilingSetupStatus }}> + {children} + </ProfilingSetupStatusContext.Provider> + ); +} diff --git a/x-pack/plugins/profiling/public/components/contexts/profiling_setup_status/use_profiling_setup_status.tsx b/x-pack/plugins/profiling/public/components/contexts/profiling_setup_status/use_profiling_setup_status.tsx new file mode 100644 index 0000000000000..ac2e4379a9864 --- /dev/null +++ b/x-pack/plugins/profiling/public/components/contexts/profiling_setup_status/use_profiling_setup_status.tsx @@ -0,0 +1,17 @@ +/* + * 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 { useContext } from 'react'; +import { ProfilingSetupStatusContext } from './profiling_setup_status_context'; + +export function useProfilingSetupStatus() { + const context = useContext(ProfilingSetupStatusContext); + if (!context) { + throw new Error('ProfilingSetupStatusContext not found'); + } + return context; +} diff --git a/x-pack/plugins/profiling/public/components/profiling_app_page_template/index.tsx b/x-pack/plugins/profiling/public/components/profiling_app_page_template/index.tsx index 061215abe6ccd..a62d342b3919e 100644 --- a/x-pack/plugins/profiling/public/components/profiling_app_page_template/index.tsx +++ b/x-pack/plugins/profiling/public/components/profiling_app_page_template/index.tsx @@ -8,6 +8,7 @@ import { EuiBetaBadge, EuiButton, + EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, @@ -20,6 +21,8 @@ import { useHistory } from 'react-router-dom'; import { NoDataPageProps } from '@kbn/shared-ux-page-no-data-types'; import { useProfilingDependencies } from '../contexts/profiling_dependencies/use_profiling_dependencies'; import { PrimaryProfilingSearchBar } from './primary_profiling_search_bar'; +import { useLocalStorage } from '../../hooks/use_local_storage'; +import { useProfilingSetupStatus } from '../contexts/profiling_setup_status/use_profiling_setup_status'; export const PROFILING_FEEDBACK_LINK = 'https://ela.st/profiling-feedback'; @@ -46,6 +49,12 @@ export function ProfilingAppPageTemplate({ start: { observabilityShared }, } = useProfilingDependencies(); + const [privilegesWarningDismissed, setPrivilegesWarningDismissed] = useLocalStorage( + 'profiling.privilegesWarningDismissed', + false + ); + const { profilingSetupStatus } = useProfilingSetupStatus(); + const { PageTemplate: ObservabilityPageTemplate } = observabilityShared.navigation; const history = useHistory(); @@ -110,6 +119,32 @@ export function ProfilingAppPageTemplate({ </EuiPanel> </EuiFlexItem> )} + {profilingSetupStatus?.unauthorized === true && privilegesWarningDismissed !== true ? ( + <EuiFlexItem grow={false}> + <EuiCallOut + iconType="warning" + title={i18n.translate('xpack.profiling.privilegesWarningTitle', { + defaultMessage: 'User privilege limitation', + })} + > + <p> + {i18n.translate('xpack.profiling.privilegesWarningDescription', { + defaultMessage: + 'Due to privileges issues we could not check the Universal Profiling status. If you encounter any issues or if data fails to load, please contact your administrator for assistance.', + })} + </p> + <EuiButton + onClick={() => { + setPrivilegesWarningDismissed(true); + }} + > + {i18n.translate('xpack.profiling.dismissPrivilegesCallout', { + defaultMessage: 'Dismiss', + })} + </EuiButton> + </EuiCallOut> + </EuiFlexItem> + ) : null} <EuiFlexItem>{children}</EuiFlexItem> </EuiFlexGroup> </ObservabilityPageTemplate> diff --git a/x-pack/plugins/profiling/public/hooks/use_local_storage.ts b/x-pack/plugins/profiling/public/hooks/use_local_storage.ts new file mode 100644 index 0000000000000..5adbb36432127 --- /dev/null +++ b/x-pack/plugins/profiling/public/hooks/use_local_storage.ts @@ -0,0 +1,57 @@ +/* + * 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 { useState, useEffect, useMemo } from 'react'; + +export function useLocalStorage<T>(key: string, defaultValue: T) { + // This is necessary to fix a race condition issue. + // It guarantees that the latest value will be always returned after the value is updated + const [storageUpdate, setStorageUpdate] = useState(0); + + const item = useMemo(() => { + return getFromStorage(key, defaultValue); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [key, storageUpdate, defaultValue]); + + const saveToStorage = (value: T) => { + if (value === undefined) { + window.localStorage.removeItem(key); + } else { + window.localStorage.setItem(key, JSON.stringify(value)); + setStorageUpdate(storageUpdate + 1); + } + }; + + useEffect(() => { + function onUpdate(event: StorageEvent) { + if (event.key === key) { + setStorageUpdate(storageUpdate + 1); + } + } + window.addEventListener('storage', onUpdate); + return () => { + window.removeEventListener('storage', onUpdate); + }; + }, [key, setStorageUpdate, storageUpdate]); + + return [item, saveToStorage] as const; +} + +function getFromStorage<T>(keyName: string, defaultValue: T) { + const storedItem = window.localStorage.getItem(keyName); + + if (storedItem !== null) { + try { + return JSON.parse(storedItem) as T; + } catch (err) { + window.localStorage.removeItem(keyName); + // eslint-disable-next-line no-console + console.log(`Unable to decode: ${keyName}`); + } + } + return defaultValue; +} diff --git a/x-pack/plugins/profiling/public/routing/index.tsx b/x-pack/plugins/profiling/public/routing/index.tsx index db2a22f357580..9e08cfbc53fec 100644 --- a/x-pack/plugins/profiling/public/routing/index.tsx +++ b/x-pack/plugins/profiling/public/routing/index.tsx @@ -27,6 +27,7 @@ import { AddDataTabs, AddDataView } from '../views/add_data_view'; import { StackTracesView } from '../views/stack_traces_view'; import { StorageExplorerView } from '../views/storage_explorer'; import { RouteBreadcrumb } from './route_breadcrumb'; +import { DeleteDataView } from '../views/delete_data_view'; const routes = { '/': { @@ -62,6 +63,9 @@ const routes = { }, }, }, + '/delete_data_instructions': { + element: <DeleteDataView />, + }, '/': { children: { '/stacktraces/{topNType}': { diff --git a/x-pack/plugins/profiling/public/services.ts b/x-pack/plugins/profiling/public/services.ts index a477d522b3417..1a2a684f96e15 100644 --- a/x-pack/plugins/profiling/public/services.ts +++ b/x-pack/plugins/profiling/public/services.ts @@ -18,6 +18,13 @@ import { TopNResponse } from '../common/topn'; import type { SetupDataCollectionInstructions } from '../server/lib/setup/get_setup_instructions'; import { AutoAbortedHttpService } from './hooks/use_auto_aborted_http_client'; +export interface ProfilingSetupStatus { + has_setup: boolean; + has_data: boolean; + pre_8_9_1_data: boolean; + unauthorized?: boolean; +} + export interface Services { fetchTopN: (params: { http: AutoAbortedHttpService; @@ -40,9 +47,7 @@ export interface Services { timeTo: number; kuery: string; }) => Promise<ElasticFlameGraph>; - fetchHasSetup: (params: { - http: AutoAbortedHttpService; - }) => Promise<{ has_setup: boolean; has_data: boolean }>; + fetchHasSetup: (params: { http: AutoAbortedHttpService }) => Promise<ProfilingSetupStatus>; postSetupResources: (params: { http: AutoAbortedHttpService }) => Promise<void>; setupDataCollectionInstructions: (params: { http: AutoAbortedHttpService; @@ -101,10 +106,7 @@ export function getServices(): Services { return createFlameGraph(baseFlamegraph); }, fetchHasSetup: async ({ http }) => { - const hasSetup = (await http.get(paths.HasSetupESResources, {})) as { - has_setup: boolean; - has_data: boolean; - }; + const hasSetup = (await http.get(paths.HasSetupESResources, {})) as ProfilingSetupStatus; return hasSetup; }, postSetupResources: async ({ http }) => { diff --git a/x-pack/plugins/profiling/public/views/delete_data_view/index.tsx b/x-pack/plugins/profiling/public/views/delete_data_view/index.tsx new file mode 100644 index 0000000000000..7e07ba4a1ec86 --- /dev/null +++ b/x-pack/plugins/profiling/public/views/delete_data_view/index.tsx @@ -0,0 +1,42 @@ +/* + * 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 { EuiCard, EuiIcon, EuiLink } from '@elastic/eui'; +import React from 'react'; +import { useProfilingDependencies } from '../../components/contexts/profiling_dependencies/use_profiling_dependencies'; +import { ProfilingAppPageTemplate } from '../../components/profiling_app_page_template'; + +export function DeleteDataView() { + const { + start: { + core: { docLinks }, + }, + } = useProfilingDependencies(); + + return ( + <ProfilingAppPageTemplate tabs={[]} restrictWidth hideSearchBar> + <div style={{ display: 'flex', flexGrow: 1, justifyContent: 'center', alignItems: 'center' }}> + <EuiCard + style={{ flexGrow: 0, maxWidth: '500px' }} + icon={<EuiIcon color="danger" size="xxl" type="warning" />} + title="You have existing profiling data" + description="To proceed with the Universal Profiling setup, please delete existing profiling data following the steps described in the link below." + footer={ + <div> + <EuiLink + href={`${docLinks.ELASTIC_WEBSITE_URL}/guide/en/observability/${docLinks.DOC_LINK_VERSION}/profiling-upgrade.html#profiling-delete-data`} + target="_blank" + > + Delete existing profiling data + </EuiLink> + </div> + } + /> + </div> + </ProfilingAppPageTemplate> + ); +} diff --git a/x-pack/plugins/profiling/server/lib/setup/cluster_settings.ts b/x-pack/plugins/profiling/server/lib/setup/cluster_settings.ts index 72d84b329ab2d..dde0b33da6291 100644 --- a/x-pack/plugins/profiling/server/lib/setup/cluster_settings.ts +++ b/x-pack/plugins/profiling/server/lib/setup/cluster_settings.ts @@ -42,6 +42,7 @@ export async function validateResourceManagement({ }, resources: { created: statusResponse.resources.created, + pre_8_9_1_data: statusResponse.resources.pre_8_9_1_data, }, }; } diff --git a/x-pack/plugins/profiling/server/routes/setup.ts b/x-pack/plugins/profiling/server/routes/setup.ts index 4e4e2c15b9f66..1ce7d8d056201 100644 --- a/x-pack/plugins/profiling/server/routes/setup.ts +++ b/x-pack/plugins/profiling/server/routes/setup.ts @@ -9,8 +9,7 @@ import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; import { RouteRegisterParameters } from '.'; import { getRoutePaths } from '../../common'; import { - areResourcesSetupForAdmin, - areResourcesSetupForViewer, + areResourcesSetup, createDefaultSetupState, mergePartialSetupStates, } from '../../common/setup'; @@ -88,58 +87,47 @@ export function registerSetupRoute({ }, }); } - - const verifyFunctionsForViewer = [ + const verifyFunctions = [ + validateMaximumBuckets, + validateResourceManagement, + validateSecurityRole, validateCollectorPackagePolicy, validateSymbolizerPackagePolicy, validateProfilingInApmPackagePolicy, ]; - const partialStatesForViewer = await Promise.all([ - ...verifyFunctionsForViewer.map((fn) => fn(setupOptions)), + const partialStates = await Promise.all([ + ...verifyFunctions.map((fn) => fn(setupOptions)), hasProfilingData({ ...setupOptions, client: clientWithProfilingAuth, }), ]); - const mergedStateForViewer = mergePartialSetupStates(state, partialStatesForViewer); - - /* - * We need to split the verification steps - * because of users with viewer privileges - * cannot get the cluster settings - */ - if (areResourcesSetupForViewer(mergedStateForViewer)) { - return response.ok({ - body: { - has_setup: true, - has_data: mergedStateForViewer.data.available, - }, - }); - } - - /** - * Performe advanced verification in case the first step failed. - */ - const verifyFunctionsForAdmin = [ - validateMaximumBuckets, - validateResourceManagement, - validateSecurityRole, - ]; - - const partialStatesForAdmin = await Promise.all( - verifyFunctionsForAdmin.map((fn) => fn(setupOptions)) - ); - const mergedState = mergePartialSetupStates(mergedStateForViewer, partialStatesForAdmin); + const mergedState = mergePartialSetupStates(state, partialStates); return response.ok({ body: { - has_setup: areResourcesSetupForAdmin(mergedState), + has_setup: areResourcesSetup(mergedState), has_data: mergedState.data.available, + pre_8_9_1_data: mergedState.resources.pre_8_9_1_data, }, }); } catch (error) { + // We cannot fully check the status of all resources + // to make sure Profiling has been set up and has data + // for users with monitor privileges. This privileges + // is needed to call the profiling ES plugin for example. + if (error?.meta?.statusCode === 403) { + return response.ok({ + body: { + has_setup: true, + pre_8_9_1_data: false, + has_data: true, + unauthorized: true, + }, + }); + } return handleRouteHandlerError({ error, logger, @@ -192,32 +180,36 @@ export function registerSetupRoute({ const partialStates = await Promise.all( [ - validateCollectorPackagePolicy, - validateMaximumBuckets, validateResourceManagement, validateSecurityRole, + validateMaximumBuckets, + validateCollectorPackagePolicy, validateSymbolizerPackagePolicy, validateProfilingInApmPackagePolicy, ].map((fn) => fn(setupOptions)) ); const mergedState = mergePartialSetupStates(state, partialStates); - const executeFunctions = [ + const executeAdminFunctions = [ + ...(mergedState.resource_management.enabled ? [] : [enableResourceManagement]), + ...(mergedState.permissions.configured ? [] : [setSecurityRole]), + ...(mergedState.settings.configured ? [] : [setMaximumBuckets]), + ]; + + const executeViewerFunctions = [ ...(mergedState.policies.collector.installed ? [] : [createCollectorPackagePolicy]), ...(mergedState.policies.symbolizer.installed ? [] : [createSymbolizerPackagePolicy]), ...(mergedState.policies.apm.profilingEnabled ? [removeProfilingFromApmPackagePolicy] : []), - ...(mergedState.resource_management.enabled ? [] : [enableResourceManagement]), - ...(mergedState.permissions.configured ? [] : [setSecurityRole]), - ...(mergedState.settings.configured ? [] : [setMaximumBuckets]), ]; - if (!executeFunctions.length) { + if (!executeAdminFunctions.length && !executeViewerFunctions.length) { return response.ok(); } - await Promise.all(executeFunctions.map((fn) => fn(setupOptions))); + await Promise.all(executeAdminFunctions.map((fn) => fn(setupOptions))); + await Promise.all(executeViewerFunctions.map((fn) => fn(setupOptions))); if (dependencies.telemetryUsageCounter) { dependencies.telemetryUsageCounter.incrementCounter({